import random,time
import Image
#~ import psyco
#~ psyco.full()

white=(255,255,255)
black=(0,0,0)
red=(255,0,0)
green=(0,255,0)
blue=(0,0,255)
colors=[red,green,blue]

class Walker(object):
  def __init__(self,color,switch=5,death=1,orth=False,cw=50,nocross=True):
    self.death=death
    self.nocross=nocross
    self.switch=switch
    self.color=color
    self.orth=orth
    self.cw=cw
    
  def maybe_changedv(self,dv):
    
      
    ndv=dv
    if random.random()*100<self.switch:
      if random.random()*100<self.cw:
        cw=True
      else:
        cw=False
      if cw:
        ndv=(dv+1)%8
      else:
        ndv=(dv-1)%8
      if self.orth:
        if cw:
          ndv=(dv+2)%8
        else:
          ndv=(dv-2)%8
    return ndv

      
  def maybe_die(self):
    if random.random()*100<self.death:
      return True
    return False
    

class Board(object):
  def __init__(self,size,fn):
    self.fn=fn
    self.x=size[0]
    self.y=size[1]
    self.size=size
    self.pix={}
    for xx in range(self.x):
      for yy in range(self.y):
        self.pix[(xx,yy)]=white
        
  def set(self,pos,col):
    self.pix[pos]=col
    
  def make(self):
    im=Image.new('RGB',self.size)
    print 'saving as:',self.fn
    for xx in range(self.x):
      for yy in range(self.y):
        im.putpixel((xx,yy),self.pix[xx,yy])
    sc=1280/max(self.x,self.y)
    ns=(self.x*sc,self.y*sc)
    im=im.resize(ns)
    im.save(self.fn)
  
  def isok(self,pos):
    res = pos[0]>=0 and pos[0]<self.x and pos[1]>=0 and pos[1]<self.y
    #~ res=res and self.pix[pos]==white
    
    return res
    
  def oob(self,pos):
    return pos[0]<0 or pos[1]<0 or pos[0]>=self.x or pos[1]>=self.y
  

def add(pos,dv):
  assert dv>=0 and dv<8,"dv is %s"%str(dv)
  if dv==0:
    return pos[0]+1,pos[1]
  if dv==1:
    return pos[0]+1,pos[1]+1
  if dv==2:
    return pos[0],pos[1]+1
  if dv==3:
    return pos[0]-1,pos[1]+1
  if dv==4:
    return pos[0]-1,pos[1]
  if dv==5:
    return pos[0]-1,pos[1]-1
  if dv==6:
    return pos[0],pos[1]-1
  if dv==7:
    return pos[0]+1,pos[1]-1

def walk(w,b):
  #get start pos.
  st=(random.randrange(b.x),random.randrange(b.y))
  i=0
  while b.pix[st]!=white:
    st=(random.randrange(b.x),random.randrange(b.y))
    i+=1
    if i>100:
      return
  #~ print w.color
  #~ print 'starting at',st
  
  b.set(st,w.color)
  dv=random.randrange(8)
  if w.orth:
    dv=dv-(dv%2)
  
  next=add(st,dv)
  while b.isok(next):
    #~ print 'next is ok:',next
    if dv>3:
      cdv,adv=(dv-2)%4,(dv+1)%4
      cp,ap=add(next,cdv),add(next,adv)
      if w.nocross and ((not b.oob(cp) and b.pix[cp]!=white) and (not b.oob(ap) and b.pix[ap]!=white)):
        #~ print 'breaking, next:',next,ap,cp,b.pix[ap],b.pix[cp]
        break
    b.set(next,w.color)
    next=add(next,dv)
    dv=w.maybe_changedv(dv)
    if w.maybe_die():
      break
    
class Bag:
  pass
      
      

ty='.png'
  
trials=2000

for t in range(trials):
  size=(1280,1024)
  size=(random.randrange(100,1024),random.randrange(100,1024))
  print size
  types=random.choice([1,2,2,4,3,7,40])
  name='paths%d'%int(time.time()*100)
  b=Board(size,name+ty)
  distros=[]
  walkers={}
  print 'types:',types
  for n in range(types):
    w=Bag()
    w.color=(random.randrange(255),random.randrange(255),random.randrange(255))
    w.cw=([0,10,20,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,80,90,100])
    w.switch=random.choice([0,0,1,2,3,5,4,6,10,20,30,40,25,50,80,100])
    w.death=random.choice([0,1,1,1,1,1,1,1,1,1,1,1,5,10,40,90])
    w.nocross=random.choice([True,False])
    w.orth=random.choice([True,False])
    distros+=random.randrange(1,10)*str(n)
    if w.nocross==True or w.orth:
      if w.death==0:
        print 'override death...'
        w.death=4
    walkers[str(n)]=w
  walkercount=random.randrange(1,1000)
  print 'walkercount',walkercount
  for n in range(walkercount):
    if n%100==0:
      print n
    w=walkers[random.choice(distros)]
    w=Walker(w.color,w.switch,death=w.death,cw=w.cw,nocross=w.nocross,orth=w.orth)
    walk(w,b)
  b.make()