diff options
Diffstat (limited to 'game.py')
-rw-r--r-- | game.py | 279 |
1 files changed, 279 insertions, 0 deletions
@@ -0,0 +1,279 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2012 Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU General Public License +# along with this library; if not, write to the Free Software +# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA + + +LEVELS_TRUE = ['def generate_pattern(self):\n\ + # Level 1: Center dot is Red\n\ + dot_list = []\n\ + for i in range(25):\n\ + dot_list.append(self._mun_color.random_hvc(0, 10, 4, 7, 3, 3))\n\ + dot_list[12] = self._mun_color.hvc(0, 5, 3)\n\ + return dot_list\n', + 'def generate_pattern(self):\n\ + # Level 2: Monochrome\n\ + dot_list = []\n\ + h = int(uniform(0, 10))\n\ + for i in range(25):\n\ + dot_list.append(self._mun_color.random_hue(h, h))\n\ + return dot_list\n', + 'def generate_pattern(self):\n\ + # Level 3: Max chroma\n\ + dot_list = []\n\ + for i in range(25):\n\ + dot_list.append(self._mun_color.random_hvc(0, 10, 4, 7, 3, 3))\n\ + return dot_list\n'] +LEVELS_FALSE = ['def generate_pattern(self):\n\ + # Level 1: Center dot is not Red\n\ + dot_list = []\n\ + for i in range(25):\n\ + dot_list.append(self._mun_color.random_hvc(0, 10, 4, 7, 3, 3))\n\ + dot_list[12] = self._mun_color.random_hvc(1, 10, 4, 7, 3, 3)\n\ + return dot_list\n', + 'def generate_pattern(self):\n\ + # Level 2: not monochrome\n\ + dot_list = []\n\ + h = int(uniform(0, 8))\n\ + for i in range(25):\n\ + dot_list.append(self._mun_color.random_hue(h, h + 2))\n\ + return dot_list\n', + 'def generate_pattern(self):\n\ + # Level 3: not max chroma\n\ + dot_list = []\n\ + for i in range(25):\n\ + dot_list.append(self._mun_color.random_hvc(0, 10, 4, 7, 0, 3))\n\ + return dot_list\n'] + + +import gtk +import cairo +import gobject + +from math import sqrt +from random import uniform + +import traceback + +from gettext import gettext as _ + +import logging +_logger = logging.getLogger('reflection-activity') + +try: + from sugar.graphics import style + GRID_CELL_SIZE = style.GRID_CELL_SIZE +except ImportError: + GRID_CELL_SIZE = 0 + +from mun import MunColor +from sprites import Sprites, Sprite + +# Grid dimensions +GRID = 5 +WHITE = 2 +DOT_SIZE = 80 + + +class Game(): + + def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): + self._activity = parent + self._colors = [colors[0]] + self._colors.append(colors[1]) + self._mun_color = MunColor() + self._dot_cache = {} + + self._canvas = canvas + if parent is not None: + parent.show_all() + self._parent = parent + + self._canvas.set_flags(gtk.CAN_FOCUS) + self._canvas.connect("expose-event", self._expose_cb) + + self._width = gtk.gdk.screen_width() + self._height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5) + self._scale = self._width / (10 * DOT_SIZE * 1.2) + self._dot_size = int(DOT_SIZE * self._scale) + self._space = int(self._dot_size / 5.) + self.max_levels = len(LEVELS_TRUE) + self.this_pattern = False + + # Generate the sprites we'll need... + self._sprites = Sprites(self._canvas) + self._dots = [] + self._generate_grid() + + def _generate_grid(self): + ''' Make a new set of dots for a grid of size edge ''' + i = 0 + for y in range(GRID): + for x in range(GRID): + xoffset = int((self._width - GRID * self._dot_size - \ + (GRID - 1) * self._space) / 2.) + xoffset -= int(self._dot_size / 2) # rects aren't centered + if i < len(self._dots): + self._dots[i].move( + (xoffset + x * (self._dot_size + self._space), + y * (self._dot_size + self._space) + self._space)) + else: + self._dots.append( + Sprite(self._sprites, + xoffset + x * (self._dot_size + self._space), + y * (self._dot_size + self._space) + self._space, + self._new_dot(self._colors[0]))) + self._dots[i].type = 0 + self._dots[-1].set_label_attributes(40) + i += 1 + + def show(self, dot_list): + for i in range(GRID * GRID): + self._dots[i].set_shape(self._new_dot(dot_list[i])) + self._dots[i].type = dot_list[i] + + def show_true(self): + self.show(self._generate_pattern(LEVELS_TRUE[self._activity.level])) + self.this_pattern = True + + def show_false(self): + self.show(self._generate_pattern(LEVELS_FALSE[self._activity.level])) + self.this_pattern = False + + def show_random(self): + ''' Fill the grid with a true or false pattern ''' + if int(uniform(0, 2)) == 0: + self.show_true() + else: + self.show_false() + + def _initiating(self): + return self._activity.initiating + + def new_game(self): + ''' Start a new game. ''' + self.show_random() + + def restore_grid(self, dot_list, boolean): + ''' Restore a grid from the share ''' + self.show(dot_list) + self.this_pattern = boolean + + def save_grid(self): + ''' Return dot list for sharing ''' + dot_list = [] + for dot in self._dots: + dot_list.append(dot.type) + return(dot_list, self.this_pattern) + + def _grid_to_dot(self, pos): + ''' calculate the dot index from a column and row in the grid ''' + return pos[0] + pos[1] * GRID + + def _dot_to_grid(self, dot): + ''' calculate the grid column and row for a dot ''' + return [dot % GRID, int(dot / GRID)] + + def _set_label(self, string): + ''' Set the label in the toolbar or the window frame. ''' + self._activity.status.set_label(string) + + def _generate_pattern(self, f): + ''' Run Python code passed as argument ''' + userdefined = {} + try: + exec f in globals(), userdefined + return userdefined['generate_pattern'](self) + except ZeroDivisionError, e: + self._set_label('Python zero-divide error: %s' % (str(e))) + except ValueError, e: + self._set_label('Python value error: %s' % (str(e))) + except SyntaxError, e: + self._set_label('Python syntax error: %s' % (str(e))) + except NameError, e: + self._set_label('Python name error: %s' % (str(e))) + except OverflowError, e: + self._set_label('Python overflow error: %s' % (str(e))) + except TypeError, e: + self._set_label('Python type error: %s' % (str(e))) + except: + self._set_label('Python error') + traceback.print_exc() + return None + + def _expose_cb(self, win, event): + self.do_expose_event(event) + + def do_expose_event(self, event): + ''' Handle the expose-event by drawing ''' + # Restrict Cairo to the exposed area + cr = self._canvas.window.cairo_create() + cr.rectangle(event.area.x, event.area.y, + event.area.width, event.area.height) + cr.clip() + # Refresh sprite list + self._sprites.redraw_sprites(cr=cr) + + def _destroy_cb(self, win, event): + gtk.main_quit() + + def _new_dot(self, color): + ''' generate a dot of a color color ''' + if not color in self._dot_cache: + self._stroke = color + self._fill = color + self._svg_width = self._dot_size * 2 + self._svg_height = self._dot_size * 2 + pixbuf = svg_str_to_pixbuf( + self._header() + \ + self._rect(self._dot_size / 2., self._dot_size / 2., + self._dot_size / 2.) + \ + self._footer()) + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, + self._svg_width, self._svg_height) + context = cairo.Context(surface) + context = gtk.gdk.CairoContext(context) + context.set_source_pixbuf(pixbuf, 0, 0) + context.rectangle(0, 0, self._svg_width, self._svg_height) + context.fill() + self._dot_cache[color] = surface + + return self._dot_cache[color] + + def _header(self): + return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ + 'xmlns="http://www.w3.org/2000/svg"\n' + \ + 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ + 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ + 'height="' + str(self._svg_height) + '">\n' + + def _circle(self, r, cx, cy): + return '<circle style="fill:' + str(self._fill) + ';stroke:' + \ + str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \ + str(cx) + '" cy="' + str(cy) + '" />\n' + + def _rect(self, r, x, y): + return '<rect style="fill:' + str(self._fill) + ';stroke:' + \ + str(self._stroke) + ';" width="' + str(r * 2) + '" height="' + \ + str(r * 2) + '" x="' + \ + str(x) + '" y="' + str(y) + '" />\n' + + def _footer(self): + return '</svg>\n' + + +def svg_str_to_pixbuf(svg_string): + """ Load pixbuf from SVG string """ + pl = gtk.gdk.PixbufLoader('svg') + pl.write(svg_string) + pl.close() + pixbuf = pl.get_pixbuf() + return pixbuf |