# -*- coding: utf-8 -*-
import pygame,math,random,os
pygame.init()
W,H=800,600
screen=pygame.display.set_mode((W,H))
pygame.display.set_caption("三角洲行动 · 塔防")
clock=pygame.time.Clock()
BT=(11,21,32);BB=(24,47,64);GC=(38,68,88)
PD=(56,44,32);PM=(140,116,82);PL=(172,144,104);Pdot=(198,172,132)
UP2=(30,54,74);UT=(223,240,253);UTD=(130,164,190)
GOLD=(255,208,92);LIV=(255,96,106);MBG=(14,20,28);MAC=(0,255,150)
MP=(22,32,44,200);MB=(0,255,150,100)
TC=[(255,120,80),(110,230,160),(255,200,80),(140,200,255)]
WC=(220,60,60);WXC=(255,110,110);DBC=(60,140,255);DB2=(120,200,255)
L1=[(0,100),(600,100),(600,300),(200,300),(200,500),(800,500)]
L2=[(0,400),(200,400),(200,150),(500,150),(500,350),(800,350)]
L3=[(0,480),(240,480),(240,280),(480,280),(480,100),(800,100)]
L4=[(0,300),(300,300),(300,100),(600,100),(600,450),(800,450)]
L5=[(0,550),(200,550),(200,350),(400,350),(400,150),(650,150),(650,400),(800,400)]
TT=[{"name":"威龙","short":"A","cost":50,"range":100,"damage":35,"cooldown":45,"proj_speed":4.5,"proj_color":(255,160,90),"splash":55},
{"name":"蜂医","short":"S","cost":70,"range":110,"damage":0,"cooldown":90,"proj_speed":0,"proj_color":(110,230,160),"buff_damage":0.5,"buff_speed":0.4,"buff_duration":240},
{"name":"乌鲁鲁","short":"P","cost":100,"range":140,"damage":75,"cooldown":55,"proj_speed":7,"proj_color":(255,220,120),"homing":True},
{"name":"液氮","short":"L","cost":130,"range":120,"damage":14,"cooldown":65,"proj_speed":5,"proj_color":(170,220,255),"multishot":6,"slow":0.35,"slow_duration":100}]
WCFG={"cost":150,"range":180,"damage":30,"cooldown_normal":35,"cooldown_exo":12,"burst_count":3,"burst_interval":6,"exo_interval":3600,"exo_duration":1200}
TRCFG={"cost":120,"hp":200,"attack_range":40,"atk_dmg":8}
LP=[100,200,400,700,1000,1500,1700,1000];UP=[500,1300]
LEVEL_DIFFS=[[0,1,3],[0,1,4],[0,1],[1,2],[1,2]]
DIFF_INFO={0:{"name":"普通","hp":1.0,"speed":1.00,"reward":1.0,"color":(120,200,140)},
 1:{"name":"机密","hp":1.6,"speed":1.15,"reward":1.5,"color":(255,180,60)},
 2:{"name":"绝密","hp":2.5,"speed":1.30,"reward":2.2,"color":(255,70,80)},
 3:{"name":"水淹大坝","hp":2.0,"speed":1.25,"reward":1.8,"color":(70,170,255)},
 4:{"name":"火烧长弓","hp":2.2,"speed":1.20,"reward":2.0,"color":(255,120,40)}}
WAVES=[{"name":"小兵","hp":1.0,"speed":1.0,"color":(200,70,70),"size":12,"reward":15,"shape":"grunt"},
 {"name":"盾兵","hp":2.8,"speed":0.7,"color":(80,140,200),"size":14,"reward":25,"shape":"shield"},
 {"name":"火箭兵","hp":2.0,"speed":1.2,"color":(255,140,60),"size":13,"reward":35,"shape":"rocket"},
 {"name":"喷火兵","hp":2.5,"speed":1.1,"color":(255,180,40),"size":13,"reward":45,"shape":"flame"},
 {"name":"机枪兵","hp":3.5,"speed":0.95,"color":(180,60,180),"size":15,"reward":60,"shape":"mg"}]
WAVE_COMPS=[[(0,15)],[(0,15),(1,5)],[(0,15),(1,5),(2,5)],[(0,15),(1,5),(2,5),(3,5)],[(0,15),(1,5),(2,5),(3,5),(4,5)]]
def get_wave_list(wi):
    lst=[]
    for k,c in WAVE_COMPS[wi]:lst.extend([k]*c)
    return lst
def lf(s,b=False):
    for p in ["C:/Windows/Fonts/msyh.ttc","C:/Windows/Fonts/msyhbd.ttc","C:/Windows/Fonts/simhei.ttf","C:/Windows/Fonts/simsun.ttc","C:/Windows/Fonts/arial.ttf","/System/Library/Fonts/PingFang.ttc","/System/Library/Fonts/STHeiti Medium.ttc","/usr/share/fonts/truetype/wqy/wqy-microhei.ttc","/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"]:
        if os.path.exists(p):
            try:
                f=pygame.font.Font(p,s)
                if b:f.set_bold(True)
                return f
            except Exception:pass
    f=pygame.font.Font(None,s)
    if b:f.set_bold(True)
    return f
ft=lf(12,True);fs=lf(14,True);fm=lf(18,True);fb=lf(28,True);fh=lf(56,True)
fmt=lf(36,True);fmb=lf(22,True);fS1=lf(180,True);fdg=lf(32,True)
game_state="MENU";cur_lvl=0
difficulty=0;pending_level=0
lives=10;gold=240
enemies=[];towers=[];projs=[];fts=[];parts=[]
nid=1;spc=0;SPI=25;sel=0;st=pygame.time.get_ticks()
wolf=None;trav=None;go=False
ESS=0.45;PSS=0.85
tickets=0;lott=0;has_skin=False;ucnt=0;has_uru=False
wave_idx=0;wave_spawned=0;wave_clear_timer=0;wave_banner_timer=0;wave_banner_text=""
cur_wave_list=get_wave_list(0)
_gc={};_rc={}
def gs(r,c,a=110):
    k=(r,c,a);s=_gc.get(k)
    if s is None:
        n=40;sm=pygame.Surface((n,n),pygame.SRCALPHA);cc=(n-1)/2.0
        for yy in range(n):
            for xx in range(n):
                d=math.hypot(xx-cc,yy-cc)/cc
                if d>1:continue
                aa=int(a*(1-d)**2)
                if aa>0:sm.set_at((xx,yy),(c[0],c[1],c[2],aa))
        s=pygame.transform.smoothscale(sm,(r*2,r*2));_gc[k]=s
    return s
def rs(r,c):
    k=(r,c);s=_rc.get(k)
    if s is None:
        s=pygame.Surface((r*2,r*2),pygame.SRCALPHA)
        pygame.draw.circle(s,(c[0],c[1],c[2],26),(r,r),r)
        pygame.draw.circle(s,(c[0],c[1],c[2],100),(r,r),r,2);_rc[k]=s
    return s
def dist(x1,y1,x2,y2):return math.hypot(x1-x2,y1-y2)
def al(a,b,t):
    d=(b-a+math.pi)%(2*math.pi)-math.pi;return a+d*t
def get_wps():return [L1,L2,L3,L4,L5][cur_lvl]
def near_path(x,y):
    wps=get_wps()
    for i in range(len(wps)-1):
        p1,p2=wps[i],wps[i+1]
        sg=(p2[0]-p1[0])**2+(p2[1]-p1[1])**2
        if sg==0:continue
        t=((x-p1[0])*(p2[0]-p1[0])+(y-p1[1])*(p2[1]-p1[1]))/sg
        t=max(0,min(1,t))
        px=p1[0]+t*(p2[0]-p1[0]);py=p1[1]+t*(p2[1]-p1[1])
        if dist(x,y,px,py)<38:return True
    return False
def can_place(x,y):
    if x<26 or x>W-26 or y<58 or y>528:return False
    if sel!=5:
        if near_path(x,y):return False
    for t in towers:
        if dist(x,y,t["x"],t["y"])<46:return False
    if wolf and dist(x,y,wolf["x"],wolf["y"])<52:return False
    if trav and dist(x,y,trav["x"],trav["y"])<52:return False
    return True
def sp_parts(x,y,c,n=8,sp=3,lf_=30,sz=3):
    for _ in range(n):
        a=random.random()*math.tau;v=random.uniform(sp*0.3,sp)
        parts.append({"x":x,"y":y,"vx":math.cos(a)*v,"vy":math.sin(a)*v,"life":lf_,"max_life":lf_,"color":c,"size":random.uniform(sz*0.5,sz)})
    if len(parts)>400:del parts[:len(parts)-400]
def upd_parts():
    for p in parts[:]:
        p["x"]+=p["vx"];p["y"]+=p["vy"];p["vx"]*=0.93;p["vy"]*=0.93;p["vy"]+=0.05;p["life"]-=1
        if p["life"]<=0:parts.remove(p)
def draw_parts():
    for p in parts:
        t=p["life"]/p["max_life"];r=max(1,int(p["size"]*(0.3+0.7*t)))
        c=(int(BB[0]+(p["color"][0]-BB[0])*t),int(BB[1]+(p["color"][1]-BB[1])*t),int(BB[2]+(p["color"][2]-BB[2])*t))
        pygame.draw.circle(screen,c,(int(p["x"]),int(p["y"])),r)
def add_ft(x,y,txt,c):
    fts.append({"x":x,"y":y,"text":txt,"color":c,"life":55,"max_life":55,"vy":-1.05})
    if len(fts)>60:del fts[:len(fts)-60]
def upd_ft():
    for f in fts[:]:
        f["y"]+=f["vy"];f["vy"]*=0.97;f["life"]-=1
        if f["life"]<=0:fts.remove(f)
def draw_ft():
    for f in fts:
        t=f["life"]/f["max_life"];a=int(255*min(1,t*2))
        img=fs.render(f["text"],True,f["color"]);img.set_alpha(a)
        sh=fs.render(f["text"],True,(0,0,0));sh.set_alpha(a//2)
        screen.blit(sh,(f["x"]-img.get_width()//2+1,f["y"]-img.get_height()//2+1))
        screen.blit(img,(f["x"]-img.get_width()//2,f["y"]-img.get_height()//2))
def gr_bg():
    s=pygame.Surface((W,H)).convert()
    for y in range(H):
        t=y/(H-1)
        c=(int(BT[0]+(BB[0]-BT[0])*t),int(BT[1]+(BB[1]-BT[1])*t),int(BT[2]+(BB[2]-BT[2])*t))
        pygame.draw.line(s,c,(0,y),(W,y))
    return s
def grid(s):
    for x in range(0,W,40):
        a=22 if x%200==0 else 12
        t=pygame.Surface((1,H),pygame.SRCALPHA);t.fill((GC[0],GC[1],GC[2],a));s.blit(t,(x,0))
    for y in range(0,H,40):
        a=22 if y%200==0 else 12
        t=pygame.Surface((W,1),pygame.SRCALPHA);t.fill((GC[0],GC[1],GC[2],a));s.blit(t,(0,y))
def draw_dam(s):
    lake=pygame.Rect(625,58,165,92);pygame.draw.rect(s,(20,40,62),lake,border_radius=8)
    for i in range(6):
        wy=lake.y+16+i*14
        if wy<lake.bottom-6:
            off=(i%2)*14
            pygame.draw.line(s,(38,68,96),(lake.x+10+off,wy),(lake.right-10-off,wy),1)
    pygame.draw.rect(s,(58,90,118),lake,width=1,border_radius=8)
    dam=pygame.Rect(618,184,178,42)
    pygame.draw.rect(s,(15,20,28),(dam.x,dam.y+5,dam.w,dam.h));pygame.draw.rect(s,(58,62,72),dam)
    pygame.draw.rect(s,(92,96,108),(dam.x,dam.y,dam.w,10));pygame.draw.rect(s,(34,38,46),(dam.x,dam.bottom-8,dam.w,8))
    for i in range(4):
        gx=dam.x+14+i*42;gy=dam.y+14
        pygame.draw.rect(s,(40,42,50),(gx,gy,26,20));pygame.draw.rect(s,(100,104,116),(gx,gy,26,3))
        pygame.draw.circle(s,(130,145,160),(gx+13,gy+12),2)
        for k in range(3):pygame.draw.line(s,(55,100,145),(gx+5+k*8,dam.bottom),(gx+5+k*8,dam.bottom+10-k*2),2)
    fl=pygame.Rect(630,226,154,26);pygame.draw.rect(s,(28,60,95),fl,border_radius=4)
    pygame.draw.rect(s,(55,105,155),fl,width=1,border_radius=4)
    for i in range(6):
        fx=fl.x+12+i*26;pygame.draw.line(s,(70,130,180),(fx,fl.y+5),(fx,fl.bottom-5),2)
    l=ft.render("◆ 零号大坝",True,(120,180,220));s.blit(l,(dam.centerx-l.get_width()//2,dam.y-22))
def draw_radar(s):
    pn=pygame.Rect(630,55,150,120);pygame.draw.rect(s,(22,38,48),pn,border_radius=8)
    pygame.draw.rect(s,(68,110,130),pn,width=1,border_radius=8)
    bs=pygame.Rect(pn.x+20,pn.bottom-30,110,20);pygame.draw.rect(s,(45,55,65),bs,border_radius=3)
    pygame.draw.rect(s,(90,105,120),bs,width=1,border_radius=3)
    cx=pn.centerx;ty=pn.y+34;by=bs.y
    pygame.draw.polygon(s,(75,88,100),[(cx-20,by),(cx-7,ty+15),(cx+7,ty+15),(cx+20,by)])
    pygame.draw.line(s,(55,68,80),(cx-20,by),(cx+7,ty+15),1)
    pygame.draw.line(s,(55,68,80),(cx+20,by),(cx-7,ty+15),1)
    pygame.draw.line(s,(90,100,115),(cx-15,by-15),(cx+15,by-15),1)
    pygame.draw.line(s,(90,100,115),(cx-10,by-30),(cx+10,by-30),1)
    pygame.draw.ellipse(s,(50,65,80),(cx-30,ty-10,60,20))
    pygame.draw.ellipse(s,(140,165,185),(cx-28,ty-8,56,16))
    pygame.draw.circle(s,(200,220,240),(cx,ty),4);pygame.draw.circle(s,(100,130,150),(cx,ty),4,1)
    pygame.draw.line(s,(180,200,220),(cx,ty),(cx+12,ty-10),2);pygame.draw.circle(s,(200,230,250),(cx+12,ty-10),3)
    for i in range(3):
        r=20+i*10;a=160-i*45;t=pygame.Surface((r*2,r*2),pygame.SRCALPHA)
        pygame.draw.arc(t,(0,255,150,a),(0,0,r*2,r*2),-math.pi*0.75,-math.pi*0.25,2)
        s.blit(t,(cx-r,ty-r))
    l=ft.render("◉ 雷达站",True,(120,220,180));s.blit(l,(pn.centerx-l.get_width()//2,pn.y-18))
def draw_sarc(s):
    sh=pygame.Surface((200,30),pygame.SRCALPHA);pygame.draw.ellipse(sh,(0,0,0,80),(0,0,200,30));s.blit(sh,(610,245))
    cx=710
    ou=[(630,250),(640,160),(665,110),(710,88),(755,110),(780,160),(790,250)]
    pygame.draw.polygon(s,(72,76,82),ou);pygame.draw.polygon(s,(110,116,124),ou,2)
    pygame.draw.lines(s,(150,158,168),False,[(665,110),(710,88),(755,110)],2)
    for y in range(120,250,20):
        t=(y-88)/162.0;w=42+t*100;pygame.draw.line(s,(88,93,100),(int(cx-w),y),(int(cx+w),y),1)
    for y in [145,205]:
        t=(y-88)/162.0;w=42+t*100;pygame.draw.line(s,(180,42,42),(int(cx-w),y),(int(cx+w),y),3)
    rx,ry=710,175
    for i in range(3):
        a=-math.pi/2+i*2*math.pi/3;ex=rx+math.cos(a)*12;ey=ry+math.sin(a)*12
        pygame.draw.line(s,(240,200,50),(rx,ry),(int(ex),int(ey)),5)
    pygame.draw.circle(s,(240,200,50),(rx,ry),4);pygame.draw.circle(s,(30,30,30),(rx,ry),12,1)
    l=ft.render("☢ 切尔诺贝利石棺",True,(240,200,50));s.blit(l,(cx-l.get_width()//2,62))
def draw_babel(s):
    cx,cy=710,170
    sh=pygame.Surface((160,24),pygame.SRCALPHA);pygame.draw.ellipse(sh,(0,0,0,90),(0,0,160,24));s.blit(sh,(cx-80,cy+50))
    for i in range(7):
        w=60-i*7;y=cy+40-i*22
        pygame.draw.rect(s,(120-i*8,110-i*8,90-i*6),(cx-w,y-18,w*2,18))
        pygame.draw.rect(s,(180,160,120),(cx-w,y-18,w*2,3))
    pygame.draw.polygon(s,(200,180,140),[(cx-18,cy-134),(cx,cy-160),(cx+18,cy-134)])
    pygame.draw.circle(s,(255,220,120),(cx,cy-158),4)
    for i in range(6):
        y=cy-120+i*22
        for dx in (-14,0,14):pygame.draw.rect(s,(255,240,180),(cx+dx-2,y,4,4))
    l=ft.render("▲ 巴别塔",True,(255,220,140));s.blit(l,(cx-l.get_width()//2,cy-190))
def draw_space(s):
    cx,cy=700,180
    sh=pygame.Surface((180,24),pygame.SRCALPHA);pygame.draw.ellipse(sh,(0,0,0,90),(0,0,180,24));s.blit(sh,(cx-90,cy+62))
    pygame.draw.rect(s,(70,75,82),(cx-55,cy+12,110,50));pygame.draw.rect(s,(100,105,115),(cx-55,cy+12,110,4))
    pygame.draw.line(s,(90,95,105),(cx-45,cy+12),(cx-32,cy-48),4)
    pygame.draw.line(s,(90,95,105),(cx+45,cy+12),(cx+32,cy-48),4)
    pygame.draw.rect(s,(220,220,225),(cx-16,cy-58,32,92),border_radius=8)
    pygame.draw.rect(s,(245,245,250),(cx-16,cy-58,10,92),border_radius=8)
    pygame.draw.polygon(s,(220,50,50),[(cx-16,cy-58),(cx+16,cy-58),(cx,cy-92)])
    pygame.draw.circle(s,(120,200,240),(cx,cy-28),6);pygame.draw.circle(s,(200,240,255),(cx,cy-28),4)
    pygame.draw.polygon(s,(180,40,40),[(cx-16,cy+34),(cx-16,cy+12),(cx-30,cy+36)])
    pygame.draw.polygon(s,(180,40,40),[(cx+16,cy+34),(cx+16,cy+12),(cx+30,cy+36)])
    for i in range(3):
        px=cx-14+i*14
        pygame.draw.polygon(s,(255,180,50),[(px,cy+34),(px+10,cy+34),(px+5,cy+52)])
        pygame.draw.polygon(s,(255,90,30),[(px+3,cy+34),(px+7,cy+34),(px+5,cy+46)])
    l=ft.render("▲ 火箭发射站",True,(255,200,120));s.blit(l,(cx-l.get_width()//2,cy-116))
    for i in range(2):
        px=600+i*120;p1=pygame.Rect(px,478,90,16)
        pygame.draw.rect(s,(210,170,30),p1,border_radius=5)
        pygame.draw.rect(s,(255,220,80),p1,width=1,border_radius=5)
        pygame.draw.line(s,(160,120,10),(p1.x,p1.y+4),(p1.right,p1.y+4),2)
        pygame.draw.rect(s,(120,100,40),(p1.x-6,p1.y-4,10,24),border_radius=3)
        pygame.draw.rect(s,(120,100,40),(p1.right-4,p1.y-4,10,24),border_radius=3)
    lp=ft.render("◆ 液氧管道",True,(255,220,80));s.blit(lp,(660-lp.get_width()//2,458))
def draw_path(s,wps):
    pygame.draw.lines(s,(16,22,30),False,wps,72)
    for p in wps:pygame.draw.circle(s,(16,22,30),p,36)
    pygame.draw.lines(s,PD,False,wps,62)
    for p in wps:pygame.draw.circle(s,PD,p,31)
    pygame.draw.lines(s,PM,False,wps,52)
    for p in wps:pygame.draw.circle(s,PM,p,26)
    pygame.draw.lines(s,PL,False,wps,42)
    for p in wps:pygame.draw.circle(s,PL,p,21)
    for i in range(len(wps)-1):
        p1,p2=wps[i],wps[i+1];sl=dist(p1[0],p1[1],p2[0],p2[1])
        if sl<1:continue
        n=max(1,int(sl/34))
        for k in range(n):
            t=(k+0.5)/n;x=p1[0]+(p2[0]-p1[0])*t;y=p1[1]+(p2[1]-p1[1])*t
            pygame.draw.circle(s,Pdot,(int(x),int(y)),2)
    sx,sy=wps[0];pygame.draw.circle(s,(90,160,200),(int(sx),int(sy)),10,2)
    ex,ey=wps[-1];pygame.draw.circle(s,(200,90,90),(int(ex),int(ey)),10,2)
def vgn():
    sm=pygame.Surface((48,36),pygame.SRCALPHA)
    for y in range(36):
        for x in range(48):
            nx=(x/47)*2-1;ny=(y/35)*2-1;d=min(1,math.hypot(nx,ny*0.9));a=int(115*(d**2.6))
            if a>0:sm.set_at((x,y),(0,0,0,a))
    return pygame.transform.smoothscale(sm,(W,H))
SB=[None,None,None,None,None]
def build_static():
    global SB
    for i,(fn,wps) in enumerate([(draw_dam,L1),(draw_radar,L2),(draw_sarc,L3),(draw_babel,L4),(draw_space,L5)]):
        s=gr_bg();grid(s);fn(s);draw_path(s,wps);s.blit(vgn(),(0,0));SB[i]=s
def sp_enemy():
    global nid,wave_spawned
    if wave_idx>=len(WAVES):return
    if wave_spawned>=len(cur_wave_list):return
    kind=cur_wave_list[wave_spawned];w=WAVES[kind]
    wps=get_wps();el=(pygame.time.get_ticks()-st)/1000
    d=DIFF_INFO[difficulty]
    base_hp=45+int(el//12)*14
    hp=int(min(280,base_hp)*w["hp"]*d["hp"])
    spd=(0.42+random.random()*0.18)*w["speed"]*d["speed"]
    rw=int(w["reward"]*d["reward"])
    enemies.append({"id":nid,"x":wps[0][0],"y":wps[0][1],"progress":0,"hp":hp,"max_hp":hp,"base_speed":spd,"slow_factor":1,"slow_timer":0,"reward":rw,"color":w["color"],"flash":0,"dead":False,"phase":random.random()*math.tau,"shape":w["shape"],"size":w["size"]})
    nid+=1;wave_spawned+=1
def dmg_e(e,dmg,c=(255,240,200)):
    if e.get("dead"):return
    dmg=int(dmg)
    if dmg<=0:return
    e["hp"]-=dmg;e["flash"]=8
    add_ft(e["x"]+random.uniform(-6,6),e["y"]-18,str(dmg),c)
    if e["hp"]<=0:e["hp"]=0;e["dead"]=True
def upd_enemies():
    global lives,go,gold,wave_idx,wave_clear_timer,wave_banner_timer,wave_banner_text,wave_spawned,spc,cur_wave_list,trav
    wps=get_wps()
    for e in enemies[:]:
        if e.get("dead"):
            gold+=e["reward"];sp_parts(e["x"],e["y"],e["color"],12,3.5,34,4)
            add_ft(e["x"],e["y"]-26,"+"+str(e["reward"]),GOLD);enemies.remove(e);continue
        if e["flash"]>0:e["flash"]-=1
        if e["slow_timer"]>0:e["slow_timer"]-=1
        else:e["slow_factor"]=1
        if trav is not None:
            dt=dist(e["x"],e["y"],trav["x"],trav["y"])
            if dt<TRCFG["attack_range"]:
                trav["hp"]-=TRCFG["atk_dmg"]
                if trav["hp"]<=0:
                    sp_parts(trav["x"],trav["y"],DBC,20,4,40,5)
                    add_ft(trav["x"],trav["y"]-30,"深蓝被摧毁",(255,100,100))
                    trav=None
                continue
        sp=e["base_speed"]*e["slow_factor"]*ESS
        e["progress"]+=sp*0.01
        if e["progress"]>=1:
            lives-=1
            if lives<=0:lives=0;go=True
            enemies.remove(e)
            continue
        p=min(e["progress"],1);sc=len(wps)-1;si=min(int(p*sc),sc-1);spg=p*sc-si
        p1=wps[si];p2=wps[si+1]
        e["x"]=p1[0]+(p2[0]-p1[0])*spg;e["y"]=p1[1]+(p2[1]-p1[1])*spg
    if wave_banner_timer>0:wave_banner_timer-=1
    if wave_idx<len(WAVES):
        if wave_spawned>=len(cur_wave_list) and len(enemies)==0:
            wave_clear_timer+=1
            if wave_clear_timer>=90:
                wave_idx+=1;wave_spawned=0;wave_clear_timer=0;spc=0
                if wave_idx<len(WAVES):
                    cur_wave_list=get_wave_list(wave_idx)
                    wave_banner_text=f"第 {wave_idx+1} 波 · 共 {len(cur_wave_list)} 敌人"
                    wave_banner_timer=120
                else:
                    wave_banner_text="全部波次通关！"
                    wave_banner_timer=180
        else:wave_clear_timer=0
def draw_enemies():
    for e in enemies:
        x,y=int(e["x"]),int(e["y"]);hr=e["hp"]/e["max_hp"]
        sz=e.get("size",12);shp=e.get("shape","grunt")
        sh=pygame.Surface((sz*2+6,sz+4),pygame.SRCALPHA)
        pygame.draw.ellipse(sh,(0,0,0,90),(0,0,sz*2+6,sz+4));screen.blit(sh,(x-sz-3,y+sz-2))
        if e["slow_factor"]<1:
            g=gs(sz+10,(140,200,255),70);screen.blit(g,(x-sz-10,y-sz-10))
        wb=math.sin(e["phase"]+pygame.time.get_ticks()*0.008)*2
        bc=(255,200,200) if e["flash"]>0 else e["color"]
        pygame.draw.circle(screen,(30,18,24),(x,y+2),sz+1)
        pygame.draw.circle(screen,bc,(x,int(y+wb)),sz)
        pygame.draw.circle(screen,tuple(min(255,c+50) for c in bc),(x-sz//4,int(y+wb)-sz//3),sz//2)
        if shp=="shield":
            pygame.draw.arc(screen,(220,220,230),(x-2,y-sz-2,sz*2+4,sz*2+4),-math.pi*0.6,math.pi*0.6,4)
            pygame.draw.line(screen,(180,180,190),(x,y-sz),(x,y+sz),2)
        elif shp=="rocket":
            pygame.draw.line(screen,(60,60,60),(x+sz-2,y-sz+2),(x+sz+10,y-sz-8),4)
            pygame.draw.circle(screen,(180,80,40),(x+sz+10,y-sz-8),3)
        elif shp=="flame":
            pygame.draw.line(screen,(80,60,40),(x+sz-2,y+2),(x+sz+10,y+2),4)
            pygame.draw.circle(screen,(255,120,40),(x+sz+11,y+2),3)
            pygame.draw.circle(screen,(255,220,100),(x+sz+11,y+2),1)
        elif shp=="mg":
            pygame.draw.line(screen,(50,50,50),(x+sz-2,y-4),(x+sz+10,y-4),3)
            pygame.draw.line(screen,(50,50,50),(x+sz-2,y+4),(x+sz+10,y+4),3)
            pygame.draw.line(screen,(70,70,70),(x+sz+8,y-6),(x+sz+8,y+6),2)
        pygame.draw.circle(screen,(255,255,255),(x-sz//3,int(y+wb)-2),2)
        pygame.draw.circle(screen,(20,20,30),(x-sz//3,int(y+wb)-2),1)
        bw=sz*2+2;bx=x-bw//2;by=y-sz-12
        pygame.draw.rect(screen,(18,28,38),(bx-1,by-1,bw+2,6),border_radius=3)
        col=(90,220,120) if hr>0.5 else ((255,200,80) if hr>0.25 else (240,80,80))
        pygame.draw.rect(screen,col,(bx,by,int(bw*hr),4),border_radius=2)
def sum_wolf(x,y):
    global gold,wolf
    if wolf is not None or gold<WCFG["cost"]:return False
    if not can_place(x,y):return False
    gold-=WCFG["cost"]
    wolf={"x":x,"y":y,"cooldown":0,"burst_counter":0,"burst_delay":0,"angle":-math.pi/2,"exo_active":False,"exo_timer":0,"exo_charge":0,"recoil":0}
    add_ft(x,y-40,"红狼登场!",WC);sp_parts(x,y,WC,18,4,40,4);return True
def upd_wolf():
    global wolf
    if wolf is None:return
    if wolf["exo_active"]:
        wolf["exo_timer"]-=1
        if wolf["exo_timer"]<=0:
            wolf["exo_active"]=False;wolf["exo_timer"]=0;add_ft(wolf["x"],wolf["y"]-40,"外骨骼关闭",(200,200,200))
    else:
        wolf["exo_charge"]+=1
        if wolf["exo_charge"]>=WCFG["exo_interval"]:
            wolf["exo_active"]=True;wolf["exo_timer"]=WCFG["exo_duration"];wolf["exo_charge"]=0
            add_ft(wolf["x"],wolf["y"]-40,"外骨骼启动!",WXC);sp_parts(wolf["x"],wolf["y"],WXC,20,4,40,4)
    if wolf["recoil"]>0:wolf["recoil"]-=0.08
    if wolf["burst_counter"]>0:
        wolf["burst_delay"]-=1
        if wolf["burst_delay"]<=0:fire_wolf();wolf["burst_counter"]-=1;wolf["burst_delay"]=WCFG["burst_interval"]
    else:
        if wolf["cooldown"]>0:wolf["cooldown"]-=1
        else:
            tg=None;b=-1
            for e in enemies:
                d=dist(wolf["x"],wolf["y"],e["x"],e["y"])
                if d<=WCFG["range"] and e["progress"]>b:b=e["progress"];tg=e
            if tg:
                wolf["burst_counter"]=WCFG["burst_count"];wolf["burst_delay"]=0
                wolf["angle"]=math.atan2(tg["y"]-wolf["y"],tg["x"]-wolf["x"])
                wolf["cooldown"]=WCFG["cooldown_exo"] if wolf["exo_active"] else WCFG["cooldown_normal"]
def fire_wolf():
    if wolf is None:return
    tg=None;b=-1
    for e in enemies:
        d=dist(wolf["x"],wolf["y"],e["x"],e["y"])
        if d<=WCFG["range"] and e["progress"]>b:b=e["progress"];tg=e
    if not tg:return
    ang=math.atan2(tg["y"]-wolf["y"],tg["x"]-wolf["x"])
    col=WXC if wolf["exo_active"] else WC
    wolf["recoil"]=1
    projs.append({"x":wolf["x"],"y":wolf["y"],"vx":math.cos(ang)*8*PSS,"vy":math.sin(ang)*8*PSS,"speed":8*PSS,"angle":ang,"damage":WCFG["damage"],"type":"wolf","color":col,"life":200,"splash":0,"radius":5,"slow":0,"slow_duration":0,"homing":False,"target_id":None,"trail":[]})
def draw_wolf():
    if wolf is None:return
    x,y=int(wolf["x"]),int(wolf["y"])
    col=WXC if wolf["exo_active"] else WC
    g=gs(38,col,90);screen.blit(g,(x-38,y-38))
    sh=pygame.Surface((44,18),pygame.SRCALPHA);pygame.draw.ellipse(sh,(0,0,0,100),(0,0,44,18));screen.blit(sh,(x-22,y+10))
    pygame.draw.circle(screen,(18,30,42),(x,y+2),25);pygame.draw.circle(screen,(40,60,80),(x,y),24)
    pygame.draw.circle(screen,col,(x,y),18);pygame.draw.circle(screen,tuple(min(255,c+60) for c in col),(x-4,y-5),10)
    ro=int(wolf["recoil"]*4);ang=wolf["angle"]
    tt=pygame.Surface((60,60),pygame.SRCALPHA);cx=cy=30
    pygame.draw.rect(tt,(30,48,66),(cx,cy-7,30-ro,14),border_radius=5);pygame.draw.rect(tt,col,(cx,cy-4,28-ro,8),border_radius=4)
    pygame.draw.circle(tt,(20,34,50),(cx+27-ro,cy),6)
    rot=pygame.transform.rotate(tt,-math.degrees(ang));screen.blit(rot,rot.get_rect(center=(x,y)))
    if not wolf["exo_active"]:
        r=wolf["exo_charge"]/WCFG["exo_interval"]
        if r>0.05:pygame.draw.arc(screen,(255,140,140),(x-30,y-30,60,60),-math.pi/2,-math.pi/2+r*math.tau,3)
def sum_trav(x,y):
    global gold,trav
    if trav is not None or gold<TRCFG["cost"]:return False
    if not can_place(x,y):return False
    gold-=TRCFG["cost"]
    trav={"x":x,"y":y,"hp":TRCFG["hp"],"max_hp":TRCFG["hp"],"pulse":0}
    add_ft(x,y-40,"深蓝部署!",DBC);sp_parts(x,y,DBC,18,4,40,4);return True
def upd_trav():
    if trav is None:return
    trav["pulse"]=(trav["pulse"]+0.05)%math.tau
def draw_trav():
    if trav is None:return
    x,y=int(trav["x"]),int(trav["y"])
    g=gs(40,DBC,100);screen.blit(g,(x-40,y-40))
    sh=pygame.Surface((50,20),pygame.SRCALPHA);pygame.draw.ellipse(sh,(0,0,0,100),(0,0,50,20));screen.blit(sh,(x-25,y+10))
    pygame.draw.circle(screen,(18,30,42),(x,y+2),24)
    pygame.draw.circle(screen,(40,60,90),(x,y),22)
    pts=[]
    for i in range(8):
        a=-math.pi/2+i*math.tau/8
        pts.append((x+math.cos(a)*16,y+math.sin(a)*16))
    pygame.draw.polygon(screen,DBC,pts)
    pygame.draw.polygon(screen,DB2,pts,2)
    pygame.draw.line(screen,(200,240,255),(x,y-9),(x,y+9),3)
    pygame.draw.line(screen,(200,240,255),(x-9,y),(x+9,y),3)
    pygame.draw.circle(screen,(255,255,255),(x,y),4)
    pr=int(40+math.sin(trav["pulse"])*8)
    s=pygame.Surface((pr*2,pr*2),pygame.SRCALPHA)
    pygame.draw.circle(s,(120,200,255,80),(pr,pr),pr,2)
    screen.blit(s,(x-pr,y-pr))
    hr=trav["hp"]/trav["max_hp"]
    bw=44;bx=x-bw//2;by=y-34
    pygame.draw.rect(screen,(18,28,38),(bx-1,by-1,bw+2,6),border_radius=3)
    col=(60,200,255) if hr>0.5 else ((255,200,80) if hr>0.25 else (240,80,80))
    pygame.draw.rect(screen,col,(bx,by,int(bw*hr),4),border_radius=2)
def mk_tower(k,x,y):return{"type":k,"x":x,"y":y,"cooldown":0,"angle":-math.pi/2,"damage_mult":1,"speed_mult":1,"buff_timer":0,"pulse":0,"recoil":0,"spawn_anim":1}
def mk_proj(x,y,ang,sp,dmg,k,c,splash=0,r=5):return{"x":x,"y":y,"vx":math.cos(ang)*sp,"vy":math.sin(ang)*sp,"speed":sp,"angle":ang,"damage":dmg,"type":k,"color":c,"life":220,"splash":splash,"radius":r,"slow":0,"slow_duration":0,"homing":False,"target_id":None,"trail":[]}
def splash(x,y,r,dmg,c,slow=0,sd=0):
    for e in enemies:
        if e.get("dead"):continue
        d=dist(x,y,e["x"],e["y"])
        if d<=r:
            f=1-0.45*(d/r);dmg_e(e,dmg*f,c)
            if slow and e["hp"]>0:e["slow_factor"]=slow;e["slow_timer"]=max(e["slow_timer"],sd)
    sp_parts(x,y,c,14,4,28,5)
def fire_tower(t,cfg,tg):
    c=cfg["proj_color"]
    if t["type"]==2 and has_uru:c=(255,140,60)
    dmg=cfg["damage"]*t["damage_mult"]
    ang=math.atan2(tg["y"]-t["y"],tg["x"]-t["x"])
    if t["type"]==0:projs.append(mk_proj(t["x"],t["y"],ang,cfg["proj_speed"],dmg,"bomb",c,splash=cfg["splash"],r=6))
    elif t["type"]==2:
        p=mk_proj(t["x"],t["y"],ang,cfg["proj_speed"],dmg,"missile",c,r=5);p["homing"]=True;p["target_id"]=tg["id"];projs.append(p)
    elif t["type"]==3:
        n=cfg["multishot"]
        for i in range(n):
            a=ang+(i-(n-1)/2)*0.16
            p=mk_proj(t["x"],t["y"],a,cfg["proj_speed"],dmg,"ice",c,r=4);p["slow"]=cfg["slow"];p["slow_duration"]=cfg["slow_duration"];projs.append(p)
def upd_towers():
    for t in towers:
        t["pulse"]=max(0,t["pulse"]-0.04);t["recoil"]=max(0,t["recoil"]-0.09);t["spawn_anim"]=max(0,t["spawn_anim"]-0.06)
        if t["buff_timer"]>0:
            t["buff_timer"]-=1
            if t["buff_timer"]<=0:t["damage_mult"]=1;t["speed_mult"]=1
        cfg=TT[t["type"]]
        if t["type"]==1:
            t["cooldown"]-=1
            if t["cooldown"]<=0:
                t["cooldown"]=cfg["cooldown"];ab=False
                for o in towers:
                    if o is t:continue
                    if dist(t["x"],t["y"],o["x"],o["y"])<=cfg["range"]:
                        o["damage_mult"]=1+cfg["buff_damage"];o["speed_mult"]=1+cfg["buff_speed"];o["buff_timer"]=cfg["buff_duration"];ab=True
                if ab:t["pulse"]=1;sp_parts(t["x"],t["y"],(110,230,160),10,2.5,30,3)
            continue
        t["cooldown"]-=1
        if t["cooldown"]>0:continue
        tg=None;b=-1
        for e in enemies:
            d=dist(t["x"],t["y"],e["x"],e["y"])
            if d<=cfg["range"] and e["progress"]>b:b=e["progress"];tg=e
        if tg is None:continue
        t["angle"]=math.atan2(tg["y"]-t["y"],tg["x"]-t["x"])
        t["cooldown"]=cfg["cooldown"]/max(0.5,t["speed_mult"]);t["recoil"]=1;fire_tower(t,cfg,tg)
def upd_projs():
    for p in projs[:]:
        if p["homing"] and p["target_id"] is not None:
            tg=None
            for e in enemies:
                if e["id"]==p["target_id"] and not e.get("dead"):tg=e;break
            if tg:
                des=math.atan2(tg["y"]-p["y"],tg["x"]-p["x"]);p["angle"]=al(p["angle"],des,0.20)
                p["vx"]=math.cos(p["angle"])*p["speed"];p["vy"]=math.sin(p["angle"])*p["speed"]
            else:p["homing"]=False
        p["x"]+=p["vx"];p["y"]+=p["vy"];p["life"]-=1
        p["trail"].append((p["x"],p["y"]))
        if len(p["trail"])>9:p["trail"].pop(0)
        if p["x"]<-40 or p["x"]>W+40 or p["y"]<-40 or p["y"]>H+40:projs.remove(p);continue
        hit=False
        for e in enemies:
            if e.get("dead"):continue
            if dist(p["x"],p["y"],e["x"],e["y"])<16:
                hit=True
                if p["splash"]>0:splash(p["x"],p["y"],p["splash"],p["damage"],p["color"])
                else:
                    dmg_e(e,p["damage"],p["color"])
                    if p["slow"] and e["hp"]>0:e["slow_factor"]=p["slow"];e["slow_timer"]=max(e["slow_timer"],p["slow_duration"])
                    sp_parts(p["x"],p["y"],p["color"],5,2.5,18,3)
                break
        if hit or p["life"]<=0:
            if p["splash"]>0 and not hit:splash(p["x"],p["y"],p["splash"],p["damage"],p["color"])
            projs.remove(p)
def draw_projs():
    for p in projs:
        n=len(p["trail"])
        for i in range(n-1):
            t=i/max(1,n-1);r=max(1,int(p["radius"]*t*0.8))
            c=(int(BB[0]+(p["color"][0]-BB[0])*t),int(BB[1]+(p["color"][1]-BB[1])*t),int(BB[2]+(p["color"][2]-BB[2])*t))
            pygame.draw.circle(screen,c,(int(p["trail"][i][0]),int(p["trail"][i][1])),r)
        x,y=int(p["x"]),int(p["y"])
        g=gs(p["radius"]*3,p["color"],110);screen.blit(g,(x-p["radius"]*3,y-p["radius"]*3))
        if p["type"]=="bomb":
            pygame.draw.circle(screen,(40,30,24),(x,y),p["radius"]);pygame.draw.circle(screen,p["color"],(x,y),p["radius"]-1);pygame.draw.circle(screen,(255,240,200),(x-1,y-1),2)
        elif p["type"]=="missile":
            a=p["angle"];tip=(x+math.cos(a)*8,y+math.sin(a)*8);lft=(x+math.cos(a+2.4)*5,y+math.sin(a+2.4)*5);rgt=(x+math.cos(a-2.4)*5,y+math.sin(a-2.4)*5)
            pygame.draw.polygon(screen,p["color"],[tip,lft,rgt]);pygame.draw.circle(screen,(255,255,220),(x,y),2)
        elif p["type"]=="ice":
            pygame.draw.circle(screen,(230,248,255),(x,y),p["radius"]);pygame.draw.circle(screen,p["color"],(x,y),p["radius"]-1,1)
        else:
            pygame.draw.circle(screen,p["color"],(x,y),p["radius"]);pygame.draw.circle(screen,(255,255,255),(x,y),max(1,p["radius"]-3))
def draw_towers():
    for t in towers:
        x,y=int(t["x"]),int(t["y"]);cfg=TT[t["type"]];col=TC[t["type"]]
        if t["type"]==2 and has_uru:col=(210,60,20);ac=(255,140,60);mz=(255,180,80)
        else:ac=tuple(min(255,c+60) for c in col);mz=(255,220,180)
        g=gs(36,col,70+int(t["pulse"]*60));screen.blit(g,(x-36,y-36))
        sh=pygame.Surface((46,18),pygame.SRCALPHA);pygame.draw.ellipse(sh,(0,0,0,100),(0,0,46,18));screen.blit(sh,(x-23,y+10))
        pygame.draw.circle(screen,(18,30,42),(x,y+2),22);pygame.draw.circle(screen,(38,58,76),(x,y),21)
        pygame.draw.circle(screen,(52,78,100),(x,y),18);pygame.draw.circle(screen,col,(x,y),14);pygame.draw.circle(screen,ac,(x-3,y-4),8)
        ang=t["angle"];ro=int(t["recoil"]*5)
        tt=pygame.Surface((64,64),pygame.SRCALPHA);cx=cy=32
        if t["type"]==0:
            pygame.draw.rect(tt,(30,48,66),(cx,cy-8,30-ro,16),border_radius=5);pygame.draw.rect(tt,col,(cx,cy-5,28-ro,10),border_radius=4)
            pygame.draw.circle(tt,(20,34,50),(cx+27-ro,cy),7);pygame.draw.circle(tt,mz,(cx+27-ro,cy),3)
        elif t["type"]==1:
            pygame.draw.line(tt,(230,255,240),(cx-7,cy),(cx+7,cy),4);pygame.draw.line(tt,(230,255,240),(cx,cy-7),(cx,cy+7),4);pygame.draw.circle(tt,col,(cx,cy),11,2)
        elif t["type"]==2:
            pygame.draw.rect(tt,(30,48,66),(cx-2,cy-12,28-ro,10),border_radius=4);pygame.draw.rect(tt,(30,48,66),(cx-2,cy+2,28-ro,10),border_radius=4)
            pygame.draw.rect(tt,col,(cx,cy-10,24-ro,6),border_radius=3);pygame.draw.rect(tt,col,(cx,cy+4,24-ro,6),border_radius=3)
            if has_uru:pygame.draw.circle(tt,mz,(cx+22-ro,cy),3);pygame.draw.circle(tt,mz,(cx+22-ro,cy-7),2)
        elif t["type"]==3:
            for i in range(3):
                a=i*math.tau/3;px=int(cx+math.cos(a)*10);py=int(cy+math.sin(a)*10)
                pygame.draw.circle(tt,col,(px,py),5);pygame.draw.circle(tt,(230,248,255),(px,py),2)
            pygame.draw.circle(tt,(200,235,255),(cx,cy),8,2)
        rot=pygame.transform.rotate(tt,-math.degrees(ang));screen.blit(rot,rot.get_rect(center=(x,y)))
        if t["buff_timer"]>0:
            r=t["buff_timer"]/TT[1]["buff_duration"];pygame.draw.arc(screen,(110,230,160),(x-28,y-28,56,56),-math.pi/2,-math.pi/2+r*math.tau,3)
        if t["type"]==1 and t["pulse"]>0:
            r=int(cfg["range"]*(1-t["pulse"]*0.7));a=int(120*t["pulse"])
            s=pygame.Surface((r*2,r*2),pygame.SRCALPHA);pygame.draw.circle(s,(110,230,160,a),(r,r),r,2);screen.blit(s,(x-r,y-r))
BW,BH=118,50;BG_=8;BC=6
_tw=BC*BW+(BC-1)*BG_;BSX=(W-_tw)//2;BY=545
BTNS=[pygame.Rect(BSX+i*(BW+BG_),BY,BW,BH) for i in range(BC)]
def item_cost(i):
    if i<4:return TT[i]["cost"]
    if i==4:return WCFG["cost"]
    return TRCFG["cost"]
def can_afford(i):
    if i==4 and wolf is not None:return False
    if i==5 and trav is not None:return False
    return gold>=item_cost(i)
def item_col(i):
    if i<4:
        if i==2 and has_uru:return (255,140,60)
        return TC[i]
    if i==4:return WC
    return DBC
def item_nm(i):
    if i<4:return TT[i]["name"]
    if i==4:return "红狼"
    return "深蓝"
def item_k(i):
    if i<4:return TT[i]["short"]
    if i==4:return "R"
    return "B"
def draw_top():
    bar=pygame.Surface((W,50),pygame.SRCALPHA)
    for y in range(50):
        a=int(210*(1-y/50)+40);pygame.draw.line(bar,(14,26,38,a),(0,y),(W,y))
    screen.blit(bar,(0,0));pygame.draw.line(screen,(48,82,110),(0,50),(W,50),1)
    pygame.draw.circle(screen,(180,140,40),(28,25),12);pygame.draw.circle(screen,GOLD,(28,25),10);pygame.draw.circle(screen,(255,240,190),(25,22),4)
    gi=fm.render(str(gold),True,GOLD);screen.blit(gi,(46,25-gi.get_height()//2))
    hx,hy=200,25
    pygame.draw.circle(screen,LIV,(hx-5,hy-3),6);pygame.draw.circle(screen,LIV,(hx+5,hy-3),6)
    pygame.draw.polygon(screen,LIV,[(hx-11,hy-1),(hx+11,hy-1),(hx,hy+12)]);pygame.draw.circle(screen,(255,180,190),(hx-6,hy-5),2)
    li=fm.render(str(lives),True,LIV);screen.blit(li,(hx+20,hy-li.get_height()//2))
    lv=["零号大坝","长弓溪谷","AZ3","巴克申","航天基地"][cur_lvl]
    lvimg=fs.render("◈ "+lv,True,(140,200,230));screen.blit(lvimg,(330,25-lvimg.get_height()//2))
    dn=DIFF_INFO[difficulty]["name"];dc=DIFF_INFO[difficulty]["color"]
    dimg=fs.render("["+dn+"]",True,dc);screen.blit(dimg,(330+lvimg.get_width()+8,25-dimg.get_height()//2))
    el=(pygame.time.get_ticks()-st)/1000;mi=int(el//60);se=int(el%60)
    ti=fm.render(f"{mi:02d}:{se:02d}",True,UTD);screen.blit(ti,(W-ti.get_width()-24,25-ti.get_height()//2))
    ci=fs.render(f"敌人 {len(enemies)}",True,(200,140,140));screen.blit(ci,(W-ci.get_width()-24,46-ci.get_height()))
    if wave_idx<len(WAVES):
        wtxt=fs.render(f"第 {wave_idx+1}/{len(WAVES)} 波 · 剩余 {len(cur_wave_list)-wave_spawned+len(enemies)}",True,(255,200,120))
    else:
        wtxt=fs.render("全部波次已通过",True,(0,255,150))
    screen.blit(wtxt,(W//2-wtxt.get_width()//2,54))
def draw_bot():
    p=pygame.Surface((W,62),pygame.SRCALPHA)
    for y in range(62):
        a=int(230*(1-y/62)+20);pygame.draw.line(p,(16,30,44,a),(0,y),(W,y))
    screen.blit(p,(0,H-62));pygame.draw.line(screen,(50,86,116),(0,H-62),(W,H-62),1)
def draw_btn(rect,i,mp):
    hv=rect.collidepoint(mp);act=sel==i;aff=can_afford(i);col=item_col(i);base=UP2
    if act:base=(44,84,112)
    elif hv and aff:base=(40,68,90)
    if not aff:base=(28,40,52)
    sh=pygame.Surface((rect.w+4,rect.h+4),pygame.SRCALPHA);pygame.draw.rect(sh,(0,0,0,70),(2,3,rect.w,rect.h),border_radius=12);screen.blit(sh,(rect.x-2,rect.y-2))
    pygame.draw.rect(screen,base,rect,border_radius=11)
    if act:pygame.draw.rect(screen,col,rect,width=2,border_radius=11)
    elif hv and aff:pygame.draw.rect(screen,tuple(min(255,c+40) for c in col),rect,width=2,border_radius=11)
    else:pygame.draw.rect(screen,(52,82,106),rect,width=1,border_radius=11)
    ix,iy=rect.x+24,rect.centery
    g=gs(18,col,90 if aff else 40);screen.blit(g,(ix-18,iy-18))
    pygame.draw.circle(screen,(18,30,42),(ix,iy+1),14);pygame.draw.circle(screen,col if aff else (90,105,118),(ix,iy),12)
    br=tuple(min(255,c+70) for c in col) if aff else (120,135,148);pygame.draw.circle(screen,br,(ix-3,iy-4),5)
    nc=UT if aff else (110,130,148);ni=fs.render(item_nm(i),True,nc);screen.blit(ni,(rect.x+44,rect.y+8))
    cc=GOLD if aff else (150,110,80);ci=ft.render(str(item_cost(i)),True,cc);screen.blit(ci,(rect.x+44,rect.y+28))
    ki=ft.render(item_k(i),True,(90,120,145));screen.blit(ki,(rect.right-ki.get_width()-8,rect.bottom-ki.get_height()-6))
    if (i==4 and wolf is not None) or (i==5 and trav is not None):
        mk=ft.render("已部署",True,(110,190,130));screen.blit(mk,(rect.right-mk.get_width()-8,rect.y+8))
def draw_sel(mp):
    mx,my=mp
    if my>528 or my<50:return
    if sel==4 and wolf is not None:return
    if sel==5 and trav is not None:return
    if sel<4:
        cfg=TT[sel];rng=cfg["range"];col=TC[sel]
        if sel==2 and has_uru:col=(255,140,60)
    elif sel==4:rng=WCFG["range"];col=WC
    else:rng=TRCFG["attack_range"];col=DBC
    ok=can_place(mx,my) and can_afford(sel)
    s=rs(rng,col if ok else (200,80,80));screen.blit(s,(mx-rng,my-rng))
    if ok:pygame.draw.circle(screen,(100,240,160),(mx,my),20,2)
    else:
        pygame.draw.line(screen,(240,90,90),(mx-12,my-12),(mx+12,my+12),3);pygame.draw.line(screen,(240,90,90),(mx+12,my-12),(mx-12,my+12),3)
def draw_go():
    ov=pygame.Surface((W,H),pygame.SRCALPHA);ov.fill((20,6,6,210));screen.blit(ov,(0,0))
    t=fh.render("撤离失败",True,(255,80,80));sh=fh.render("撤离失败",True,(60,10,10))
    tx=W//2-t.get_width()//2;ty=H//2-90;screen.blit(sh,(tx+3,ty+3));screen.blit(t,(tx,ty))
    se=int((pygame.time.get_ticks()-st)/1000)
    sub=fb.render(f"坚守了 {se} 秒",True,(255,180,180));screen.blit(sub,(W//2-sub.get_width()//2,ty+80))
    hint=fm.render("按 R 重新开始   |   按 ESC 返回关卡选择",True,GOLD)
    p=0.6+0.4*math.sin(pygame.time.get_ticks()*0.005);hint.set_alpha(int(255*p))
    screen.blit(hint,(W//2-hint.get_width()//2,ty+140))
def draw_vic():
    ov=pygame.Surface((W,H),pygame.SRCALPHA);ov.fill((6,20,12,210));screen.blit(ov,(0,0))
    t=fh.render("撤离成功",True,(60,255,140));sh=fh.render("撤离成功",True,(10,60,30))
    tx=W//2-t.get_width()//2;ty=H//2-90;screen.blit(sh,(tx+3,ty+3));screen.blit(t,(tx,ty))
    se=int((pygame.time.get_ticks()-st)/1000)
    sub=fb.render(f"耗时 {se} 秒",True,(180,255,200));screen.blit(sub,(W//2-sub.get_width()//2,ty+80))
    hint=fm.render("按 ESC 返回关卡选择",True,GOLD)
    p=0.6+0.4*math.sin(pygame.time.get_ticks()*0.005);hint.set_alpha(int(255*p))
    screen.blit(hint,(W//2-hint.get_width()//2,ty+140))
_lw,_lh=140,110
LRC=[pygame.Rect(50,140,_lw,_lh),pygame.Rect(270,100,_lw,_lh),pygame.Rect(590,155,_lw,_lh),pygame.Rect(120,360,_lw,_lh),pygame.Rect(390,330,_lw,_lh),pygame.Rect(630,380,_lw,_lh)]
def draw_lvl(mp):
    for y in range(H):
        t=y/H;c=int(60+25*t);pygame.draw.line(screen,(c,c,c+2),(0,y),(W,y))
    bar=pygame.Surface((W,80),pygame.SRCALPHA)
    for y in range(80):
        a=int(180*(1-y/80)+30);pygame.draw.line(bar,(20,20,22,a),(0,y),(W,y))
    screen.blit(bar,(0,0));pygame.draw.line(screen,(90,90,95),(0,80),(W,80),1)
    ti=fb.render("选择关卡",True,(230,230,235));screen.blit(ti,(W//2-ti.get_width()//2,25))
    br=pygame.Rect(20,22,90,40);hb=br.collidepoint(mp)
    pygame.draw.rect(screen,(95,95,100) if hb else (70,70,75),br,border_radius=8);pygame.draw.rect(screen,(140,140,145),br,width=1,border_radius=8)
    bt=fs.render("← 返回",True,(225,225,230));screen.blit(bt,(br.centerx-bt.get_width()//2,br.centery-bt.get_height()//2))
    nms=["零号大坝","长弓溪谷","AZ3","巴克申","航天基地"]
    cols=[((85,100,120),(0,255,150)),((95,90,80),(255,200,100)),((90,75,70),(240,180,80)),((80,70,90),(200,160,255)),((70,80,100),(100,180,255))]
    for i,rect in enumerate(LRC):
        if i<5:
            hv=rect.collidepoint(mp);bc,brd=cols[i]
            if hv:bc=tuple(min(255,c+15) for c in bc)
            if hv:g=gs(_lw//2+20,brd,70);screen.blit(g,(rect.centerx-(_lw//2+20),rect.centery-(_lw//2+20)))
            pygame.draw.rect(screen,bc,rect,border_radius=10)
            pygame.draw.rect(screen,brd if hv else tuple(c//2+60 for c in brd),rect,width=2,border_radius=10)
            thumb=rect.inflate(-24,-24);thumb.height-=24
            pygame.draw.rect(screen,(30,38,50),thumb,border_radius=6);pygame.draw.rect(screen,(70,90,110),thumb,width=1,border_radius=6)
            cxt,cyt=thumb.centerx,thumb.centery
            if i==0:
                pygame.draw.polygon(screen,(90,150,130),[(thumb.x+14,thumb.bottom-10),(cxt-12,thumb.y+12),(cxt+12,thumb.y+12),(thumb.right-14,thumb.bottom-10)],2)
                pygame.draw.line(screen,(140,200,170),(cxt-22,thumb.bottom-10),(cxt+22,thumb.bottom-10),2);pygame.draw.circle(screen,(0,255,150),(cxt,thumb.y+8),3)
            elif i==1:
                rx,ry=cxt,thumb.y+14
                pygame.draw.polygon(screen,(150,160,170),[(rx-11,thumb.bottom-8),(rx-3,ry),(rx+3,ry),(rx+11,thumb.bottom-8)])
                pygame.draw.ellipse(screen,(200,215,230),(rx-14,ry-6,28,10));pygame.draw.arc(screen,(255,210,100),(rx-20,ry-16,40,30),-math.pi*0.75,-math.pi*0.25,2);pygame.draw.circle(screen,(255,220,120),(rx,ry-3),2)
            elif i==2:
                rx,ry=cxt,thumb.y+18
                ou=[(rx-22,thumb.bottom-8),(rx-18,ry),(rx-7,ry-12),(rx,ry-15),(rx+7,ry-12),(rx+18,ry),(rx+22,thumb.bottom-8)]
                pygame.draw.polygon(screen,(140,148,158),ou);pygame.draw.polygon(screen,(80,85,92),ou,2);pygame.draw.line(screen,(240,200,50),(rx-9,ry+2),(rx+9,ry+2),2)
            elif i==3:
                rx,ry=cxt,thumb.y+26
                for j in range(4):
                    w=14-j*2;y=ry+j*7
                    pygame.draw.rect(screen,(160-j*12,150-j*12,120-j*10),(rx-w,y-5,w*2,5))
                pygame.draw.polygon(screen,(220,200,150),[(rx-7,ry-5),(rx,ry-14),(rx+7,ry-5)]);pygame.draw.circle(screen,(255,240,160),(rx,ry-12),2)
            else:
                rx,ry=cxt,thumb.y+32
                pygame.draw.rect(screen,(70,75,82),(rx-16,ry,32,12))
                pygame.draw.rect(screen,(220,220,225),(rx-5,ry-16,10,20),border_radius=3)
                pygame.draw.polygon(screen,(220,50,50),[(rx-5,ry-16),(rx+5,ry-16),(rx,ry-26)])
                pygame.draw.polygon(screen,(255,180,50),[(rx-4,ry+12),(rx+4,ry+12),(rx,ry+22)])
                pygame.draw.rect(screen,(210,170,30),(rx-32,ry+18,20,5),border_radius=2)
                pygame.draw.rect(screen,(210,170,30),(rx+12,ry+18,20,5),border_radius=2)
            nm=fs.render(nms[i],True,(220,245,255));screen.blit(nm,(rect.centerx-nm.get_width()//2,rect.bottom-30))
            tg=ft.render("▶ 可进入",True,brd);screen.blit(tg,(rect.centerx-tg.get_width()//2,rect.bottom-14))
        else:
            pygame.draw.rect(screen,(44,44,48),rect,border_radius=10);pygame.draw.rect(screen,(78,78,84),rect,width=1,border_radius=10)
            lx,ly=rect.centerx,rect.centery-14
            pygame.draw.rect(screen,(100,100,108),(lx-13,ly-2,26,22),border_radius=4);pygame.draw.arc(screen,(100,100,108),(lx-10,ly-15,20,22),math.pi*0.05,math.pi*0.95,3);pygame.draw.circle(screen,(60,60,66),(lx,ly+8),3)
            nm=fs.render("更新中",True,(135,135,142));screen.blit(nm,(rect.centerx-nm.get_width()//2,rect.bottom-28))
    hint=ft.render("更多地图正在开发中，敬请期待…",True,(120,120,128));screen.blit(hint,(W//2-hint.get_width()//2,H-30))
    return br
def draw_diff(mp):
    for y in range(H):
        t=y/H;c=int(55+20*t);pygame.draw.line(screen,(c,c,c+2),(0,y),(W,y))
    bar=pygame.Surface((W,80),pygame.SRCALPHA)
    for y in range(80):
        a=int(180*(1-y/80)+30);pygame.draw.line(bar,(20,20,22,a),(0,y),(W,y))
    screen.blit(bar,(0,0));pygame.draw.line(screen,(90,90,95),(0,80),(W,80),1)
    lvl_name=["零号大坝","长弓溪谷","AZ3","巴克申","航天基地"][pending_level]
    ti=fb.render(lvl_name,True,(235,235,240));screen.blit(ti,(W//2-ti.get_width()//2,12))
    sub=fs.render("— 选择难度 —",True,(180,180,190));screen.blit(sub,(W//2-sub.get_width()//2,52))
    br=pygame.Rect(20,22,90,40);hb=br.collidepoint(mp)
    pygame.draw.rect(screen,(95,95,100) if hb else (70,70,75),br,border_radius=8);pygame.draw.rect(screen,(140,140,145),br,width=1,border_radius=8)
    bt=fs.render("← 返回",True,(225,225,230));screen.blit(bt,(br.centerx-bt.get_width()//2,br.centery-bt.get_height()//2))
    opts=LEVEL_DIFFS[pending_level];diff_list=[]
    cw,ch=200,220;total=len(opts)*cw+(len(opts)-1)*40;sx=(W-total)//2
    for i,di in enumerate(opts):
        info=DIFF_INFO[di];r=pygame.Rect(sx+i*(cw+40),190,cw,ch);hv=r.collidepoint(mp)
        bc=(45,55,70) if not hv else (62,78,98)
        if hv:
            g=gs(cw//2+20,info["color"],70);screen.blit(g,(r.centerx-(cw//2+20),r.centery-(cw//2+20)))
        pygame.draw.rect(screen,bc,r,border_radius=14)
        pygame.draw.rect(screen,info["color"] if hv else tuple(c//2+50 for c in info["color"]),r,width=3,border_radius=14)
        nm=fb.render(info["name"],True,info["color"]);screen.blit(nm,(r.centerx-nm.get_width()//2,r.y+24))
        pygame.draw.line(screen,info["color"],(r.x+24,r.y+74),(r.right-24,r.y+74),1)
        if di==3:
            for k in range(3):
                wy=r.bottom-30+k*6
                pygame.draw.line(screen,(70,170,255),(r.x+20,wy),(r.right-20,wy),1)
        elif di==4:
            for k in range(3):
                fx=r.x+40+k*40
                pygame.draw.polygon(screen,(255,120,40),[(fx,r.bottom-14),(fx+14,r.bottom-14),(fx+7,r.bottom-26)])
                pygame.draw.polygon(screen,(255,220,80),[(fx+4,r.bottom-14),(fx+10,r.bottom-14),(fx+7,r.bottom-20)])
        for j,(k,v) in enumerate([("敌人 HP",f"x{info['hp']:.1f}"),("敌人速度",f"x{info['speed']:.2f}"),("金币奖励",f"x{info['reward']:.1f}")]):
            y=r.y+90+j*24
            kj=fs.render(k,True,(180,190,200));screen.blit(kj,(r.x+18,y))
            vj=fs.render(v,True,info["color"]);screen.blit(vj,(r.right-vj.get_width()-18,y))
        btn=pygame.Rect(r.centerx-60,r.bottom-52,120,36);hb2=btn.collidepoint(mp)
        bgc=info["color"] if hb2 else tuple(c//2+30 for c in info["color"])
        pygame.draw.rect(screen,bgc,btn,border_radius=8);pygame.draw.rect(screen,(255,255,255),btn,width=1,border_radius=8)
        bt2=fm.render("开 始",True,(20,20,25));screen.blit(bt2,(btn.centerx-bt2.get_width()//2,btn.centery-bt2.get_height()//2))
        diff_list.append((r,di))
    hint=ft.render("难度越高，敌人越强，但金币奖励也越丰厚",True,(140,140,150))
    screen.blit(hint,(W//2-hint.get_width()//2,H-30))
    return br,diff_list
def draw_menu(mp):
    screen.fill(MBG)
    for x in range(0,W,40):pygame.draw.line(screen,(20,35,50),(x,0),(x,H))
    for y in range(0,H,40):pygame.draw.line(screen,(20,35,50),(0,y),(W,y))
    cx,cy=W//2+120,H//2+30
    g=gs(140,MAC,90);screen.blit(g,(cx-140,cy-140))
    sh=fS1.render("S1",True,(5,60,40));screen.blit(sh,(cx-sh.get_width()//2+5,cy-sh.get_height()//2+5))
    s1=fS1.render("S1",True,MAC);screen.blit(s1,(cx-s1.get_width()//2,cy-s1.get_height()//2))
    sub=fm.render("—— 三角洲行动 ——",True,(180,220,200));screen.blit(sub,(cx-sub.get_width()//2,cy+110))
    pygame.draw.polygon(screen,MAC,[(30,20),(40,40),(20,40)]);pygame.draw.polygon(screen,(255,255,255),[(30,25),(36,38),(24,38)])
    ti=fmt.render("三角洲行动",True,(255,255,255));screen.blit(ti,(60,15))
    ticket=fm.render(f"点券: {tickets}",True,GOLD);screen.blit(ticket,(W-ticket.get_width()-30,70))
    ys=100
    if has_skin:sk=fs.render("✓ 皮肤「肆-A2」",True,(0,255,150));screen.blit(sk,(W-sk.get_width()-30,ys));ys+=22
    if has_uru:uk=fs.render("✓ 皮肤「狂热」",True,(255,140,60));screen.blit(uk,(W-uk.get_width()-30,ys))
    pn=pygame.Rect(30,90,300,380);pygame.draw.rect(screen,MP,pn,border_radius=8);pygame.draw.rect(screen,MB,pn,width=1,border_radius=8)
    c1=pygame.Rect(40,105,280,90);h1=c1.collidepoint(mp);brd1=(255,220,100) if h1 else (180,140,60)
    pygame.draw.rect(screen,(25,22,20),c1,border_radius=6);pygame.draw.rect(screen,brd1,c1,width=2 if h1 else 1,border_radius=6)
    ts=fdg.render("骏龙",True,(80,60,20));tn=fdg.render("骏龙",True,(230,200,100));screen.blit(ts,(52,110));screen.blit(tn,(51,109))
    bd=pygame.Rect(120,109,48,22);pygame.draw.rect(screen,(180,30,30),bd,border_radius=3);pygame.draw.rect(screen,(255,255,255),bd,width=1,border_radius=3)
    bt=ft.render("肆-A2",True,(255,255,255));screen.blit(bt,(bd.x+8,bd.y+4))
    gr=pygame.Rect(172,109,70,22);pygame.draw.rect(screen,(220,170,50),gr,border_radius=3)
    gt=ft.render("8抽保底",True,(40,20,0));screen.blit(gt,(gr.x+6,gr.y+4))
    if has_skin:st="已获得「肆-A2」";sc=(0,255,150)
    elif lott<8:st=f"第{lott+1}次  {LP[lott]}点券";sc=(200,180,160)
    else:st="已抽完";sc=(150,130,110)
    si=ft.render(st,True,sc);screen.blit(si,(55,148))
    s3=ft.render("点击卡片抽奖",True,(150,130,110));screen.blit(s3,(55,168))
    c2=pygame.Rect(40,205,280,60);h2=c2.collidepoint(mp);brd2=(0,255,150) if h2 else (40,80,100)
    pygame.draw.rect(screen,(25,45,60),c2,border_radius=6);pygame.draw.rect(screen,brd2,c2,width=2 if h2 else 1,border_radius=6)
    t2=fs.render("洲年送券狂欢",True,MAC);screen.blit(t2,(55,213))
    t2b=ft.render("点击领取 3900 点券！",True,(200,220,240));screen.blit(t2b,(55,235))
    c3=pygame.Rect(40,275,280,90);h3=c3.collidepoint(mp);brd3=(255,140,60) if h3 else (140,60,30)
    pygame.draw.rect(screen,(30,15,10),c3,border_radius=6);pygame.draw.rect(screen,brd3,c3,width=2 if h3 else 1,border_radius=6)
    us=fdg.render("狂热",True,(60,20,10));un=fdg.render("狂热",True,(255,140,60));screen.blit(us,(52,280));screen.blit(un,(51,279))
    ub=pygame.Rect(120,279,58,22);pygame.draw.rect(screen,(200,60,20),ub,border_radius=3);pygame.draw.rect(screen,(255,255,255),ub,width=1,border_radius=3)
    ubt=ft.render("乌鲁鲁",True,(255,255,255));screen.blit(ubt,(ub.x+8,ub.y+4))
    ug=pygame.Rect(182,279,60,22);pygame.draw.rect(screen,(220,90,30),ug,border_radius=3)
    ugt=ft.render("2抽保底",True,(40,10,0));screen.blit(ugt,(ug.x+4,ug.y+4))
    if has_uru:ust="已获得「狂热」";usc=(255,140,60)
    elif ucnt<2:ust=f"第{ucnt+1}次  {UP[ucnt]}点券";usc=(220,160,120)
    else:ust="已抽完";usc=(150,130,110)
    usi=ft.render(ust,True,usc);screen.blit(usi,(55,318))
    us3=ft.render("点击卡片抽奖",True,(150,100,80));screen.blit(us3,(55,338))
    at=fs.render("公告",True,(255,255,255));screen.blit(at,(50,385))
    pygame.draw.line(screen,MAC,(50,405),(85,405),2)
    a1=ft.render("10月5日更新 | 水淹大坝 / 火烧长弓 上线",True,(160,180,200));screen.blit(a1,(50,420))
    a2=ft.render("9月30日更新 | 深蓝部署单位上线",True,(160,180,200));screen.blit(a2,(50,440))
    for i,it in enumerate(["👤","⚙","🚪"]):
        ny=150+i*60
        pygame.draw.circle(screen,(30,45,60),(W-40,ny),16);pygame.draw.circle(screen,(60,90,110),(W-40,ny),16,1)
        nt=fm.render(it,True,(180,200,220));screen.blit(nt,(W-40-nt.get_width()//2,ny-nt.get_height()//2))
    sb=pygame.Rect(560,480,200,60);hov=sb.collidepoint(mp)
    if hov:g=gs(60,MAC,80);screen.blit(g,(sb.centerx-60,sb.centery-60))
    pygame.draw.rect(screen,(0,40,30) if hov else (0,20,15),sb,border_radius=4);pygame.draw.rect(screen,MAC if hov else (0,180,100),sb,width=2,border_radius=4)
    bt=fmb.render("开始游戏",True,MAC if hov else (0,220,130));screen.blit(bt,(sb.centerx-bt.get_width()//2,sb.centery-bt.get_height()//2))
    cb=pygame.Rect(W-60,20,30,30)
    if cb.collidepoint(mp):pygame.draw.rect(screen,(200,60,60),cb,border_radius=4)
    pygame.draw.line(screen,(150,150,150),(W-52,28),(W-38,42),2);pygame.draw.line(screen,(150,150,150),(W-38,28),(W-52,42),2)
    return sb,cb,c1,c2,c3
def reset():
    global lives,gold,enemies,towers,projs,fts,parts
    global wolf,trav,nid,spc,go,st,sel
    global wave_idx,wave_spawned,wave_clear_timer,wave_banner_timer,wave_banner_text,cur_wave_list
    lives=10;gold=240
    enemies=[];towers=[];projs=[];fts=[];parts=[]
    wolf=None;trav=None;nid=1;spc=0;go=False;sel=0;st=pygame.time.get_ticks()
    wave_idx=0;wave_spawned=0;wave_clear_timer=0
    cur_wave_list=get_wave_list(0)
    wave_banner_timer=150;wave_banner_text=f"第 1 波 · 共 {len(cur_wave_list)} 敌人"
def handle_click(pos):
    global sel,gold
    mx,my=pos
    for i,r in enumerate(BTNS):
        if r.collidepoint(mx,my):sel=i;return
    if my>528:return
    if not can_afford(sel):return
    if sel<4:
        cfg=TT[sel]
        if can_place(mx,my):
            gold-=cfg["cost"];towers.append(mk_tower(sel,mx,my))
            sp_parts(mx,my,TC[sel],14,3.5,30,4);add_ft(mx,my-32,cfg["name"],TC[sel])
    elif sel==4:sum_wolf(mx,my)
    elif sel==5:sum_trav(mx,my)
def upd_all():
    global spc,go
    spc+=1
    if spc>=SPI:spc=0;sp_enemy()
    upd_enemies();upd_towers();upd_wolf();upd_trav();upd_projs();upd_parts();upd_ft()
    if lives<=0:go=True
def draw_all(mp):
    screen.blit(SB[cur_lvl],(0,0))
    if not go:draw_sel(mp)
    draw_towers();draw_trav();draw_wolf();draw_enemies();draw_projs();draw_parts();draw_ft()
    draw_top();draw_bot()
    for i,r in enumerate(BTNS):draw_btn(r,i,mp)
    if wave_banner_timer>0:
        alpha=min(255,wave_banner_timer*4)
        bt=fb.render(wave_banner_text,True,(255,220,120))
        sh=fb.render(wave_banner_text,True,(40,20,10))
        sh.set_alpha(alpha//2);bt.set_alpha(alpha)
        bx=W//2-bt.get_width()//2;by=H//2-80
        screen.blit(sh,(bx+3,by+3));screen.blit(bt,(bx,by))
    if go:draw_go()
    elif wave_idx>=len(WAVES) and len(enemies)==0:draw_vic()
def main():
    global sel,go,game_state,cur_lvl,tickets,lott,has_skin,ucnt,has_uru
    global difficulty,pending_level
    build_static()
    running=True
    while running:
        clock.tick(60)
        mp=pygame.mouse.get_pos()
        for ev in pygame.event.get():
            if ev.type==pygame.QUIT:running=False
            elif ev.type==pygame.KEYDOWN:
                if ev.key==pygame.K_ESCAPE:
                    if game_state=="MENU":running=False
                    elif game_state=="LEVEL_SELECT":game_state="MENU"
                    elif game_state=="DIFFICULTY":game_state="LEVEL_SELECT"
                    else:game_state="LEVEL_SELECT"
                elif game_state=="PLAYING":
                    if ev.key in (pygame.K_a,pygame.K_1):sel=0
                    elif ev.key in (pygame.K_s,pygame.K_2):sel=1
                    elif ev.key in (pygame.K_p,pygame.K_3):sel=2
                    elif ev.key in (pygame.K_l,pygame.K_4):sel=3
                    elif ev.key==pygame.K_r:
                        if go:reset();game_state="PLAYING"
                        else:sel=4
                    elif ev.key in (pygame.K_b,pygame.K_5,pygame.K_6):sel=5
                elif game_state=="GAME_OVER":
                    if ev.key==pygame.K_r:reset();game_state="PLAYING"
                    elif ev.key==pygame.K_ESCAPE:game_state="LEVEL_SELECT"
            elif ev.type==pygame.MOUSEBUTTONDOWN and ev.button==1:
                if game_state=="MENU":
                    sb,cb,c1,c2,c3=draw_menu(mp)
                    if c1.collidepoint(ev.pos):
                        if not has_skin and lott<8:
                            price=LP[lott]
                            if tickets>=price:
                                tickets-=price;lott+=1
                                if lott>=8:has_skin=True;add_ft(c1.centerx,c1.centery-20,"恭喜获得「肆-A2」！",(0,255,150))
                                else:add_ft(c1.centerx,c1.centery-20,f"第{lott}次抽奖",(255,220,100))
                            else:add_ft(c1.centerx,c1.centery-20,"点券不足！",(255,100,100))
                        elif has_skin:add_ft(c1.centerx,c1.centery-20,"已获得皮肤",(0,255,150))
                        else:add_ft(c1.centerx,c1.centery-20,"已抽完",(200,200,200))
                    elif c2.collidepoint(ev.pos):tickets+=3900;add_ft(c2.centerx,c2.centery-20,"+3900 点券",GOLD)
                    elif c3.collidepoint(ev.pos):
                        if not has_uru and ucnt<2:
                            price=UP[ucnt]
                            if tickets>=price:
                                tickets-=price;ucnt+=1
                                if ucnt>=2:has_uru=True;add_ft(c3.centerx,c3.centery-20,"恭喜获得「狂热」！",(255,140,60))
                                else:add_ft(c3.centerx,c3.centery-20,f"第{ucnt}次抽奖",(255,180,100))
                            else:add_ft(c3.centerx,c3.centery-20,"点券不足！",(255,100,100))
                        elif has_uru:add_ft(c3.centerx,c3.centery-20,"已获得皮肤",(255,140,60))
                        else:add_ft(c3.centerx,c3.centery-20,"已抽完",(200,200,200))
                    elif sb.collidepoint(ev.pos):game_state="LEVEL_SELECT"
                    elif cb.collidepoint(ev.pos):running=False
                elif game_state=="LEVEL_SELECT":
                    br=draw_lvl(mp)
                    if br.collidepoint(ev.pos):game_state="MENU"
                    else:
                        for i in range(5):
                            if LRC[i].collidepoint(ev.pos):pending_level=i;game_state="DIFFICULTY";break
                elif game_state=="DIFFICULTY":
                    br,diffs=draw_diff(mp)
                    if br.collidepoint(ev.pos):game_state="LEVEL_SELECT"
                    else:
                        for r,di in diffs:
                            btn=pygame.Rect(r.centerx-60,r.bottom-52,120,36)
                            if btn.collidepoint(ev.pos) or r.collidepoint(ev.pos):
                                cur_lvl=pending_level;difficulty=di;reset();game_state="PLAYING";break
                elif game_state=="PLAYING":
                    if go:reset();game_state="PLAYING"
                    else:handle_click(ev.pos)
        if game_state=="MENU":draw_menu(mp);upd_ft();draw_ft()
        elif game_state=="LEVEL_SELECT":draw_lvl(mp);upd_ft();draw_ft()
        elif game_state=="DIFFICULTY":draw_diff(mp);upd_ft();draw_ft()
        elif game_state=="PLAYING":
            if go:game_state="GAME_OVER";draw_all(mp)
            else:upd_all();draw_all(mp)
        elif game_state=="GAME_OVER":draw_all(mp)
        pygame.display.flip()
    pygame.quit()
if __name__=="__main__":main()