Mercurial > hg > lib > markup
view python/safe.py @ 12:1e42c0147a49
minutor changed file format for minecraft 1.18
author | Henry S. Thompson <ht@inf.ed.ac.uk> |
---|---|
date | Sat, 11 Dec 2021 16:30:29 -0500 |
parents | e411408d64ec |
children | 1cd5c7952aaa |
line wrap: on
line source
#!/usr/bin/python3 '''Find a safe landing space (i.e. in air, not above lava) near a cluster''' import sys, math from util import * from bisect import insort def usage(): print("""Usage: safe.py [-d n] [filename] n is maximum distance of landing to some point in the cluster, default is 10. Feed stdin with lines from the output of cluster.py, having produced air.tsv with the same settings as the cluster input, and lava.tsv with a lower-bound on Y of 0""") class Block: '''Shared by Air and Lava, holds points and columns. Columns are dictionaries indexed by (x,z) coords, value is upward-ordered list of pairs, closed intervals of y''' def __init__(self,filename): with open(filename,'r') as file: self.readHeaders(file) self.readPoints(file) cc=self.columns={} tc={} for p in self.points: k=(p[0],p[2]) y=p[1] try: yy=tc[k] insort(yy,y) except KeyError: tc[k]=[y] # convert to lists of intervals for k,yy in tc.items(): tyy=[yy] ii=[] if k==(108.5, -45.5): pass while True: clean=True for j,yy in enumerate(tyy): if len(yy)==1+(yy[-1]-yy[0]): ii.append((yy[0],yy[-1])) else: clean=False for i in range(len(yy)-1): if yy[i]+1!=yy[i+1]: ii.append((yy[0],yy[i])) tyy=[yy[i+1:]]+tyy[j+1:] break if clean: break self.columns[k]=set(ii) # so we can merge later def readPoints(self,file): file.readline() self.points=[[float(i) for i in l.split('\t')[2].split('/')] for l in file] Block.readHeaders=readHeaders # from util class Air(Block): pass class Lava(Block): pass def d(p1,p2): dx=p1[0]-p2[0] dz=p1[1]-p2[1] dy=p1[2]-p2[2] return math.sqrt((dx*dx)+(dy*dy)+(dz*dz)) def safety(p): ka=[((a[0],a[2]),d(a,p)) for a in A.points if d(a,p)<=n] return [(k,A.columns[k[0]],L.columns.get(k[0],None)) for k in ka] if __name__=='__main__': n=10.0 if len(sys.argv)>1: if sys.argv[1]=='-d': sys.argv.pop(1) n=float(sys.argv.pop(1)) if len(sys.argv)>1: infile=open(sys.argv.pop(1)) else: infile=sys.stdin A=Air('air.tsv') L=Lava('lava.tsv') readHeaders(sys.modules['__main__'],infile,False) for l in infile: c=eval(l) ss=[] hits={} misses=[] for p in c: ss=safety(p) if ss: for (k,a,l) in ss: try: (aa,ll)=hits[k] aa.update(a) if l is not None: ll.update(l) except KeyError: hits[k]=(a,l) else: misses.append(p) print(c) if hits: print(' %s nearby landing columns'%len(hits)) done={} for k in sorted(hits.keys(),key=lambda k:k[1]): if k[0] not in done: done[k[0]]=1 aa,ll=hits[k] laa=sorted(list(aa)) lowAir=laa[0][0] j=-1 if ll is not None: lll=sorted(list(ll)) highLava=-1 for i,(_,h) in enumerate(lll): if h>highLava and h<lowAir: highLava=h if h+1==lowAir: j=i break if j>-1: lava='['+','.join(str(e) if i!=j else \ "(%s,%s)"%(e[0],RedFmt%e[1]) for i,e in enumerate(lll))+']' lowAir=RedFmt%lowAir else: lava=None else: lava=None print("%s(%s %s %s)@%0.1f: %s %s"%(' ' if j>-1 else '', k[0][0],lowAir,k[0][1],k[1],laa,lava)) else: print(' No nearby landing zones') if infile!=sys.stdin: infile.close()