Guest User

flora_bw.py

a guest
Jul 1st, 2012
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.17 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2.  
  3. # This file is called flora_bw.py and the release is 1
  4. # Wolf Mathwig wrote this stuff and uploaded it to the internet on 2012-07-02
  5. # It is an addendum to a submission for the first NeoGAF Weekly Recreational Programming Challenge
  6. #
  7. # It was a Monday. Windows cmd knew no mercy.
  8. #
  9. # This is is a script developed for Python 2.6.7 on Mac OS X
  10. #
  11. # If something breaks, hit me: [email protected]
  12.  
  13. import random, sys, os, time
  14.  
  15. random.seed()
  16.  
  17. height, width = 0,0
  18.  
  19. bad_start = 0
  20.  
  21. try:
  22.     height, width = os.popen('stty size', 'r').read().split()
  23.     height  = int(height)
  24.     width   = int(width)
  25. except:
  26.     try:
  27.         from ctypes import windll, create_string_buffer
  28.    
  29.         # stdin handle is -10
  30.         # stdout handle is -11
  31.         # stderr handle is -12
  32.    
  33.         h = windll.kernel32.GetStdHandle(-12)
  34.         csbi = create_string_buffer(22)
  35.         res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
  36.    
  37.         if res:
  38.             import struct
  39.             (bufx, bufy, curx, cury, wattr,
  40.              left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
  41.             width = right - left + 1
  42.             height = bottom - top + 1
  43.         else:
  44.             width, height = 80, 25 # can't determine actual size - return default values
  45.     except:
  46.         print "I cannot determine your console size. Please provide your console dimensions in characters."
  47.         try:
  48.             width = int(raw_input('Width: '))
  49.             height = int(raw_input('Height: '))
  50.         except:
  51.             bad_start = 1
  52.             print "You provided input I cannot work with. I will use 20x20"
  53.             width = 20
  54.             height = 20
  55. if not bad_start:
  56.     print "Console dimensions: "+str(width)+"x"+str(height)
  57. if int(height)<15:
  58.   print "Console height is 15 characters minimum. Sorry."
  59.   sys.exit()
  60.  
  61. if bad_start:
  62.   print "I will continue working in 5 seconds."
  63.   time.sleep(5)
  64.  
  65. canvas =  {'dx': ((width-1)/2*2)*2, 'dy': ((height-3)/2*2)*2, 'pic':[]}
  66. color = {'dx':canvas['dx']/2, 'dy':canvas['dy']/2, 'pic':[]}
  67.  
  68. sleep_time = 0.05
  69.  
  70. global_counter = 0
  71. runs = 0
  72.  
  73. max_y = canvas['dy']-2
  74. if max_y<0:
  75.   max_y = 2
  76.  
  77. raster = {  "0000":" ",
  78.             "0001":",",
  79.             "0010":".",
  80.             "0011":"_",
  81.             "0100":"'",
  82.             "0101":"]",
  83.             "0110":"/",
  84.             "0111":"J",
  85.             "1000":"*",
  86.             "1001":"\\",
  87.             "1010":"[",
  88.             "1011":"L",
  89.             "1100":"*",
  90.             "1101":"?",
  91.             "1110":"F",
  92.             "1111":"#",
  93.             }
  94.  
  95. # Raster ANSI escape colours
  96. bl = '\033[30m'
  97. blu = '\033[44m'
  98. b1 = '\033[31m'
  99. b2 = '\033[91m'
  100. g1 = '\033[32m'
  101. g2 = '\033[92m'
  102. p1 = '\033[35m'
  103. p2 = '\033[95m'
  104.  
  105. # Nulling the canvas data structure
  106. for y in range(0, canvas['dy']):
  107.   canvas['pic'].append([])
  108.   for x in range(0, canvas['dx']):
  109.     pp = 0
  110.     # Frame with random pixels (UNUSED because scrolling makes it look weird)
  111.     #if x == 0 or x == canvas['dx']-1 or y == 0 or y == canvas['dy']-1:
  112.     #  pp = random.randint(0,1)
  113.     canvas['pic'][y].append(pp)
  114.  
  115. # Hint: We grow downwards, display flipped
  116.  
  117. # Decode data structure and display it
  118. def pic_decode():
  119.   global global_counter, runs
  120.   i = 0
  121.   p = 0
  122.   c = 0
  123.   outp = ""
  124.  
  125.   # Scrolling driver
  126.   init_i = global_counter%color['dx']
  127.  
  128.   trans = []
  129.  
  130.   while p < len(canvas['pic']):
  131.     trans.append([])
  132.     i = 0
  133.     while i < len(canvas['pic'][p]):
  134.       trans[p/2].append(str(canvas['pic'][p][i])+str(canvas['pic'][p][i+1])+\
  135.                         str(canvas['pic'][p+1][i])+str(canvas['pic'][p+1][i+1]))
  136.       i += 2
  137.     p += 2
  138.  
  139.   if os.name == "posix":
  140.     # Unix/Linux/MacOS/BSD/etc
  141.     os.system('clear')
  142.     #print "cls"
  143.   elif os.name in ("nt", "dos", "ce"):
  144.     # DOS/Windows
  145.     os.system('CLS')
  146.    
  147.   # Fill and output data and color
  148.   for f1 in range(0, len(trans)):
  149.     print outp
  150.     outp = ""
  151.     i = init_i
  152.  
  153.     # Scroll: Left portion is what's right of i
  154.     for f2 in range(i, len(trans[f1])):
  155.       outp += raster[trans[f1][f2]]
  156.     # Scroll: Right portion is what's left of i
  157.     for f2 in range(0, init_i):
  158.       outp += raster[trans[f1][f2]]
  159.  
  160.   # Stats barf
  161.   print "STEP "+ '_'*(6-len(str(global_counter))) +str(global_counter)+\
  162.         "   RUNS "+str(runs)
  163.  
  164.   global_counter += 1
  165.   time.sleep(sleep_time)
  166.  
  167. # UNUSED -- Randomized pixels
  168. def randomized(runs):
  169.   for i in range(0,runs):
  170.     for y in range(0, canvas['dy']):
  171.       for x in range(0, canvas['dx']):
  172.         canvas['pic'][y][x] = random.randint(0,1)
  173.     pic_decode()
  174.  
  175. # Determine slope and y at x=0
  176. def linfunc(start,end):
  177.   x = end['x'] - start['x']
  178.   y = end['y'] - start['y']
  179.   slope = 0
  180.   b = 0
  181.   try:
  182.     slope = y / x
  183.     b = start['y']-slope*start['x']
  184.   except:
  185.     # Division by zero
  186.     slope = 0
  187.     b = 0
  188.   return {'slope':slope, 'b':b}
  189.  
  190. # Draw a line
  191. # col is a toggle between grass and tree
  192. # hint is for determining which line in a wider segment is drawn
  193. def line(start, end, col, hint=0):
  194.   global max_y, runs
  195.   slope = linfunc(start, end)
  196.   b = slope['b']
  197.   slope = slope['slope']
  198.   x = start['x']
  199.   y = start['y']
  200.   if not slope:
  201.     return start
  202.   for j in range(start['y'], end['y']):
  203.     if j > (max_y-random.randint(0, 15)):
  204.       #print "exceed"
  205.       break
  206.     try:
  207.       old_x = x
  208.       old_y = y
  209.       x = (j-b)/slope
  210.       y = j-1
  211.       try:
  212.         canvas['pic'][len(canvas['pic'])-y][x] = 1
  213.         if col:
  214.           if (end['y']-y) >2:
  215.             c_pick = g1
  216.           else:
  217.             c_pick = g2
  218.         else:
  219.           if not random.randint(0, 30):
  220.             if random.randint(0,1):
  221.               c_pick = p2
  222.             else:
  223.               c_pick = p1
  224.           else:
  225.             if not hint:
  226.               c_pick = b1
  227.             if hint==1:
  228.               c_pick = b2
  229.             if hint==-1:
  230.               c_pick = bl
  231.       except:
  232.         #print str(x)+"."+str(y)+": out of array"
  233.         x = old_x
  234.         y = old_y
  235.         break
  236.     except:
  237.       #print "div by 0"
  238.       break
  239.     if random.randint(0,runs)==0:
  240.       pic_decode()
  241.  
  242.   # We return the last-drawn position so that segments can continue there
  243.   return {'x':x, 'y':y}
  244.  
  245. # Draw a number of grass leaves with a height range
  246. def grass(stems, height):
  247.   for i in range(0, stems):
  248.     c_height = random.randint(height['min'], height['max'])
  249.     x = random.randint(0, canvas['dx']-2)
  250.     if x > ((height['min']+ height['max']) / 2) and random.randint(0, 5) > 1:
  251.       c_height = random.randint(height['min'],\
  252.                                 height['min'] + (height['min']+ height['max']) / 2)
  253.     target = random.randint(-c_height, c_height)
  254.     line({'x':x, 'y':2}, {'x':x+target, 'y':c_height}, 1)
  255.  
  256. # Draw a flower stem segment
  257. def flowerstem_segment(start, end, thickness, overdraw):
  258.   result = {'x':start['x'], 'y':start['y']}
  259.   slope = linfunc(start, end)
  260.   x = start['x']
  261.   for t in range(0, thickness):
  262.     factor = -1
  263.     c_t = t
  264.     result = line(
  265.                 {'x':start['x'], 'y':start['y']},
  266.                 {'x':end['x'], 'y':end['y']}, 0,1)
  267.     while c_t > 0:
  268.       factor *= -1
  269.       line(
  270.                 {'x':start['x'] +c_t*factor, 'y':start['y']},
  271.                 {'x':end['x']   +c_t*factor, 'y':end['y']}, 0)
  272.       c_t -= 1
  273.     result['y'] += 1
  274.     if not t:
  275.       continue
  276.     line({'x':start['x']+t, 'y':start['y']}, {'x':end['x']+t, 'y':end['y']}, 0)
  277.     # SHADOW
  278.     line({'x':start['x']+t+1, 'y':start['y']}, {'x':end['x']+t+1, 'y':end['y']}, 0, -1)
  279.   return result
  280.  
  281. # Draw a flower stem, which itself consists of flower stem segments
  282. # variance determines height and width variance for segments
  283. # overdraw is unused
  284. def flowerstem(variance, thickness, overdraw, height, segments, pos={'x':-1,'y':-1}):
  285.   if not segments:
  286.     segments = random.randint(3, 15)
  287.   s = 0
  288.   if pos['x']==-1:
  289.     pos = {'x':random.randint(thickness, canvas['dx']-thickness), 'y':0}
  290.   while pos['y']<height and s < segments:
  291.     grass(random.randint(0,1), {'min':2, 'max':canvas['dy']/random.randint(8,12)})
  292.     c_variance_x = random.randint(0, variance)
  293.     c_variance_y = random.randint(1, (int(variance*0.6)%12)+2)
  294.     end = { 'x':random.randint(pos['x']-c_variance_x/2, pos['x']+c_variance_x),
  295.             'y':random.randint(pos['y']+1, pos['y']+c_variance_y)}
  296.     pos = flowerstem_segment(pos, end, thickness, overdraw)
  297.     if thickness > 1 and not random.randint(0,1):
  298.       c_thickness = thickness - 1
  299.       flowerstem(variance*2, c_thickness, overdraw, height, s, {'x':pos['x'],'y':pos['y']})
  300.     s += 1
  301.  
  302. # Draw a bunch of flowers
  303. def flowers(stems):
  304.   global max_y
  305.   for i in range(0, stems):
  306.     flowerstem( random.randint(3, 8),       # variance
  307.                 random.randint(2, 6),       # thickness
  308.                 random.randint(0, 1),       # overdraw
  309.                 random.randint(10, max_y),  # height
  310.                 random.randint(0, 10))      # segments
  311.  
  312. # How many times do we repeat the basic thing?
  313. runs = random.randint(3, 100)
  314. while runs > 0:
  315.   try:
  316.     if random.randint(0,2):
  317.       grass(random.randint(10,35), {'min':2, 'max':canvas['dy']/random.randint(4,9)})
  318.     if random.randint(0,1):
  319.       flowers(random.randint(1,2))
  320.   except KeyboardInterrupt:
  321.     runs = 0
  322.   runs -= 1
  323.  
  324. pic_decode()
  325.  
  326. # We have to reset the terminal color
Advertisement
Add Comment
Please, Sign In to add comment