Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

More things...

  • Loading branch information...
commit bf7ab27d4773fda7ccde13eefeb189b419404057 1 parent 10c0aa7
Dolkar authored
140 CachedSystemRandom.py
... ... @@ -0,0 +1,140 @@
  1 +"""
  2 +Created: 11.1.2012
  3 +Version: 0.1
  4 +Author: Dolkar
  5 +License: None
  6 +
  7 +Cryptografically safe pseudo-random generator using os.urandom.
  8 +Standard random module already has one such generator, SystemRandom, which is
  9 +pretty inefficient because of large os.urandom overhead. This one minimizes
  10 +the loss by loading random data in large chunks (10KiB by default). It also uses
  11 +struct for unpacking the raw binary randomness, which is faster than
  12 +binascii.hexlify.
  13 +
  14 +Run the file for speed comparisons. If you find anything that can be implemented
  15 +more efficiently... let me know.
  16 +"""
  17 +
  18 +
  19 +import random as _random
  20 +from os import urandom as _urandom
  21 +from binascii import hexlify as _hexlify
  22 +from struct import unpack_from as _unpack_from
  23 +
  24 +BPF = 53 # Number of bits in a float
  25 +FLOAT_CONV_CONSTANT = 2 ** -(BPF + 11) # For 8-byte int to [0, 1) float range
  26 +
  27 +_CACHE_SIZE = 10240
  28 +
  29 +__all__ = ["CachedSystemRandom", "random", "uniform", "randint", "choice",
  30 + "sample", "randrange", "shuffle", "normalvariate", "lognormvariate",
  31 + "expovariate", "vonmisesvariate", "gammavariate", "triangular",
  32 + "betavariate", "paretovariate", "weibullvariate", "getrandbits"]
  33 +
  34 +class CachedSystemRandom(_random.Random):
  35 + def __init__(self, cache_size = _CACHE_SIZE):
  36 + """
  37 + CachedSystemRandom(cache_size = 10240): Creates a random number
  38 + generator with given cache size in bytes.
  39 + """
  40 + self._source = _urandom
  41 + self._cache_size = cache_size
  42 + self.refresh()
  43 +
  44 + def getrandbits(self, k):
  45 + """
  46 + getrandbits(k) -> x. Generates a long int with k random bits.
  47 + Used for covering very large ranges"""
  48 + if k <= 0:
  49 + raise ValueError('number of bits must be greater than zero')
  50 + if k != int(k):
  51 + raise TypeError('number of bits should be an integer')
  52 +
  53 + bytes = (k + 7) // 8 # bits / 8 and rounded up
  54 +
  55 + data = self._cache[self._pos:self._pos + bytes]
  56 +
  57 + bytes_left = self._cache_size - self._pos
  58 + if bytes >= bytes_left:
  59 + if bytes > self._cache_size:
  60 + data = ''.join((data, self._source(bytes - bytes_left)))
  61 + self.refresh()
  62 + else:
  63 + self.refresh()
  64 + self._pos = bytes - bytes_left
  65 + data = ''.join((data, self._cache[:self._pos]))
  66 + else:
  67 + self._pos += bytes
  68 +
  69 + return long(_hexlify(data), 16) >> (bytes * 8 - k) # trim excess bits
  70 +
  71 + def refresh(self):
  72 + """Drops all current catched data and fetches some new."""
  73 + # 8 extra bytes to ensure enough space for a random call
  74 + self._cache = self._source(self._cache_size + 8)
  75 + self._pos = 0
  76 +
  77 + def random(self):
  78 + """Get the next random number in the range [0.0, 1.0)."""
  79 + value = _unpack_from('Q', self._cache, self._pos)[0] * FLOAT_CONV_CONSTANT
  80 + self._pos += 8
  81 + if self._pos >= self._cache_size:
  82 + self.refresh()
  83 + return value
  84 +
  85 + def _stub(self, *args, **kwds):
  86 + "Stub method. Not used for a system random number generator."
  87 + return None
  88 + seed = jumpahead = _stub
  89 +
  90 + def _notimplemented(self, *args, **kwds):
  91 + "Method should not be called for a system random number generator."
  92 + raise NotImplementedError('System entropy source does not have state.')
  93 + getstate = setstate = _notimplemented
  94 +
  95 +_inst = CachedSystemRandom()
  96 +random = _inst.random
  97 +uniform = _inst.uniform
  98 +triangular = _inst.triangular
  99 +randint = _inst.randint
  100 +choice = _inst.choice
  101 +randrange = _inst.randrange
  102 +sample = _inst.sample
  103 +shuffle = _inst.shuffle
  104 +normalvariate = _inst.normalvariate
  105 +lognormvariate = _inst.lognormvariate
  106 +expovariate = _inst.expovariate
  107 +vonmisesvariate = _inst.vonmisesvariate
  108 +gammavariate = _inst.gammavariate
  109 +betavariate = _inst.betavariate
  110 +paretovariate = _inst.paretovariate
  111 +weibullvariate = _inst.weibullvariate
  112 +getrandbits = _inst.getrandbits
  113 +
  114 +if __name__ == '__main__':
  115 + from timeit import timeit
  116 +
  117 + R = _random.Random()
  118 + SR = _random.SystemRandom()
  119 + CSR = CachedSystemRandom()
  120 + setup = 'from __main__ import CSR, SR, R'
  121 +
  122 + def testMethod(name, number):
  123 + a = timeit('R.%s' % name, setup, number = number) * 1000
  124 + b = timeit('SR.%s' % name, setup, number = number) * 1000
  125 + c = timeit('CSR.%s' % name, setup, number = number) * 1000
  126 + print "%25s %8.3f ms %12.3f ms %14.3f ms" % (name, a, b, c)
  127 +
  128 + print " call Random SystemRandom C.SystemRandom"
  129 + print
  130 + testMethod('random()', 100000)
  131 + testMethod('randrange(100000)', 10000)
  132 + testMethod('randrange(2**100)', 10000)
  133 + testMethod('uniform(0, 2**100)', 10000)
  134 + testMethod('choice(range(1000))', 10000)
  135 + testMethod('shuffle(range(1000))', 100)
  136 + testMethod('gammavariate(1.0,1.0)', 10000)
  137 + print
  138 + testMethod('getrandbits(2)', 100000)
  139 + testMethod('getrandbits(2**10)', 10000)
  140 + testMethod('getrandbits(2**20)', 100)
10 README.txt
@@ -11,4 +11,12 @@ shunting - A shunting yard algorithm implementation for converting infix to post
11 11 Useful for mathematical or logical expressions. Handles parentheses. Not well documented.
12 12
13 13 vector - A hopefully easy to use vector class for computations with vectors.
14   -I made it a long time ago and would probably change few things in there...
  14 +I made it a long time ago and would probably change few things in there...
  15 +
  16 +CachedSystemRandom - An efficient cryptographically secure random number generator.
  17 +
  18 +randomShapes - A screensaver showing randomly generated "shapes". Pretty nice to watch.
  19 +
  20 +snake - A simple snake-like game on wrapped map with centered camera. Brings a new
  21 + feel to the old snake. Control the snake with arrows and try to eat food
  22 + before it's too late...
194 randomShapes.py
... ... @@ -0,0 +1,194 @@
  1 +import random
  2 +import pygame
  3 +from vector import Vector
  4 +from math import radians
  5 +from colorsys import hsv_to_rgb
  6 +
  7 +DIM = (800, 600)
  8 +ESCAPE_EVENTS = set([pygame.KEYDOWN, pygame.MOUSEMOTION, pygame.MOUSEBUTTONDOWN, pygame.QUIT])
  9 +JOINTS = 3
  10 +WAIT_TIME = 500 # 10 seconds
  11 +
  12 +class Joint(object):
  13 + def __init__(self, length, sharpness = 180):
  14 + self.length = length
  15 + self.sharpness = sharpness
  16 + self.step = random.randrange(-sharpness, sharpness) % 360
  17 + self.start = random.randrange(360)
  18 + self.angle = self.start
  19 +
  20 + def getPos(self):
  21 + return Vector.polar(radians(self.angle), self.length)
  22 +
  23 + def rotate(self):
  24 + """Rotates the joint and returns True if it did a full circle already."""
  25 + self.angle = (self.angle + self.step) % 360
  26 + return self.angle == self.start
  27 +
  28 +
  29 +class ShapeDrawer(object):
  30 + def __init__(self, surface, pos, size, joints):
  31 + self.surface = surface
  32 + self.size = size
  33 + self.pos = Vector(pos)
  34 + self.initJoints(joints)
  35 + color = hsv_to_rgb(random.random(), random.random() * 0.6 + 0.2, 1)
  36 + self.color = pygame.Color(*[int(v * 255) for v in color])
  37 +
  38 + self.lines = 0
  39 + self.total_length = 0
  40 +
  41 + def initJoints(self, count):
  42 + sharpness = random.randint(3, 120)
  43 +
  44 + self.joints = []
  45 + for _ in xrange(count):
  46 + self.joints.append(Joint(self.size / float(count), sharpness))
  47 +
  48 + self.last_point = tuple(self.getPos())
  49 +
  50 + def __iter__(self):
  51 + return self
  52 +
  53 + def getPos(self):
  54 + return sum((j.getPos() for j in self.joints), self.pos)
  55 +
  56 + def getMaxStep(self):
  57 + return max(j.sharpness for j in self.joints)
  58 +
  59 + def next(self):
  60 + """Draws a next line and returns relative line length."""
  61 + done = [j.rotate() for j in self.joints]
  62 +
  63 + point = self.getPos()
  64 + pygame.draw.aaline(self.surface, self.color, tuple(point), self.last_point)
  65 + length = (point - self.last_point).mag()
  66 +
  67 + self.last_point = tuple(point)
  68 + self.lines += 1
  69 + self.total_length += length
  70 +
  71 + if all(done): # We are done here...
  72 + raise StopIteration
  73 +
  74 + return length / self.size
  75 +
  76 +class ShapeFader(object):
  77 + """Shape fading process"""
  78 + def __init__(self, surface):
  79 + self.surface = surface
  80 + self.surface.set_colorkey(None)
  81 + self.size = self.surface.get_size()
  82 + self.tick = 0
  83 +
  84 + def step(self):
  85 + if self.tick % 3 == 0 and self.tick < 300:
  86 + rotate(self.surface, self.surface, 3, 1.02)
  87 + self.surface.blit(black, (0, 0))
  88 + self.tick += 1
  89 +
  90 +
  91 +def writeStats(drawer):
  92 + """Draws shape stats on a transparent surface"""
  93 + sharptext = font.render("Sharpness: %s" % drawer.getMaxStep(), True, (255, 180, 0))
  94 + linestext = font.render("Number of lines: %s" % drawer.lines, True, (255, 180, 0))
  95 + lengthtext = font.render("Total length: %s" % int(drawer.total_length), True, (255, 180, 0))
  96 + avg = int(drawer.total_length) / drawer.lines
  97 + averagetext = font.render("Average line length: %s" % avg, True, (255, 180, 0))
  98 +
  99 + surface = pygame.Surface((300, 100))
  100 + surface.set_colorkey((0, 0, 0))
  101 + surface.blit(sharptext, (20, 20))
  102 + surface.blit(linestext, (20, 40))
  103 + surface.blit(lengthtext, (20, 60))
  104 + surface.blit(averagetext, (20, 80))
  105 + return surface
  106 +
  107 +def rotate(surface, source, tick, scale = 1, rate = 2000.0):
  108 + """Rotates surface based on tick and blits it centered."""
  109 + angle = (1 - (tick / rate) % 1) * 360
  110 + rect = source.get_rect()
  111 + rotated = pygame.transform.rotozoom(source, angle, scale)
  112 + rect.center = rotated.get_rect().center
  113 + surface.blit(rotated, (0, 0), rect)
  114 +
  115 +
  116 +pygame.init()
  117 +screen = pygame.display.set_mode(DIM, pygame.FULLSCREEN)
  118 +screen.fill((0, 0, 0))
  119 +pygame.event.clear()
  120 +pygame.mouse.set_visible(False)
  121 +timer = pygame.time.Clock()
  122 +
  123 +font = pygame.font.SysFont('georgia', 13, bold = "True")
  124 +black = pygame.Surface(DIM, flags = pygame.SRCALPHA)
  125 +black.fill((0, 0, 0, 5))
  126 +
  127 +tick = 0
  128 +wait_time = 30
  129 +last_shape = None
  130 +shape = None
  131 +stats = None
  132 +drawer = None
  133 +running = True
  134 +
  135 +
  136 +while running:
  137 + timer.tick(50)
  138 + tick += 1
  139 +
  140 + # Setting...
  141 + if wait_time > 0:
  142 + # Waiting...
  143 + wait_time -= 1
  144 +
  145 + elif drawer:
  146 + # Image is being drawed
  147 + try:
  148 + timemod = drawer.next()
  149 + except StopIteration:
  150 + # Image done, change state...
  151 + stats = writeStats(drawer)
  152 + wait_time = WAIT_TIME
  153 + rot_start_tick = tick
  154 +
  155 + last_shape = None
  156 + drawer = None
  157 + else:
  158 + wait_time = round(2 * timemod)
  159 +
  160 + else:
  161 + if shape:
  162 + # Fading last shape
  163 + rotate(shape, shape, tick - rot_start_tick)
  164 + shape.blit(stats, (0, 0))
  165 + last_shape = ShapeFader(shape)
  166 + stats = None
  167 + # Setting a new drawer...
  168 + shape = pygame.Surface(DIM)
  169 + shape.set_colorkey((0, 0, 0))
  170 + drawer = ShapeDrawer(shape, (400, 300), 300, JOINTS)
  171 + wait_time = 20
  172 +
  173 + # Drawing...
  174 + if last_shape:
  175 + # Blend last shape as background
  176 + last_shape.step()
  177 + screen.blit(last_shape.surface, (0, 0))
  178 +
  179 + if shape:
  180 + if not drawer:
  181 + # Rotate
  182 + rotate(screen, shape, tick - rot_start_tick)
  183 + else:
  184 + screen.blit(shape, (0, 0))
  185 +
  186 + if stats:
  187 + screen.blit(stats, (0, 0))
  188 +
  189 + pygame.display.update()
  190 +
  191 + for event in pygame.event.get():
  192 + if event.type in ESCAPE_EVENTS:
  193 + pygame.quit()
  194 + running = False
128 snake.py
... ... @@ -0,0 +1,128 @@
  1 +import pygame
  2 +from random import randrange
  3 +
  4 +pygame.font.init()
  5 +
  6 +DIFFS = [0.001, 0.0025, 0.005, 0.0075, 0.01]
  7 +
  8 +class Game(object):
  9 + def __init__(self, size, block_size, speed = 10, difficulty = 3, growth = 3):
  10 + self.size = size
  11 + self.block_size = block_size
  12 + self.distance = self.block_size + 1
  13 + self.font = pygame.font.SysFont("consolas", 32, bold = True)
  14 + self.speed = speed
  15 + self.snake = [(size / 2, size / 2)]
  16 + self.dir = (0, -1)
  17 + self.running = True
  18 + self.base_growth = growth
  19 + self.growth = self.base_growth
  20 + self.score_decay_growth = DIFFS[difficulty - 1]
  21 + self.score = 100
  22 + self.turn = 0
  23 +
  24 +
  25 + self.surface = pygame.display.set_mode((size * (block_size + 1),) * 2)
  26 + self.generateFood()
  27 + self.run()
  28 +
  29 + def generateFood(self):
  30 + self.food = (randrange(0, self.size), randrange(0, self.size))
  31 + if self.food in self.snake:
  32 + self.generateFood()
  33 +
  34 + def makeTurn(self):
  35 + newpos = ((self.snake[0][0] + self.dir[0]) % self.size,
  36 + (self.snake[0][1] + self.dir[1]) % self.size)
  37 +
  38 + self.snake = [newpos] + self.snake
  39 +
  40 + if newpos == self.food:
  41 + self.growth += self.base_growth
  42 + self.score += 0.1 * len(self.snake) ** 1.5 + 10
  43 + self.generateFood()
  44 +
  45 + if self.growth > 0:
  46 + self.growth -= 1
  47 + else:
  48 + self.snake.pop()
  49 +
  50 + self.score -= 0.5 + self.score_decay_growth * self.turn
  51 + self.turn += 1
  52 +
  53 + if self.snake.count(newpos) >= 2:
  54 + # collided...
  55 + self.score -= 100
  56 + del(self.snake[0])
  57 +
  58 + if self.score <= 0:
  59 + # the end...
  60 + self.running = False
  61 + self.score = 0
  62 +
  63 + self.showFrame()
  64 +
  65 + def showFrame(self):
  66 + self.surface.fill((0, 0, 0))
  67 + cam_pos = (self.snake[0][0] - self.size / 2, self.snake[0][1] - self.size / 2)
  68 +
  69 + line_y = ((self.size - cam_pos[1]) % self.size * self.distance - 1)
  70 + line_x = ((self.size - cam_pos[0]) % self.size * self.distance - 1)
  71 + pygame.draw.line(self.surface, (60, 60, 60),
  72 + (0, line_y), (self.size * self.distance, line_y))
  73 + pygame.draw.line(self.surface, (60, 60, 60),
  74 + (line_x, 0), (line_x, self.size * self.distance))
  75 +
  76 + shade = 250
  77 + for (x, y) in self.snake:
  78 + pos = ((x - cam_pos[0]) % self.size * self.distance,
  79 + (y - cam_pos[1]) % self.size * self.distance)
  80 + pygame.draw.rect(self.surface, (0, round(shade), 0), (pos, (self.block_size,) * 2))
  81 + shade -= 150.0 / len(self.snake)
  82 +
  83 + foodpos = ((self.food[0] - cam_pos[0]) % self.size * self.distance + self.block_size / 2,
  84 + (self.food[1] - cam_pos[1]) % self.size * self.distance + self.block_size / 2)
  85 + pygame.draw.circle(self.surface, (255, 0, 0), foodpos, self.block_size / 2)
  86 +
  87 + if self.score < 500:
  88 + color = (255, self.score / 2, 0)
  89 + else:
  90 + color = (max((1000 - self.score) / 500 * 255, 0), 255, 0)
  91 +
  92 + sc = self.font.render(str(int(self.score)), True, color)
  93 + width = self.font.size(str(int(self.score)))[0]
  94 +
  95 + turn = self.font.render(str(self.turn), True, (0, 150, 255))
  96 +
  97 + self.surface.blit(sc, (self.size * self.distance - width - 20, 20))
  98 + self.surface.blit(turn, (20, 20))
  99 +
  100 + pygame.display.update()
  101 +
  102 + def run(self):
  103 + clock = pygame.time.Clock()
  104 +
  105 + while True:
  106 + if self.running:
  107 + self.makeTurn()
  108 + clock.tick(self.speed)
  109 +
  110 + event = pygame.event.poll()
  111 + while event and event.type != pygame.KEYDOWN:
  112 + if event.type == pygame.QUIT:
  113 + pygame.quit()
  114 + return
  115 + event = pygame.event.poll()
  116 + if event:
  117 + if self.dir[1]:
  118 + if event.key == pygame.K_LEFT:
  119 + self.dir = (-1, 0)
  120 + elif event.key == pygame.K_RIGHT:
  121 + self.dir = (1, 0)
  122 + else:
  123 + if event.key == pygame.K_UP:
  124 + self.dir = (0, -1)
  125 + elif event.key == pygame.K_DOWN:
  126 + self.dir = (0, 1)
  127 +
  128 +Game(20, 20, 10, difficulty = 3)

0 comments on commit bf7ab27

Please sign in to comment.
Something went wrong with that request. Please try again.