import random as ra from . import drawing from . import decos class Board(): def __init__(self,p1,p2,p1k,p2k,p1u,p2u): self.grid=[None for _ in range(12)] # p1u/p2u split from original units is because now they can both be in the form 0-5 and it JUST WORKS™ # Haha it had a bug anyway. P2's units were upside down. for k,v in p1u.items(): self.grid[k]=v for k,v in p2u.items(): self.grid[6+(3+k)%6]=v self.p1={}; self.p2={} self.p1['name']=p1; self.p2['name']=p2 self.p1['key']=p1k; self.p2['key']=p2k self.p1['score']=0; self.p2['score']=0 for i in range(len(self.grid)): if self.grid[i] is not None: self.grid[i].code=i for i in self.grid: if i is None: continue # Just gonna sneak this into the name as well, until I support actual names. if i.name=='': i.name=str(i.code) i.board=self if i.cls=='guardian': i.status['guard']=0.5 if i.cls=='tactician': start=i.code//6%2*6 targs=[n for n in self.getunits(*list(range(start,start+6)),codes=True)] bufftargs=[] for n in targs: bufftargs.extend([(n,m) for m in ['atk','def','int','spd'] if m not in n.status]) bufftargs=ra.sample(bufftargs,3) for n in bufftargs: n[0].status[n[1]]=0.1*i.int i.speedval=i.aspd(70)+ra.random()*0.0001 self.turn=0 def controller(self): # The main game loop thing. # The two yield statements do serve a purpose. # Sometimes we don't want anything back in (when a charged action is to occur) # So we send a code that says "don't send us anything next step" along with the result # Setup stuff goes here? Maybe? while self.uptobat(): try: u=self.getactive() except AttributeError: break try: if 'charging' in u.status: action=yield None result=self.act2(u,*u.status['action']) u.status.pop('action',None) u.status.pop('charging',None) else: actviews=[] lerst=self.bs() for action in u.actions: actd=actinfo[action] spd=u.aspd(actd.get('startup',actd['recovery'])) after=self.bs(spd) actviews.append((action,f"flags: {actd['flags']}",f"re-q: {after} (after {lerst[after-1].name})")) action=yield ((self.p1['name'],self.p1['key']) if u.code<6 else (self.p2['name'],self.p2['key']), u.name, actviews) u.status.pop('action',None) # If he got cancelled while charging, clean up result=self.act1(u,*action) except decos.RanceException as ex: result=str(ex) yield result return f"Good game, {self.p1['name'] if self.p1['score']>self.p2['score'] else self.p2['name'] if self.p1['score']30: return False # Game's over. return True def twizzle(self,leftside): # This is very broken, needs to fix turn order stuff. # It's less broken now but it's still kinda bad. if leftside: temp=self.grid[0:3] self.grid[0:3]=self.grid[3:6] self.grid[3:6]=temp else: temp=self.grid[9:12] self.grid[9:12]=self.grid[6:9] self.grid[6:9]=temp for i in range(12): try: self.grid[i].code=i except AttributeError: continue def act1(self,u,action,target=None,*_): actd=actinfo[action] t=self.getunits(target,action=action) if t is not None: t=t[0] if u.curflags=0 else 10,u.curflags) #if u.curflags==0: self.order.pop(u.code) return scores[2] def getunits(self,*units,action=None,codes=False,dead=False): # The mega get function. No grid access should occur without this being called. if action: # We're in targeting mode. if 'target' not in actinfo[action]['attrs']: return None if len(units)!=1 or units[0] is None: raise decos.RanceException(f'You must target one unit with {action}') out=self.resolvenames(*units,codes=codes,dead=dead) if not dead: out=[u for u in out if 'dead' not in u.status] # Not sure why this line is here, if dead is False it should be correctly filtered out in resolvenames. if action and not out: raise decos.RanceException(f'Invalid target for {action}') return out def resolvenames(self,*units,codes=False,dead=False): if codes: return [u for u in self.grid if u is not None and u.code in units and ((not dead) or 'dead' not in u.status)] names={u:u.name for u in self.grid if u is not None} out=[] for unit in units: res=[k for k,v in names.items() if v==unit] if len(res)!=1: try: o=self.grid[int(unit)] except ValueError: raise decos.RanceException(f'Name {unit} is ambiguous; matches {len(res)} units') if o is not None: out.append(o) else: out.append(res[0]) return out def __str__(self): return drawing.drawboard(self) def getactive(self): try: return self.bs()[0] except IndexError: return None def bs(self,sim=None): out=[x for x in self.grid if x is not None and x.curflags>0] if sim is not None: out2={x.code:x.speedval for x in out} out2[-1]=sim ind=sorted(out2.items(),key=lambda x:x[1]).index((-1,sim)) return ind return sorted(out,key=lambda x:x.speedval)