/usr/share/pyshared/pypy/sandbox/rpython/tool/ansi_mandelbrot.py is in python-pypy.sandbox 2.2.1+dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | import sys
from py.io import ansi_print, get_terminal_width
"""
Black 0;30 Dark Gray 1;30
Blue 0;34 Light Blue 1;34
Green 0;32 Light Green 1;32
Cyan 0;36 Light Cyan 1;36
Red 0;31 Light Red 1;31
Purple 0;35 Light Purple 1;35
Brown 0;33 Yellow 1;33
Light Gray 0;37 White 1;37
"""
palette = [39, 34, 35, 36, 31, 33, 32, 37]
colour_range = None # used for debugging
def print_pixel(colour, value_range, invert=1):
global colour_range
chars = [".", ".", "+", "*", "%", "#"]
idx = lambda chars: (colour+1) * (len(chars) - 1) / value_range
if invert:
idx = lambda chars, idx=idx:len(chars) - 1 - idx(chars)
char = chars[idx(chars)]
ansi_colour = palette[idx(palette)]
ansi_print(char, ansi_colour, newline=False, flush=True)
#if colour_range is None:
# colour_range = [colour, colour]
#else:
# colour_range = [min(colour_range[0], colour), max(colour_range[1], colour)]
class Mandelbrot:
def __init__ (self, width=100, height=28, x_pos=-0.5, y_pos=0, distance=6.75):
self.xpos = x_pos
self.ypos = y_pos
aspect_ratio = 1/3.
factor = float(distance) / width # lowering the distance will zoom in
self.xscale = factor * aspect_ratio
self.yscale = factor
self.iterations = 170
self.x = width
self.y = height
self.z0 = complex(0, 0)
def init(self):
self.reset_lines = False
xmin = self.xpos - self.xscale * self.x / 2
ymin = self.ypos - self.yscale * self.y / 2
self.x_range = [xmin + self.xscale * ix for ix in range(self.x)]
self.y_range = [ymin + self.yscale * iy for iy in range(self.y)]
#print "x", self.x_range[0], self.x_range[-1]
#print "y", self.y_range[0], self.y_range[-1]
def reset(self, cnt):
self.reset_lines = cnt
def generate(self):
self.reset_lines = False
iy = 0
while iy < self.y:
ix = 0
while ix < self.x:
c = complex(self.x_range[ix], self.y_range[iy])
z = self.z0
colour = 0
mind = 2
for i in range(self.iterations):
z = z * z + c
d = abs(z)
if d >= 2:
colour = min(int(mind / 0.007), 254) + 1
break
else:
mind = min(d, mind)
yield ix, iy, colour
if self.reset_lines is not False: # jump to the beginning of the line
iy += self.reset_lines
do_break = bool(self.reset_lines)
self.reset_lines = False
if do_break:
break
ix = 0
else:
ix += 1
iy += 1
class Driver(object):
zoom_locations = [
# x, y, "distance", range
(0.37865401, 0.669227668, 0.04, 111),
(-1.15, -0.28, 0.9, 94),
(-1.15, -0.28, 0.3, 58),
(-1.15, -0.28, 0.05, 26),
]
def __init__(self, **kwargs):
self.kwargs = kwargs
self.zoom_location = -1
self.colour_range = 256
self.invert = True
self.init()
def init(self):
self.width = get_terminal_width() or 80 # in some envs, the py lib doesnt default the width correctly
self.mandelbrot = Mandelbrot(width=(self.width or 1), **self.kwargs)
self.mandelbrot.init()
self.gen = self.mandelbrot.generate()
def reset(self, cnt=0):
""" Resets to the beginning of the line and drops cnt lines internally. """
self.mandelbrot.reset(cnt)
def catchup(self):
""" Fills the current line. """
x = 0
while x != self.width - 1:
x, y, c = self.gen.next()
print_pixel(c, self.colour_range, self.invert)
print >>sys.stderr
def restart(self):
""" Restarts the current generator. """
print >>sys.stderr
self.init()
def dot(self):
""" Emits a colourful character. """
x = c = 0
try:
x, y, c = self.gen.next()
if x == 0:
width = get_terminal_width()
if width != self.width:
self.init()
except StopIteration:
kwargs = self.kwargs
self.zoom_location += 1
self.zoom_location %= len(self.zoom_locations)
loc = self.zoom_locations[self.zoom_location]
kwargs.update({"x_pos": loc[0], "y_pos": loc[1], "distance": loc[2]})
self.colour_range = loc[3]
#global colour_range
#print colour_range, loc[2]
#colour_range = None
return self.restart()
print_pixel(c, self.colour_range, self.invert)
if x == self.width - 1:
print >>sys.stderr
if __name__ == '__main__':
import random
from time import sleep
d = Driver()
for x in xrange(15000):
sleep(random.random() / 300)
d.dot()
if 0 and random.random() < 0.01:
d.catchup()
print "WARNING! " * 3
d.reset(1)
# print "R",
if 0 and random.random() < 0.01:
string = "WARNING! " * 3
d.jump(len(string))
print string,
|