PyLeague 学院

学习
编写
一支能赢球的球队。

这里不需要你把整个引擎背得滚瓜烂熟,而是要理解你的球队所做的三个决策,并不断打磨它们直到赢下比赛。我们带你从一份已经能踢的模板,走到你战胜真正对手的第一场胜利。

从哪里开始

你的路线,从零到参赛

不必从零开始写一支球队。捷径是这样的:从已经能用的东西起步,用方法逐步改进,并衡量每一次改动。

01

复制模板

它已经能有竞争力地比赛:传球、射向球门死角、逼抢无主之球。这是你的起点,而不是一张白纸。

$ cp -r equipos/plantilla equipos/miequipo
02

每次改一处

只改战术,或只改球员。每次只改一处,是唯一能弄清什么变好、什么变坏的办法。

03

用陪练来衡量

在多个 seed 下让它对阵多个对手,观察胜率与数据。这样一场走运的比赛就骗不了你。

$ python sparring.py --team equipos/miequipo
04

参赛

把你的球队上传到平台,在带 ELO 排名的联赛中较量,或自己搭一个。让代码说话。

$ python league.py
你要编写的内容

三个层级,从慢到快

你的球队在三个层面上做决策。关键理念:AI(如果你使用的话)以较慢的节奏设定方案,而一个快速的确定性层每一刻都在执行它。这样模型就永远不必每秒决策 20 次。只定制你感兴趣的层级,其余的直接复用。

10

教练

读取比分与时钟,设定心态:进攻、均衡或防守。决策次数不多,却定下基调。CoachBrain.decide(ctx)

节奏
6

战术

用四个旋钮把球队布置在场上:防线高度、宽度、逼抢与边路。胜负几乎总是在这里决定。TeamStrategy.plan(ctx)

节奏
9

球员

每一刻都做决定:移动、传球、射门、冲刺。快速而灵敏,每名球员各一个。PlayerBrain.decide(view)

每个tick

想了解每个层级接收什么、返回什么的细节?请看参与者指南

战术,无需数学

你的球队,四个旋钮搞定

你不必手动计算站位。你选择四个数值,引擎会把它们转化为每名球员的位置。你可以把它们固定下来,也可以让它们随比赛变化(一套响应式战术)。

line_height · 0.0 → 1.0

防线高度

你的球队站位有多靠前。低 = 收缩且稳固的阵型;高 = 高位逼抢,但会在身后留出空当。

width · 0.0 → 1.0

宽度

球队站位有多开阔。紧凑封住中路;开阔则利用边路,把对手拉扯开。

pressing · 0.0 → 1.0

逼抢

你以多大强度去抢球。注意:目前大量逼抢很耗体力,且不一定能抢到(请阅读下方的「当前打法」)。

focus · left / center / right

进攻边路

你把进攻压向何处。默认走中路;把它压向某一边路,可从那里进攻,或为你的前锋制造插上空当。

真实代码

你的第一套战术,六行搞定

一套固定战术就是一个旋钮字典。一套响应式战术则是一个观察比赛后重新计算这些旋钮的函数。两者都很简短。

mi_tactica.py
# 1) 固定战术:始终如一的风格
from aicup import TacticalStrategy

mi_estilo = TacticalStrategy("Mi estilo", {
    "line_height": 0.35,   # 收缩,稳固
    "width":       0.45,   # 走中路,紧凑
    "pressing":    0.30,   # 等待,不冒进
})

# 2) 响应式战术:随比赛而变
from aicup.tactics import progress, possession

def mandos(ctx):
    defendiendo = possession(ctx) == "theirs" or progress(ctx) < 0.45
    if defendiendo:
        return {"line_height": 0.30, "pressing": 0.35}   # 收缩防守
    return {"line_height": 0.74, "pressing": 0.50}       # 抢断后立即压上

mi_contra = TacticalStrategy("Mi contraataque", mandos)

没有设置的旋钮会使用其默认值。完整的战术库(tiki-taka、catenaccio、gegenpressing……)以及如何编写球员与教练,都在战术文档中。

制胜秘诀

真正拉开差距的东西

这些建议来自数百场比赛的实战。它们不是魔法:而是把有竞争力的球队和凑数的球队区分开来的习惯。

衡量,别靠猜

单场比赛会骗人:运气影响很大。用陪练搭配多个 seed,凭胜率而非感觉来决策。

利用当前打法

目前紧凑而收缩的阵型比高位逼抢更奏效。先把后防做稳,再由此发展。

管理体力

冲刺和大力射门会消耗体力。把冲刺留到最后阶段,并去逼抢已经跑没体力的对手

使用球队的方案

在你的球员中读取 view.plan:它会告诉你该站在哪里、该由谁去抢球。别自己乱来。

射向死角

射向球门中路等于把球送给门将。瞄准立柱并调整力度:并非什么都要用最大力量。

按顺序逐层推进

先做战术(旋钮),再做球员(传球、射门、盯人),最后做教练(何时冒险)。

常见错误

以及如何避免它们

几乎每个人起步时都会在这里栽跟头。提前看清它们,能帮你少输六七场冤枉球。

始终全力逼抢

你指望抢到球,结果只是把自己累垮。解决办法:调低 pressing,只在关键时刻逼抢,而非全程。

四处溜达的门将

GK 远离自己的球门就等于白送进球。解决办法:别让他跑远;看看示例球员是怎么处理的。

防线太高却无保护

你把所有人都压上去,结果被打身后。解决办法:让中场和前锋比后卫压得更靠前,或者降低防线。

对单一对手过度优化

你赢了一个对手,却输给所有人。解决办法:在认定某个方案有效之前,先在多个对手和多个 seed 下衡量。

总用最大力量射门

总用最大力 = 体力耗尽,最后射得更差。解决办法:合理分配 kick_power

会崩溃的代码

引擎会保护你,但一个出错的球员会原地不动,让你白白损失 tick。解决办法:在本地测试并查看播放器。

引擎的「当前打法」

发现什么能赢,本身就是游戏的一部分

关于当前引擎的一个坦诚细节:紧凑防守型战术比高位逼抢表现更好。原因是目前逼抢并不能有效地「抢下」球——控球很「黏」,要抢断得贴得非常近才行。因此类似 catenaccio 的风格往往效果很好,而 gegenpressing 则吃亏。

示例战术是起点,而非最优解。引擎会不断演进(路线图里已考虑让逼抢能够抢下球),因此当前打法也会随之改变。找到此刻能赢的组合,就是你的竞争优势。

参赛之前

你的球队准备好了吗?

过一遍这份快速清单。如果全部打勾,你就可以上传它,与其他人一较高下了。

  • 踢得不出错:撑完整场比赛,没有异常,也没有停住不动的球员。
  • 能赢下模板队:在多个 seed 下都能从基准对手身上拿下比赛。
  • 思路清晰:你清楚它为什么这样站位。
  • 善用体力:不会到最后跑没了体力,也不会白白浪费冲刺。
  • 射门有讲究:瞄准死角并合理分配力度。
  • 用数据衡量过:你用陪练检验过它,而不只是一场比赛。
现在轮到你了

你已经知道怎么做了。
让代码来决定。

创建账户,几分钟即可在线参赛;或克隆项目在本地开发。基础模式无需 API 与任何配置即可运行。