ICFP日記3

使われなくなった変数とか計算しかけて放置しているところとかかなりひどいソースコードだけどさらしてみるテスト。だいたいファイル名がdraft.pyだし。
initialize捨ててるし、enemyのデータ保管しているだけで使わないし、そもそもparseのtelemetryの中にthinkがあるとか。sinの値の2回微分を求めているけど使わないし。
まぁ、なんとひどいコードでしょうか。

import sys
HOSTNAME = sys.argv[1]
PORT = int(sys.argv[2])

import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((HOSTNAME, PORT))

class Memory(object):
    def __init__(self):
        self.objects = set()
        self.prev_sinv = None
        self.prev_dsinv = None
        self.dsinv = None
memory = Memory()

def take(xs, fs):
    return tuple(f(xs.pop(0)) for f in fs)
    
def telemetry(xs):
    """T time-stamp vehicle-ctl vehicle-x vehicle-y vehicle-dir vehicle-speed objects ;"""
    keys = """time_stamp ctl 
              x y dir speed""".split()
    pairs = zip(keys, take(xs, [int, str, float, float, float, float]))
    memory.__dict__.update(pairs)
    globals().update(pairs)

    objects = []
    enemies = []
    while xs:
        typ = xs.pop(0)
        if typ == ";":
            break
        if typ == "m":
            # m enemy-x enemy-y enemy-dir enemy-speed
            enemies.append(take(xs, [float] * 4))
        elif typ == "h":
            take(xs, [float] * 3) # throw away
        else:
            # object-kind object-x object-y object-r 
            objects.append((typ, take(xs, [float] * 3)))

    memory.enemies = enemies # latest data only
    memory.objects.update(objects) # keep unique (it is a set)

    # think
    from math import sin, cos, pi, sqrt
    
    rdir = dir / 180 * pi # radian
    speed = 1
    nx = cos(rdir)
    ny = sin(rdir)
    dx = speed * nx
    dy = speed * ny
    dist = sqrt(x * x + y * y)
    cp = -x * dy + y * dx
    dp = -x * dx - y * dy
    sinv = cp / dist / speed
    cosv = dp / dist / speed
    #print sinv, cosv
    command = ""

    dsinv = 0.0
    if cosv > 0.5 and memory.prev_sinv != None:
        dsinv = sinv - memory.prev_sinv
        if memory.prev_dsinv != None:
            ddsinv = dsinv - memory.prev_dsinv
            #print "davel", davel
        memory.prev_dsinv = dsinv
    memory.prev_sinv = sinv

    dir_score = acc_score = 0
    if cosv < 0.5:
        if sinv > 0:
            dir_score += 1 # r
        else:
            dir_score -= 1 # l
    else:
        estimate = sinv + (dist / speed) * dsinv / 2
        if estimate > 0.1:
            dir_score += 1
        elif estimate < -0.1:
            dir_score -= 1
    
    # ray tracing
    maxrad = 0
    maxone = (0, 0)
    for (typ, (ox, oy, orad)) in objects:
        sv = (ox - x) * ny - (oy - y) * nx
        if sv < orad * 1.1:
            cv = ((ox - x) * nx + (oy - y) * ny)
            vrad = orad / cv
            if vrad > maxrad:
                maxrad = vrad
                maxone = (sv, cv - orad)
    #print "max:", maxrad, maxone
    if maxone[1] != 0 and maxone[0] != 0:
        #print "avoid", maxrad / (maxone[1] / speed) * (abs(maxone[0]) / maxone[0])
        dir_score -= maxrad / (maxone[1] / speed) * (abs(maxone[0]) / maxone[0])
            
    if dp < 0 and speed > 10:
        acc_score -= 1 # b
        
    #print x, y, dx, dy, dist, cp
    if acc_score < 0:
        command = "b"
    else:
        command = "a"

    if dir_score > 0:
        command += "r;"
    elif dir_score < 0:
        command += "l;"
    else:
        command += ";"
    s.send(command)
    #print command

def feed(items):
    typ = items[0]
    #print items
    if typ == "I":
        pass
    elif typ == "T":
        items = telemetry(items[1:])
    elif typ == "B":
        if len(items) > 3:
            feed(items[3:]) # telemetry
    elif typ in "CKSE":
        memory.__init__()
buf = ""    
while 1:
    buf += s.recv(1024)
    if not buf: break
    #print buf
    while(buf.find(";") != -1):
        x = buf.find(";")
        line = buf[:x + 1]
        buf = buf[x + 1:]
        items = line.split()
        try:
            #print items
            feed(items)
        except Exception, e:
            import traceback
            traceback
            print e
s.close()