Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- # This file is called flora.py and the release is 2
- # Wolf Mathwig wrote this stuff and uploaded it to the internet on 2012-07-02
- # It is a submission for the first NeoGAF Weekly Recreational Programming Challenge
- #
- # It was a Monday. Windows prompted a change.
- #
- # This is is a script developed for Python 2.6.7 on Mac OS X
- # It needs a terminal that supports UTF-8 and ANSI terminal colors
- #
- # The output only looks perfect if the font you're using includes block characters,
- # and has perfect spacing (this is not necessarily the case for arbitrary reasons)
- #
- # Optimal font properties:
- # Menlo Regular 14 pt.
- # Distance between letters: 1
- # Distance between rows: 0.81
- #
- # If something breaks, hit me: [email protected]
- import random, sys, os, time
- random.seed()
- height, width = 0,0
- bad_start = 0
- try:
- height, width = os.popen('stty size', 'r').read().split()
- height = int(height)
- width = int(width)
- except:
- try:
- from ctypes import windll, create_string_buffer
- # stdin handle is -10
- # stdout handle is -11
- # stderr handle is -12
- h = windll.kernel32.GetStdHandle(-12)
- csbi = create_string_buffer(22)
- res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
- if res:
- import struct
- (bufx, bufy, curx, cury, wattr,
- left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
- width = right - left + 1
- height = bottom - top + 1
- else:
- width, height = 80, 25 # can't determine actual size - return default values
- except:
- print "I cannot determine your console size. Please provide your console dimensions in characters."
- try:
- width = int(raw_input('Width: '))
- height = int(raw_input('Height: '))
- except:
- bad_start = 1
- print "You provided input I cannot work with. I will use 20x20"
- width = 20
- height = 20
- if not bad_start:
- print "Console dimensions: "+str(width)+"x"+str(height)
- if int(height)<15:
- print "Console height is 15 characters minimum. Sorry."
- sys.exit()
- if bad_start:
- print "I will continue working in 5 seconds."
- time.sleep(5)
- canvas = {'dx': ((width-1)/2*2)*2, 'dy': ((height-3)/2*2)*2, 'pic':[]}
- color = {'dx':canvas['dx']/2, 'dy':canvas['dy']/2, 'pic':[]}
- sleep_time = 0.05
- global_counter = 0
- runs = 0
- max_y = canvas['dy']-2
- if max_y<0:
- max_y = 2
- raster = { "0000":" ",
- "0001":"▗",
- "0010":"▖",
- "0011":"▄",
- "0100":"▝",
- "0101":"▐",
- "0110":"▞",
- "0111":"▟",
- "1000":"▘",
- "1001":"▚",
- "1010":"▌",
- "1011":"▙",
- "1100":"▀",
- "1101":"▜",
- "1110":"▛",
- "1111":"█",
- }
- # Raster ANSI escape colours
- bl = '\033[30m'
- blu = '\033[44m'
- b1 = '\033[31m'
- b2 = '\033[91m'
- g1 = '\033[32m'
- g2 = '\033[92m'
- p1 = '\033[35m'
- p2 = '\033[95m'
- # Nulling the canvas data structure
- for y in range(0, canvas['dy']):
- canvas['pic'].append([])
- for x in range(0, canvas['dx']):
- pp = 0
- # Frame with random pixels (UNUSED because scrolling makes it look weird)
- #if x == 0 or x == canvas['dx']-1 or y == 0 or y == canvas['dy']-1:
- # pp = random.randint(0,1)
- canvas['pic'][y].append(pp)
- # Nulling color to blue background
- for y in range(0, color['dy']):
- color['pic'].append([])
- for x in range(0, color['dx']):
- color['pic'][y].append(blu)
- # Hint: We grow downwards, display flipped
- # Decode data structure and display it
- def pic_decode():
- global global_counter, runs
- i = 0
- p = 0
- c = 0
- outp = ""
- # Scrolling driver
- init_i = global_counter%color['dx']
- trans = []
- while p < len(canvas['pic']):
- trans.append([])
- i = 0
- while i < len(canvas['pic'][p]):
- trans[p/2].append(str(canvas['pic'][p][i])+str(canvas['pic'][p][i+1])+\
- str(canvas['pic'][p+1][i])+str(canvas['pic'][p+1][i+1]))
- i += 2
- p += 2
- if os.name == "posix":
- # Unix/Linux/MacOS/BSD/etc
- os.system('clear')
- #print "cls"
- elif os.name in ("nt", "dos", "ce"):
- # DOS/Windows
- os.system('CLS')
- # Fill and output data and color
- for f1 in range(0, len(trans)):
- print outp
- outp = ""
- i = init_i
- # Scroll: Left portion is what's right of i
- for f2 in range(i, len(trans[f1])):
- outp += color['pic'][f1][f2] + raster[trans[f1][f2]]
- # Scroll: Right portion is what's left of i
- for f2 in range(0, init_i):
- outp += color['pic'][f1][f2] + raster[trans[f1][f2]]
- # Stats barf
- print "\033[0mSTEP "+ '_'*(6-len(str(global_counter))) +str(global_counter)+\
- " RUNS "+str(runs)
- global_counter += 1
- time.sleep(sleep_time)
- # UNUSED -- Randomized pixels
- def randomized(runs):
- for i in range(0,runs):
- for y in range(0, canvas['dy']):
- for x in range(0, canvas['dx']):
- canvas['pic'][y][x] = random.randint(0,1)
- pic_decode()
- # Determine slope and y at x=0
- def linfunc(start,end):
- x = end['x'] - start['x']
- y = end['y'] - start['y']
- slope = 0
- b = 0
- try:
- slope = y / x
- b = start['y']-slope*start['x']
- except:
- # Division by zero
- slope = 0
- b = 0
- return {'slope':slope, 'b':b}
- # Draw a line
- # col is a toggle between grass and tree
- # hint is for determining which line in a wider segment is drawn
- def line(start, end, col, hint=0):
- global max_y, runs
- slope = linfunc(start, end)
- b = slope['b']
- slope = slope['slope']
- x = start['x']
- y = start['y']
- if not slope:
- return start
- for j in range(start['y'], end['y']):
- if j > (max_y-random.randint(0, 15)):
- #print "exceed"
- break
- try:
- old_x = x
- old_y = y
- x = (j-b)/slope
- y = j-1
- try:
- canvas['pic'][len(canvas['pic'])-y][x] = 1
- if col:
- if (end['y']-y) >2:
- c_pick = g1
- else:
- c_pick = g2
- else:
- if not random.randint(0, 30):
- if random.randint(0,1):
- c_pick = p2
- else:
- c_pick = p1
- else:
- if not hint:
- c_pick = b1
- if hint==1:
- c_pick = b2
- if hint==-1:
- c_pick = bl
- color['pic'][(len(canvas['pic'])-y)/2][x/2] = c_pick
- except:
- #print str(x)+"."+str(y)+": out of array"
- x = old_x
- y = old_y
- break
- except:
- #print "div by 0"
- break
- if random.randint(0,runs)==0:
- pic_decode()
- # We return the last-drawn position so that segments can continue there
- return {'x':x, 'y':y}
- # Draw a number of grass leaves with a height range
- def grass(stems, height):
- for i in range(0, stems):
- c_height = random.randint(height['min'], height['max'])
- x = random.randint(0, canvas['dx']-2)
- if x > ((height['min']+ height['max']) / 2) and random.randint(0, 5) > 1:
- c_height = random.randint(height['min'],\
- height['min'] + (height['min']+ height['max']) / 2)
- target = random.randint(-c_height, c_height)
- line({'x':x, 'y':2}, {'x':x+target, 'y':c_height}, 1)
- # Draw a flower stem segment
- def flowerstem_segment(start, end, thickness, overdraw):
- result = {'x':start['x'], 'y':start['y']}
- slope = linfunc(start, end)
- x = start['x']
- for t in range(0, thickness):
- factor = -1
- c_t = t
- result = line(
- {'x':start['x'], 'y':start['y']},
- {'x':end['x'], 'y':end['y']}, 0,1)
- while c_t > 0:
- factor *= -1
- line(
- {'x':start['x'] +c_t*factor, 'y':start['y']},
- {'x':end['x'] +c_t*factor, 'y':end['y']}, 0)
- c_t -= 1
- result['y'] += 1
- if not t:
- continue
- line({'x':start['x']+t, 'y':start['y']}, {'x':end['x']+t, 'y':end['y']}, 0)
- # SHADOW
- line({'x':start['x']+t+1, 'y':start['y']}, {'x':end['x']+t+1, 'y':end['y']}, 0, -1)
- return result
- # Draw a flower stem, which itself consists of flower stem segments
- # variance determines height and width variance for segments
- # overdraw is unused
- def flowerstem(variance, thickness, overdraw, height, segments, pos={'x':-1,'y':-1}):
- if not segments:
- segments = random.randint(3, 15)
- s = 0
- if pos['x']==-1:
- pos = {'x':random.randint(thickness, canvas['dx']-thickness), 'y':0}
- while pos['y']<height and s < segments:
- grass(random.randint(0,1), {'min':2, 'max':canvas['dy']/random.randint(8,12)})
- c_variance_x = random.randint(0, variance)
- c_variance_y = random.randint(1, (int(variance*0.6)%12)+2)
- end = { 'x':random.randint(pos['x']-c_variance_x/2, pos['x']+c_variance_x),
- 'y':random.randint(pos['y']+1, pos['y']+c_variance_y)}
- pos = flowerstem_segment(pos, end, thickness, overdraw)
- if thickness > 1 and not random.randint(0,1):
- c_thickness = thickness - 1
- flowerstem(variance*2, c_thickness, overdraw, height, s, {'x':pos['x'],'y':pos['y']})
- s += 1
- # Draw a bunch of flowers
- def flowers(stems):
- global max_y
- for i in range(0, stems):
- flowerstem( random.randint(3, 8), # variance
- random.randint(2, 6), # thickness
- random.randint(0, 1), # overdraw
- random.randint(10, max_y), # height
- random.randint(0, 10)) # segments
- # How many times do we repeat the basic thing?
- runs = random.randint(3, 100)
- while runs > 0:
- try:
- if random.randint(0,2):
- grass(random.randint(10,35), {'min':2, 'max':canvas['dy']/random.randint(4,9)})
- if random.randint(0,1):
- flowers(random.randint(1,2))
- except KeyboardInterrupt:
- runs = 0
- runs -= 1
- pic_decode()
- # We have to reset the terminal color
- print "\033[0m"
Advertisement
Add Comment
Please, Sign In to add comment