Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonzalo Odiard <gonzalo@nautilus.localdomain>2009-10-22 03:28:06 (GMT)
committer Gonzalo Odiard <gonzalo@nautilus.localdomain>2009-10-22 03:28:06 (GMT)
commitcae62c461a6f187bbbd4bb26a080a9f76f9d8b95 (patch)
tree5e20a332dba42c4e3d06f8b8ab738fb559381d6c
agrego todos los archivos
-rw-r--r--TODO35
-rw-r--r--activity/activity.info7
-rw-r--r--activity/domino-icon.svg93
-rw-r--r--cairoutils.py25
-rw-r--r--dominoactivity.py466
-rw-r--r--dominogame.py357
-rw-r--r--dominopiece.py196
-rw-r--r--dominopieceprocessor.py327
-rw-r--r--dominoplayer.py212
-rw-r--r--dominoview.py261
-rw-r--r--icons/cursors.svg44
-rw-r--r--icons/gamekeys.svg65
-rw-r--r--icons/scores.svg91
-rw-r--r--locale/es/LC_MESSAGES/org.laptop.Domino.mobin0 -> 1948 bytes
-rw-r--r--locale/es/activity.linfo2
-rw-r--r--po/Domino.pot118
-rw-r--r--po/POTFILES.in1
-rw-r--r--po/es.po118
-rw-r--r--setup.py5
19 files changed, 2423 insertions, 0 deletions
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..d0987be
--- /dev/null
+++ b/TODO
@@ -0,0 +1,35 @@
+
+HECHO:
+1er etapa: juego funcional para un usuario
+
+* Mostrar status (en la Toolbar? o en otro lado)
+ (cantidad de fichas de cada jugador, y fichas en el pozo)
+ (que jugador esta jugando)
+* Estrategia simple para juego de la computadora.
+* Pedir una ficha (cuando ninguna de las que tengo me sirve).
+* Pasar (cuando no puede poner ninguna ficha)
+
+2da etapa: juego con utilidad educativa
+* Proceso para substituir los numeros de las fichas por cuentas aleatoriamente generadas.
+ cuentas con distintas complejidades y operaciones.
+ imagenes con fracciones.
+
+i18n
+http://wiki.laptop.org/go/Internationalization_in_Sugar
+
+* DIbujar solo lo necesario.
+1) Dibujar las piezas fijas en una imagen estatica
+2) Pegarla en el context al redibujar y agregar la pieza que esta en movimiento
+
+ver http://blog.rastersoft.com/index.php/2007/06/20/trabajando-con-pycairo-y-gtk/
+
+
+TO DO:
+
+* Probar con distintos conceptos equivalentes:
+ numeros romanos?
+ letras mayusculas y minusculas?
+
+3era etapa: juego en la mesh
+
+
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100644
index 0000000..50855c3
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,7 @@
+[Activity]
+name = Domino
+service_name = org.laptop.Domino
+icon = domino-icon
+class = dominoactivity.Domino
+activity_version = 7
+host_version = 1
diff --git a/activity/domino-icon.svg b/activity/domino-icon.svg
new file mode 100644
index 0000000..7e183df
--- /dev/null
+++ b/activity/domino-icon.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#000000">
+ <!ENTITY fill_color "#AAAAAA">
+]>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Icon"
+ width="46.119"
+ height="46.121"
+ viewBox="0 0 46.119 46.121"
+ overflow="visible"
+ enable-background="new 0 0 46.119 46.121"
+ xml:space="preserve"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docname="domino-icon.svg"
+ sodipodi:docbase="/home/gonzalo/Activities/Domino.activity/activity"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+ id="metadata3274"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs3272" /><sodipodi:namedview
+ inkscape:window-height="879"
+ inkscape:window-width="957"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="11.313709"
+ inkscape:cx="27.939596"
+ inkscape:cy="20.396947"
+ inkscape:window-x="0"
+ inkscape:window-y="26"
+ inkscape:current-layer="Icon" />
+
+
+
+<path
+ style="fill:&fill_color;;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -14.278246,-46.460958 C -14.391566,-46.460958 -14.051608,-46.460958 -14.278246,-46.460958 z "
+ id="path3281" /><rect
+ style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:3.50000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
+ id="rect2208"
+ width="25.102291"
+ height="40.128311"
+ x="10.694989"
+ y="2.8990984" /><path
+ sodipodi:type="arc"
+ style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
+ id="path2210"
+ sodipodi:cx="17.589281"
+ sodipodi:cy="9.2630596"
+ sodipodi:rx="1.1490486"
+ sodipodi:ry="0.9722718"
+ d="M 18.73833 9.2630596 A 1.1490486 0.9722718 0 1 1 16.440233,9.2630596 A 1.1490486 0.9722718 0 1 1 18.73833 9.2630596 z"
+ transform="matrix(0.7722429,0,0,0.9126507,9.6629373,24.276228)" /><path
+ style="fill:&fill_color;;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.01488268px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 11.851479,22.96054 L 34.64079,22.965968"
+ id="path3188" /><path
+ sodipodi:type="arc"
+ style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
+ id="path3192"
+ sodipodi:cx="17.589281"
+ sodipodi:cy="9.2630596"
+ sodipodi:rx="1.1490486"
+ sodipodi:ry="0.9722718"
+ d="M 18.73833 9.2630596 A 1.1490486 0.9722718 0 1 1 16.440233,9.2630596 A 1.1490486 0.9722718 0 1 1 18.73833 9.2630596 z"
+ transform="matrix(0.7722429,0,0,0.9126507,3.9176947,0.8975099)" /><path
+ sodipodi:type="arc"
+ style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
+ id="path3194"
+ sodipodi:cx="17.589281"
+ sodipodi:cy="9.2630596"
+ sodipodi:rx="1.1490486"
+ sodipodi:ry="0.9722718"
+ d="M 18.73833 9.2630596 A 1.1490486 0.9722718 0 1 1 16.440233,9.2630596 A 1.1490486 0.9722718 0 1 1 18.73833 9.2630596 z"
+ transform="matrix(0.7722429,0,0,0.9126507,15.584956,9.4711795)" /></svg>
diff --git a/cairoutils.py b/cairoutils.py
new file mode 100644
index 0000000..e2d7ac8
--- /dev/null
+++ b/cairoutils.py
@@ -0,0 +1,25 @@
+import gobject
+import gtk
+import cairo
+
+
+def draw_round_rect(context,x,y,w,h,r):
+ # Copiado de http://www.steveanddebs.org/PyCairoDemo/
+ # "Draw a rounded rectangle"
+ # A****BQ
+ # H C
+ # * *
+ # G D
+ # F****E
+
+ context.move_to(x+r,y) # Move to A
+ context.line_to(x+w-r,y) # Straight line to B
+ context.curve_to(x+w,y,x+w,y,x+w,y+r) # Curve to C, Control points are both at Q
+ context.line_to(x+w,y+h-r) # Move to D
+ context.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h) # Curve to E
+ context.line_to(x+r,y+h) # Line to F
+ context.curve_to(x,y+h,x,y+h,x,y+h-r) # Curve to G
+ context.line_to(x,y+r) # Line to H
+ context.curve_to(x,y,x,y,x+r,y) # Curve to A
+ return
+
diff --git a/dominoactivity.py b/dominoactivity.py
new file mode 100644
index 0000000..65ba25e
--- /dev/null
+++ b/dominoactivity.py
@@ -0,0 +1,466 @@
+#!/usr/bin/env python
+
+### Domino con cuentas
+### By Gonzalo Odiard, 2006 godiard at gmail.com
+### GPL License - http://www.gnu.org/copyleft/gpl.html
+
+# Tutorial de cairo interesante
+# http://tortall.net/mu/wiki/CairoTutorial
+
+# http://www.redhatmagazine.com/2007/04/05/building-the-xo-porting-a-pygtk-game-to-sugar-part-one/
+
+# Style guide : http://www.python.org/dev/peps/pep-0008/
+
+import gobject
+import gtk
+import cairo
+import pango
+import math, random
+import os,sys
+
+import pickle
+
+import pygtk
+pygtk.require('2.0')
+import getopt
+
+import logging
+from gettext import gettext as _
+import sugar
+from sugar.activity import activity
+from sugar.graphics.toolbutton import ToolButton
+
+import dominoview
+from dominoview import DominoTableView
+from dominogame import DominoGame
+from dominogame import DominoGamePoints
+from dominopiece import DominoPiece
+import dominopieceprocessor
+from dominopieceprocessor import PieceProcessorMathSimple
+from dominopieceprocessor import PieceProcessorProductTable
+from dominopieceprocessor import PieceProcessorPoints
+from dominopieceprocessor import PieceProcessorFractions
+
+class Domino(activity.Activity):
+
+ """
+ La activity arma la Toolbar, el canvas e inicia el juego
+ """
+
+ def __init__(self, handle):
+ activity.Activity.__init__(self, handle)
+
+ # Creo la toolbar y agrego los botones
+
+ toolbox = activity.ActivityToolbox(self)
+ self.toolbar = gtk.Toolbar()
+
+ # lista con los puntajes
+ self.list_points = []
+
+ # lista de los processors
+ self.list_processors = []
+
+ self.list_processors.append(PieceProcessorMathSimple())
+ self.list_processors.append(PieceProcessorProductTable(2))
+ self.list_processors.append(PieceProcessorProductTable(3))
+ self.list_processors.append(PieceProcessorProductTable(4))
+ self.list_processors.append(PieceProcessorProductTable(5))
+ self.list_processors.append(PieceProcessorProductTable(6))
+ self.list_processors.append(PieceProcessorProductTable(7))
+ self.list_processors.append(PieceProcessorProductTable(8))
+ self.list_processors.append(PieceProcessorProductTable(9))
+ self.list_processors.append(PieceProcessorPoints())
+ self.list_processors.append(PieceProcessorFractions())
+
+
+ # agrego combo para tipo de juego
+ cmbItem = gtk.ToolItem()
+ self.cmbTipoPiezas = gtk.combo_box_new_text()
+
+ self.read_file()
+
+ for n in range(0,len(self.list_processors)):
+ self.cmbTipoPiezas.append_text(self.list_processors[n].get_name())
+ # inicializo puntajes
+ if (self.get_points_by_name(self.list_processors[n].get_name()) == None):
+ game_points = DominoGamePoints()
+ game_points.name = self.list_processors[n].get_name()
+ self.list_points.append(game_points)
+
+
+ cmbItem.add(self.cmbTipoPiezas)
+ self.toolbar.insert(cmbItem, -1)
+ self.cmbTipoPiezas.show()
+ cmbItem.show()
+ self.cmbTipoPiezas.set_active(0)
+
+ self.btnStart = ToolButton('dialog-ok')
+ self.btnStart.connect('clicked', self._start_game)
+ self.btnStart.set_tooltip(_('Start'))
+ self.toolbar.insert(self.btnStart, -1)
+ self.btnStart.show()
+
+ self.btnNew = ToolButton('list-add')
+ self.btnNew.connect('clicked', self._add_piece)
+ self.btnNew.set_tooltip(_('Get piece'))
+ self.toolbar.insert(self.btnNew, -1)
+ self.btnNew.show()
+
+ self.btnPass = ToolButton('go-next')
+ self.btnPass.connect('clicked', self._pass_next_player)
+ self.btnPass.set_tooltip(_('Pass'))
+ self.toolbar.insert(self.btnPass, -1)
+ self.btnPass.show()
+
+ self.btnScores = ToolButton('scores')
+ self.btnScores.connect('clicked', self._show_scores)
+ self.btnScores.set_tooltip(_('Scores'))
+ self.toolbar.insert(self.btnScores, -1)
+ self.btnScores.show()
+
+
+ toolbox.add_toolbar(_('Domino'), self.toolbar)
+ self.toolbar.show()
+ self.set_toolbox(toolbox)
+ toolbox.show()
+
+ toolbox.set_current_toolbar(1)
+
+ # Creo el Canvas y el CanvasBox donde dibujaremos todo el tablero y las fichas
+ self.drawingarea = gtk.DrawingArea()
+ self.drawingarea.set_size_request(dominoview.SCREEN_WIDTH,dominoview.SCREEN_HEIGHT)
+ self.drawingarea.show()
+ self.drawingarea.connect('expose-event', self.on_drawing_area_exposed)
+ self.connect('key-press-event',self.on_keypress)
+ self.set_canvas(self.drawingarea)
+
+ self.game = None
+ self.show_scores = False
+
+ self.surface = None
+
+ self.drawingarea.queue_draw()
+
+
+ def get_points_by_name(self,game_processor_name):
+ for n in range(0,len(self.list_points)):
+ if (self.list_points[n].name == game_processor_name):
+ return self.list_points[n]
+ return None
+
+ def add_points_by_name(self,game_processor_name,win):
+ for n in range(0,len(self.list_points)):
+ if (self.list_points[n].name == game_processor_name):
+ self.list_points[n].played = self.list_points[n].played + 1
+ if (win) :
+ self.list_points[n].win = self.list_points[n].win +1
+ else :
+ self.list_points[n].lost = self.list_points[n].lost +1
+
+
+ def on_drawing_area_exposed(self,drawingarea, event):
+ sys.stdout.write("REDRAW\n")
+ sys.stdout.flush()
+ x, y, width, height = drawingarea.allocation
+ self.ctx = drawingarea.window.cairo_create()
+
+
+ if (self.show_scores):
+ table = DominoTableView()
+ table.show_scores(self.ctx,self.list_points)
+ return
+
+ if (self.game == None):
+ table = DominoTableView()
+ table.help(self.ctx)
+ return
+
+ self.ctx.set_source_surface(self.surface)
+ self.ctx.paint()
+
+
+ # test end game (se puede poner en otro metodo)
+ end_game = False
+ win = False
+
+ # Dibujo la pieza seleccionada
+ player = self.game.ui_player
+ player.get_pieces()[player.order_piece_selected].draw(self.ctx,True)
+
+ for n in range(0,len(self.game.players)):
+ # dibujo las piezas del jugador
+ player = self.game.players[n]
+ pieces = player.get_pieces()
+ if (len(pieces) == 0):
+ end_game = True
+ if (self.game.ui_player == player):
+ win = True
+
+ # Chequeo si todos los jugadores pasaron
+
+ all_has_passed = True
+ for n in range(0,len(self.game.players)):
+ player = self.game.players[n]
+ if (not player.has_passed):
+ all_has_passed = False
+
+ # si todos pasaron veo quien tiene menos fichas
+ if (all_has_passed):
+ min_cant_pieces = 100
+ player_with_minus_pieces = None
+ for n in range(0,len(self.game.players)):
+ player = self.game.players[n]
+ if (len(player.get_pieces()) < min_cant_pieces):
+ min_cant_pieces = len(player.get_pieces())
+ player_with_minus_pieces = player
+
+ end_game = True
+
+ # no estoy manejando un empate... (ambos jugadores con la misma cantidad de piezas)
+
+ if (player_with_minus_pieces == player):
+ win = True
+
+ if (self.game.table):
+ self.game.table.show_status(self.ctx,self.game.get_status())
+
+ if (end_game):
+ self.add_points_by_name(self.game.processor.get_name(),win)
+ self.game.table.msg_end_game(self.ctx,win)
+
+
+ def draw_pieces(self):
+ sys.stdout.write("DIBUJANDO \n")
+ sys.stdout.flush()
+ self.surface=cairo.ImageSurface(cairo.FORMAT_ARGB32,dominoview.SCREEN_WIDTH,dominoview.SCREEN_HEIGHT)
+ surf_ctx=cairo.Context(self.surface)
+
+ if (self.game.table):
+ self.game.table.paint(surf_ctx)
+
+ # ordeno la lista de las fichas puestas desde arriba a la izq hacia abajo a la derecha
+ # para que se encimen bien cuando se dibujan
+ self.game.placed_pieces.sort(lambda pieceA, pieceB: pieceA.x - pieceB.x + pieceA.y * 100 - pieceB.y * 100)
+
+ for n in range(0,len(self.game.placed_pieces)):
+ piece = self.game.placed_pieces[n]
+ if (piece.visible):
+ piece.draw(surf_ctx,False)
+
+ #for n in range(0,len(self.game.players)):
+ # dibujo las piezas del jugador
+ player = self.game.ui_player
+ pieces = player.get_pieces()
+ for m in range(0,len(pieces)):
+ piece = pieces[m]
+ if (piece.visible):
+ if (self.game.game_state != DominoGame.GAME_STATE_LOCATE_PIECE) or (m != self.game.ui_player.order_piece_selected):
+ piece.draw(surf_ctx,False)
+
+ def _start_game(self,button):
+
+ if (self.show_scores):
+ self.show_scores = False
+
+ # Aqui comienza el juego
+ processor = self.list_processors[self.cmbTipoPiezas.get_active()]
+
+ self.game = DominoGame(processor,self.drawingarea)
+
+ self.game.btnPass = self.btnPass
+ self.game.btnNew = self.btnNew
+ # Al principio se puede pedir pero no pasar
+ self.game.btnNew.props.sensitive = True
+ self.game.btnPass.props.sensitive = False
+
+ self.game.start_game(2)
+ self.game.show_pieces_player(self.game.ui_player)
+ self.draw_pieces()
+ self.drawingarea.queue_draw()
+
+
+ def _add_piece(self, button):
+ pieces = self.game.take_pieces(1)
+ if (len(pieces) > 0):
+ piece = pieces[0]
+ self.game.ui_player.get_pieces().append(piece)
+ # esto no es mejor hay que hacerlo en la creacion?
+ piece.player = self.game.ui_player
+ piece.state = DominoPiece.PIECE_PLAYER
+ self.game.show_pieces_player(self.game.ui_player)
+ self.draw_pieces()
+ self.drawingarea.queue_draw()
+ else:
+ self.game.btnNew.props.sensitive = False
+ self.game.btnPass.props.sensitive = True
+
+
+
+ def _pass_next_player(self, button):
+
+ if (self.show_scores):
+ self.show_scores = False
+ else:
+ self.game.ui_player.has_passed = True
+ self.game.ui_player.end_play()
+
+ self.drawingarea.queue_draw()
+
+ def _show_scores(self,button):
+ self.show_scores = True
+ self.drawingarea.queue_draw()
+
+
+ def on_keypress(self, widget, event):
+ key = gtk.gdk.keyval_name(event.keyval)
+
+ # Agrego las teclas de juego de la XO (Triangulo arriba = KP_Page_Up , X = KP_Page_Down, Circulo = KP_End
+
+ if key in ('KP_Up','KP_Right','KP_Down','KP_Left','KP_Page_Up','KP_Page_Down','KP_End', 'space','KP_8','KP_6','KP_2','KP_4','Escape','Return','Up','Down','Left','Right'):
+ if (key in ('KP_Page_Up')):
+ key = 'Return'
+ if (key in ('KP_Page_Down')):
+ key = 'Escape'
+ if (key in ('KP_End')):
+ key = 'space'
+
+ if (key in ('Up', 'KP_8')):
+ key = 'KP_Up'
+ if (key in ('Right', 'KP_6')):
+ key = 'KP_Rigth'
+ if (key in ('Down', 'KP_2')):
+ key = 'KP_Down'
+ if (key in ('Left', 'KP_4')):
+ key = 'KP_Left'
+ self.key_action(key)
+ # Para saber que codigo viene
+ #else:
+ # print gtk.gdk.keyval_name(event.keyval)
+ # sys.stdout.write("keyval "+str(event.keyval)+" key "+key+"\n")
+ # sys.stdout.flush()
+ return True
+
+ def key_action(self, key):
+ redraw = False
+ if (self.show_scores):
+ self.show_scores = False
+ redraw = True
+
+ if (self.game.game_state == DominoGame.GAME_STATE_SELECT_PIECE):
+ # Seleccionamos las distintas piezas
+ if ((key == 'KP_Up') or (key == 'KP_Right')):
+ if (self.game.ui_player.order_piece_selected < len(self.game.ui_player.get_pieces()) - 1) :
+ self.game.ui_player.order_piece_selected = self.game.ui_player.order_piece_selected +1
+ else:
+ self.game.ui_player.order_piece_selected = 0
+ redraw = True
+ if ((key == 'KP_Down') or (key == 'KP_Left')):
+ if (self.game.ui_player.order_piece_selected > 0) :
+ self.game.ui_player.order_piece_selected = self.game.ui_player.order_piece_selected - 1
+ else:
+ self.game.ui_player.order_piece_selected = len(self.game.ui_player.get_pieces()) - 1
+ redraw = True
+
+ if ((key == 'Return')):
+ # Elegimos una pieza para jugar
+ self.game.game_state = DominoGame.GAME_STATE_LOCATE_PIECE
+ piece = self.game.ui_player.get_pieces()[self.game.ui_player.order_piece_selected]
+ piece.rotate()
+ nIni = int(self.game.table.cantX / 2)
+ pIni = self.game.table.cantY - 2
+ piece.x,piece.y = self.game.table.get_tile_position(nIni,pIni)
+ self.draw_pieces()
+ redraw = True
+
+ elif (self.game.game_state == DominoGame.GAME_STATE_LOCATE_PIECE):
+ # Movemos la pieza por el tablero
+ # con space la giramos y con escape la volvemos a la pila de fichas del jugador
+ piece = self.game.ui_player.get_pieces()[self.game.ui_player.order_piece_selected]
+ if ((key == 'KP_Up') or (key == 'KP_Right') or (key == 'KP_Down') or (key == 'KP_Left') or (key == 'Return')):
+ n,p = self.game.table.get_tile_coord(piece.x,piece.y)
+ n_ori , p_ori = n,p
+ if (key == 'KP_Up') :
+ if (p > 0):
+ p = p - 1
+
+ if (key == 'KP_Down') :
+ if (p < self.game.table.cantY):
+ p = p + 1
+
+ if (key == 'KP_Left') :
+ if (n > 0):
+ n = n - 1
+
+ if (key == 'KP_Right') :
+ if (n < self.game.table.cantX):
+ n = n + 1
+
+ if ((key == 'KP_Up') or (key == 'KP_Right') or (key == 'KP_Down') or (key == 'KP_Left')):
+ if (self.game.test_in_board(piece,n,p)):
+ piece.x,piece.y = self.game.table.get_tile_position(n,p)
+ redraw = True
+
+ if (key == 'Escape'):
+ # volvemos al modo de seleccion de piezas
+ self.game.game_state = DominoGame.GAME_STATE_SELECT_PIECE
+ self.game.show_pieces_player(self.game.ui_player)
+ self.draw_pieces()
+ redraw = True
+
+ if (key == 'space'):
+ # giro la pieza
+ piece.rotate()
+ redraw = True
+
+ if (key == 'Return'):
+ # posiciona la pieza si es posible
+ if (self.game.test_good_position(piece,n,p)):
+ self.game.put_piece(piece.player,piece,n,p)
+ self.game.show_pieces_player(piece.player)
+ piece.player.end_play()
+ self.draw_pieces()
+ redraw = True
+
+
+ if (redraw) :
+ self.drawingarea.queue_draw()
+ return
+
+
+ def write_file(self, file_path):
+ #save the file itself
+ #act_root = os.getenv("SUGAR_ACTIVITY_ROOT")
+ act_root = self.get_activity_root()
+ path_data = os.path.join(act_root, "data")
+ file_name = os.path.join(path_data,"Scores.data")
+ #print "file name",file_name
+ f = open(file_name, 'w')
+ try:
+ pickle.dump(self.list_points, f)
+ finally:
+ f.close()
+
+
+ def read_file(self):
+ #act_root = os.getenv("SUGAR_ACTIVITY_ROOT")
+ act_root = self.get_activity_root()
+ path_data = os.path.join(act_root, "data")
+ file_name = os.path.join(path_data,"Scores.data")
+ #print file_name
+ if os.path.exists(file_name):
+ fd = open(file_name, 'r')
+ try:
+ # lo meto en una variable intermedia por si hay problemas
+ list_points = pickle.load(fd)
+ self.list_points = list_points
+ except:
+ print "Error leyendo puntajes"
+ finally:
+ fd.close()
+
+
+
+
+
+
diff --git a/dominogame.py b/dominogame.py
new file mode 100644
index 0000000..59b0203
--- /dev/null
+++ b/dominogame.py
@@ -0,0 +1,357 @@
+import gobject
+import gtk
+import math, random
+
+import pygtk
+pygtk.require('2.0')
+import getopt
+
+import sys
+from gettext import gettext as _
+
+from sugar import profile
+
+from dominopiece import DominoPiece
+import dominoview
+from dominoview import Tile
+from dominoview import DominoTableView
+import dominoplayer
+from dominoplayer import DominoPlayer
+from dominoplayer import SimpleAutoPlayer
+
+from dominopieceprocessor import PieceProcessorMathSimple
+
+
+class DominoGame:
+
+ """
+ Esta es la clase principal del juego
+ """
+
+ # estados del juego
+ GAME_STATE_SELECT_PIECE = 1;
+ GAME_STATE_LOCATE_PIECE = 2;
+ GAME_STATE_ANOTHER_USER = 3;
+ GAME_STATE_FINISH_GAME = 4;
+
+ def __init__(self,processor,drawingarea):
+ self.ui_player = None
+ self.table = DominoTableView()
+ self.pieces = []
+ self.placed_pieces = []
+ self.game_state = DominoGame.GAME_STATE_SELECT_PIECE
+ self.players = []
+ self.values = []
+ self.cantX = self.table.cantX
+ self.cantY = self.table.cantY
+ for n in range(0,self.cantX):
+ self.values.append([])
+ for p in range(0,self.cantY):
+ tile = Tile(n,p)
+ self.values[n].append(tile)
+ # primera y ultima posicion de las piezas
+ self.start = None
+ self.end = None
+
+ self.processor = processor
+ self.drawingarea = drawingarea
+
+ def next_player(self,num_player):
+ if (num_player >= len(self.players)-1):
+ return self.players[0]
+ else:
+ return self.players[num_player+1]
+
+ # Posiciona una pieza en el tablero
+ def put_piece(self,player,piece,n,p):
+ player.remove_piece(piece)
+
+ valueA = piece.a
+ valueB = piece.b
+ if piece.reversed:
+ valueA = piece.b
+ valueB = piece.a
+
+ self.values[n][p].value = valueA
+ if piece.vertical:
+ self.values[n][p+1].value = valueB
+ else:
+ self.values[n+1][p].value = valueB
+
+ self.values[n][p].piece = piece
+ if piece.vertical:
+ self.values[n][p+1].piece = piece
+ else:
+ self.values[n+1][p].piece = piece
+
+ piece.state = DominoPiece.PIECE_PLACED
+ piece.visible = True
+ piece.x,piece.y = self.table.get_tile_position(n,p)
+ self.placed_pieces.append(piece)
+ player.order_piece_selected = 0
+ player.has_passed = False
+ self.drawingarea.queue_draw()
+
+
+ def test_in_board(self,dominoPiece,n,p):
+ n1 = n
+ p1 = p
+ n2 = n
+ p2 = p
+ if (not dominoPiece.vertical):
+ n2 = n2 + 1
+ else:
+ p2 = p2 + 1
+
+ test = not ((n1 < 0) or (p1 < 1) or (n2 > self.cantX-1) or ( p2 > self.cantY))
+ #sys.stdout.write("cantX "+str(self.cantX)+" cantY "+str(self.cantY)+"vert "+str(dominoPiece.vertical)+" rev "+str(dominoPiece.reversed)+" -- ")
+ #sys.stdout.write(" n "+str(n)+" n1 "+str(n1)+" n2 "+str(n2)+" p "+str(p)+" p1 "+str(p1)+" p2 "+str(p2)+" = "+str(test)+"\n")
+ #sys.stdout.flush()
+ return test
+
+ def test_good_position(self,dominoPiece,n,p):
+ try:
+ if (n < 0) or (p < 0) or (n > self.cantX) or ( p > self.cantY):
+ #print "Fuera de los limites"
+ return False
+ if (dominoPiece.vertical):
+ if ((p+1) > self.cantY):
+ #print "Fuera de los limites"
+ return False
+ else:
+ if ((n+1) > self.cantX):
+ #print "Fuera de los limites"
+ return False
+
+ #print "testeando posicion correcta",n,p
+ if (self.start == None) and (self.end == None):
+ #print "No hay start o end"
+ return True
+ #print "# chequea que no este ocupada esa posicion"
+ if (self.values[n][p].value != -1):
+ #print "N,P ocupada"
+ return False
+ #print "# chequear la otra posicion ocupada por la pieza, segun este vertical u horizontal"
+ try:
+ if (dominoPiece.vertical):
+ if (self.values[n][p+1].value != -1):
+ #print "N,P+1 ocupada"
+ return False
+ else:
+ if (self.values[n+1][p].value != -1):
+ #print "N+1,P ocupada"
+ return False
+
+ except (IndexError),e:
+ #print "Fuera de rango * (1) test_good_position"
+ return False
+
+ #print "# chequear las posiciones laterales"
+ valueA = dominoPiece.a
+ valueB = dominoPiece.b
+ if dominoPiece.reversed:
+ valueA = dominoPiece.b
+ valueB = dominoPiece.a
+
+ bad = self._test_invalid(valueA,n,p)
+ if dominoPiece.vertical:
+ bad = bad or self._test_invalid(valueB,n,p+1)
+ else:
+ bad = bad or self._test_invalid(valueB,n+1,p)
+ if bad:
+ #print "BAD posiciones laterales"
+ return False
+
+ #print "# hago test contra start"
+ ok = self.test_valid(self.start,valueA,n,p)
+ if ok:
+ n2,p2 = self._get_oposite_corner(dominoPiece,n,p,n,p)
+ value2 = valueB
+ else:
+ if dominoPiece.vertical:
+ ok = ok or self.test_valid(self.start,valueB,n,p+1)
+ else:
+ ok = ok or self.test_valid(self.start,valueB,n+1,p)
+ if ok:
+ n2,p2 = n,p
+ value2 = valueA
+ if ok:
+ #print "Coincide start",n2,p2,value2
+ if self.start == None:
+ self.start = Tile(n2,p2)
+ self.start.n,self.start.p = n2,p2
+ self.start.value = value2
+ self.start.piece = dominoPiece
+ return True
+
+
+ #print "# hago test contra end"
+ ok = self.test_valid(self.end,valueA,n,p)
+ if ok:
+ n2,p2 = self._get_oposite_corner(dominoPiece,n,p,n,p)
+ value2 = valueB
+ else:
+ if dominoPiece.vertical:
+ ok = ok or self.test_valid(self.end,valueB,n,p+1)
+ else:
+ ok = ok or self.test_valid(self.end,valueB,n+1,p)
+ if ok:
+ n2,p2 = n,p
+ value2 = valueA
+ if ok:
+ #print "Coincide end",n2,p2,value2
+ if self.end == None:
+ self.end = Tile(n2,p2)
+ self.end.n,self.end.p = n2,p2
+ self.end.value = value2
+ self.end.piece = dominoPiece
+ return True
+ except (IndexError),e:
+ print "Fuera de rango * test_good_position"
+ #print "End test False"
+
+ return False
+
+ def _get_oposite_corner(self,piece,nPiece,pPiece,nTest,pTest):
+ if (nPiece == nTest) and (pPiece == pTest):
+ if piece.vertical:
+ return nPiece,pPiece+1
+ else:
+ return nPiece+1,pPiece
+ else:
+ return nPiece,pPiece
+
+
+
+ def _test_invalid(self,value,n,p):
+ #print "test invalid value",value,"n=",n,"p=",p
+ try:
+ if (self.values[n+1][p].value != -1) and (self.values[n+1][p].value != value):
+ return True
+ if (self.values[n-1][p].value != -1) and (self.values[n-1][p].value != value):
+ return True
+ if (self.values[n][p+1].value != -1) and (self.values[n][p+1].value != value):
+ return True
+ if (self.values[n][p-1].value != -1) and (self.values[n][p-1].value != value):
+ return True
+ # if (n+1 < self.cantX):
+ # if (self.values[n+1][p].value != -1) and (self.values[n+1][p].value != value):
+ # return True
+ # if (n-1 >= 0):
+ # if (self.values[n-1][p].value != -1) and (self.values[n-1][p].value != value):
+ # return True
+ # if (p+1 < self.cantY):
+ # if (self.values[n][p+1].value != -1) and (self.values[n][p+1].value != value):
+ # return True
+ # if (p-1 >= 0):
+ # if (self.values[n][p-1].value != -1) and (self.values[n][p-1].value != value):
+ # return True
+ except (IndexError),e:
+ print "index error _test_invalid"
+ return False
+
+ def test_valid(self,tile,value,n,p):
+ if (tile == None):
+ return False
+ # no anda bien y hay que chequear contra start y end
+ #print "test valid n=",n,"p=",p,"value", value
+ #print "tile n",tile.n,"p",tile.p,"value",tile.value
+
+ if (tile.n == n-1) and (tile.p == p):
+ return (tile.value == value)
+ if (tile.n == n+1) and (tile.p == p):
+ return (tile.value == value)
+ if (tile.n == n) and (tile.p-1 == p):
+ return (tile.value == value)
+ if (tile.n == n) and (tile.p+1 == p):
+ return (tile.value == value)
+
+ return False
+
+ def _create_domino(self):
+ for n in range(0,7):
+ for p in range(n,7):
+ #creo pieza
+ piece = DominoPiece(n,p)
+ self.pieces.append(piece)
+ self.processor.alter_labels(self.pieces)
+
+ # Toma al azar una cantidad de piezas del juego y las devuelve en una coleccion
+ def take_pieces(self,cant):
+ result = []
+ for n in range(0,cant):
+ cantPieces = len(self.pieces)
+ if (cantPieces > 0):
+ r = int(random.random() * cantPieces)
+ piece = self.pieces[r]
+ # la quito de las piezas del juego
+ self.pieces[r] = cantPieces
+ self.pieces.remove(cantPieces)
+ # la agrego a result
+ result.append(piece)
+ return result
+
+ # para debug
+ def print_value_pieces(self,pieceList):
+ print "printValues"
+ for n in range(0,len(pieceList)):
+ piece = pieceList[n]
+ print piece.n,piece.p
+
+ def start_game(self,numPlayers):
+ self._create_domino()
+ self.placed_pieces = []
+ self.players = []
+ auto_player = SimpleAutoPlayer(self,0)
+ auto_player.set_pieces(self.take_pieces(7))
+ self.players.append(auto_player)
+ for n in range(1,numPlayers):
+ #print "bucle creacion jugadores",n
+ player = DominoPlayer(self,n)
+ player.set_pieces(self.take_pieces(7))
+ self.players.append(player)
+
+ # comienza a jugar el primer jugador
+ self.players[0].play()
+ self.ui_player = self.players[1]
+ self.ui_player.color = profile.get_color()
+ self.ui_player.name = profile.get_nick_name()
+
+
+ def show_pieces_player(self,player):
+ pieces = player.get_pieces()
+
+ if (len(pieces) > 0):
+ separacion_x = int((dominoview.SCREEN_WIDTH - dominoview.SIZE * len(pieces)) / len(pieces))
+ x = separacion_x / 2
+ y = self.table.limitTable + 5
+
+ for n in range(0,len(pieces)):
+ piece = pieces[n]
+ piece.x = x
+ piece.y = y
+ piece.vertical = True
+
+ x = x + dominoview.SIZE + separacion_x
+ piece.visible = True
+
+
+ def get_status(self):
+ players_status = ''
+ for n in range(0,len(self.players)):
+ player = self.players[n]
+ players_status = players_status + player.get_status()
+
+ if (len (self.pieces) > 0):
+ players_status = players_status + _("Stack")+" : " + str(len(self.pieces))
+ return players_status
+
+
+class DominoGamePoints:
+
+ def __init__(self):
+ self.name = None
+ self.played = 0
+ self.win = 0
+ self.lost = 0
+
diff --git a/dominopiece.py b/dominopiece.py
new file mode 100644
index 0000000..e6acf57
--- /dev/null
+++ b/dominopiece.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python
+
+### Piezas del domino
+### By Gonzalo Odiard, 2006 godiard at gmail.com
+### GPL License - http://www.gnu.org/copyleft/gpl.html
+
+
+import gobject
+import gtk
+import cairo
+import math, random
+
+import pygtk
+pygtk.require('2.0')
+import getopt
+
+import logging
+from gettext import gettext as _
+import sugar
+from sugar.graphics import xocolor
+from sugar.graphics import style
+import dominoview
+import cairoutils
+
+import dominopieceprocessor
+
+class DominoPiece:
+ """ Informacion de cada pieza del juego (visible o no) """
+
+ PIECE_PLAYER = 1
+ PIECE_IN_MOVE = 2
+ PIECE_PLACED = 3
+ PIECE_WAITING = 0
+
+ def __init__(self,a,b):
+ #print "creando pieza",n,p
+
+ self.a = a
+ self.b = b
+ self.textA = str(a)
+ self.textB = str(b)
+ self.vertical = False
+ self.reversed = False
+ self.player = None
+ self.state = DominoPiece.PIECE_WAITING
+ self.visible = False
+ self._itemA = None
+ self._itemB = None
+
+# def selected(self):
+# if (self.player == None):
+# return False
+# if (self.player.order_piece_selected == -1):
+# return False
+# if (self.player.order_piece_selected >= len(self.player.get_pieces())):
+# return False
+# if (self.player.get_pieces()[self.player.order_piece_selected] == self):
+# return True
+
+
+ def draw(self,ctx,selected):
+ SIZE = dominoview.SIZE
+ #if self.vertical:
+ # width = SIZE + SIZE/8 + 2
+ # height = SIZE*2 + SIZE/8 + 2
+ #else:
+ # width = SIZE*2 + SIZE/8 + 2
+ # height = SIZE + SIZE/8 + 2
+
+ ctx.save()
+ ctx.translate(self.x,self.y)
+ ctx.move_to(self.x,self.y)
+ #ctx.translate(1,1)
+ #ctx.move_to(1, 1)
+ r = 10
+ stroke_r,stroke_g,stroke_b = 0,0,0
+ fill_r,fill_g,fill_b = 1, 1, 1
+ alpha = 1
+ if (self.player.color != None):
+ xocolor = self.player.color
+ stroke_r,stroke_g,stroke_b,alpha = style.Color(xocolor.get_stroke_color(),1.0).get_rgba()
+ fill_r,fill_g,fill_b,alpha = style.Color(xocolor.get_fill_color(),1.0).get_rgba()
+
+
+ if self.vertical:
+ cairoutils.draw_round_rect(ctx,-1,-1,SIZE+2,SIZE*2+2,r)
+
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+ ctx.fill()
+
+ cairoutils.draw_round_rect(ctx,0,0,SIZE,SIZE*2,r)
+ if selected:
+ ctx.set_source_rgb (1, 1, 204.0/255.0)
+ else:
+ ctx.set_source_rgb (fill_r,fill_g,fill_b)
+ ctx.fill()
+
+ ctx.move_to(SIZE,0)
+ ctx.rel_line_to((SIZE/8),(SIZE/8))
+ ctx.rel_line_to(0,SIZE*2)
+ ctx.rel_line_to(-(SIZE/8),-(SIZE/8))
+ ctx.rel_line_to(0,-SIZE*2)
+ ctx.close_path()
+ ctx.fill_preserve()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+ ctx.stroke()
+
+ ctx.move_to(0,SIZE*2)
+ ctx.rel_line_to((SIZE/8),(SIZE/8))
+ ctx.rel_line_to(SIZE,0)
+ ctx.rel_line_to(-(SIZE/8),-(SIZE/8))
+ ctx.rel_line_to(-SIZE,0)
+ ctx.close_path()
+ ctx.set_source_rgb (fill_r,fill_g,fill_b)
+ ctx.fill_preserve()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+ ctx.stroke()
+
+ #ctx.move_to(SIZE/4,SIZE)
+ #ctx.rel_line_to(SIZE/2,0)
+ #ctx.stroke()
+
+
+ if not self.reversed:
+ self._draw_label_a(ctx,0,0)
+ self._draw_label_b(ctx,0,SIZE)
+ else:
+ self._draw_label_b(ctx,0,0)
+ self._draw_label_a(ctx,0,SIZE)
+
+ else:
+ cairoutils.draw_round_rect(ctx,-1,-1,SIZE*2+2,SIZE+2,r)
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+ ctx.fill()
+
+ cairoutils.draw_round_rect(ctx,0,0,SIZE*2,SIZE,r)
+ if selected:
+ ctx.set_source_rgb (1, 1, 204.0/255.0)
+ else:
+ ctx.set_source_rgb (fill_r,fill_g,fill_b)
+ ctx.fill()
+
+ ctx.move_to(SIZE*2,0)
+ ctx.rel_line_to((SIZE/8),(SIZE/8))
+ ctx.rel_line_to(0,SIZE)
+ ctx.rel_line_to(-(SIZE/8),-(SIZE/8))
+ ctx.rel_line_to(0,-SIZE)
+ ctx.close_path()
+ ctx.fill_preserve()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+ ctx.stroke()
+
+ ctx.move_to(0,SIZE)
+ ctx.rel_line_to((SIZE/8),(SIZE/8))
+ ctx.rel_line_to(SIZE*2,0)
+ ctx.rel_line_to(-(SIZE/8),-(SIZE/8))
+ ctx.rel_line_to(-SIZE*2,0)
+ ctx.close_path()
+ ctx.set_source_rgb (fill_r,fill_g,fill_b)
+ ctx.fill_preserve()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+ ctx.stroke()
+
+ #ctx.move_to(SIZE/4,0)
+ #ctx.rel_line_to(0,SIZE-SIZE/4)
+ #ctx.stroke()
+
+ if not self.reversed:
+ self._draw_label_a(ctx,0,0)
+ self._draw_label_b(ctx,SIZE,0)
+ else:
+ self._draw_label_b(ctx,0,0)
+ self._draw_label_a(ctx,SIZE,0)
+
+
+ ctx.restore()
+
+ def _draw_label_a(self,ctx,x,y):
+ self.player.game.processor.draw_label(ctx,self,self.textA,x,y)
+
+ def _draw_label_b(self,ctx,x,y):
+ self.player.game.processor.draw_label(ctx,self,self.textB,x,y)
+
+
+ def rotate(self):
+ vertical_ini = self.vertical
+ reversed_ini = self.reversed
+ if self.vertical:
+ self.reversed = not self.reversed
+ self.vertical = not self.vertical
+ n,p = self.player.game.table.get_tile_coord(self.x,self.y)
+ if (not self.player.game.test_in_board(self,n,p)):
+ self.vertical = vertical_ini
+ self.reversed = reversed_ini
+
+
diff --git a/dominopieceprocessor.py b/dominopieceprocessor.py
new file mode 100644
index 0000000..567d635
--- /dev/null
+++ b/dominopieceprocessor.py
@@ -0,0 +1,327 @@
+import gobject
+import gtk
+import cairo
+import pango
+import math, random
+
+import pygtk
+pygtk.require('2.0')
+import getopt
+
+import logging
+from gettext import gettext as _
+
+import sugar
+from sugar.graphics import style
+import dominoview
+
+M_PI = 3.14159265358979323846
+
+class PieceProcessorMathSimple:
+
+ """
+ Este es el primer ejemplo de PieceProccesor
+ Altera los valores de textA y textB de la pieza y la dibuja
+
+ """
+
+ def get_name(self):
+ return _("Simple")
+
+ def alter_labels(self,pieces):
+ for n in range(0,len(pieces)):
+ piece = pieces[n]
+ # altero textA
+ if (random.random() > .5):
+ r = int(random.random() * 10)
+ if (r < piece.a):
+ piece.textA = str(piece.a - r) + "+" + str(r)
+ else:
+ piece.textA = str(r) + "-" + str(r - piece.a)
+ # altero textB
+ if (random.random() > .5):
+ r = int(random.random() * 10)
+ if (r < piece.b):
+ piece.textB = str(piece.b - r) + "+" + str(r)
+ else:
+ piece.textB = str(r) + "-" + str(r - piece.b)
+
+
+ def draw_label(self,ctx,piece,text,xIni,yIni):
+ #print "Dibujando ",text
+ stroke_r,stroke_g,stroke_b = 0,0,0
+ alpha = 1
+ if (piece.player.color != None):
+ xocolor = piece.player.color
+ stroke_r,stroke_g,stroke_b,alpha = style.Color(xocolor.get_stroke_color(),1.0).get_rgba()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+
+ ctx.select_font_face ("Sans",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_NORMAL)
+ ctx.set_font_size (20)
+ x_bearing, y_bearing, width, height, x_advance, y_advance = ctx.text_extents (text)
+ x = 0.5-(width/2 + x_bearing)
+ y = 0.5-(height/2 + y_bearing)
+ ctx.move_to (xIni+x+(dominoview.SIZE/2), yIni+y+(dominoview.SIZE/2))
+ ctx.show_text (text)
+
+
+
+class PieceProcessorProductTable:
+
+ def __init__(self,n):
+ self.product = n
+
+ def get_name(self):
+ return _("Table of")+" "+str(self.product)
+
+ """
+ Este es un procesor para las tablas de multiplicar
+ Altera los valores de textA y textB de la pieza y la dibuja
+
+ """
+
+ def alter_labels(self,pieces):
+ for n in range(0,len(pieces)):
+ piece = pieces[n]
+ # altero textA
+ if (random.random() > .5):
+ piece.textA = str((piece.a+2) * self.product)
+ else:
+ piece.textA = str((piece.a+2)) + "*" + str(self.product)
+ # altero textB
+ if (random.random() > .5):
+ piece.textB = str((piece.b+2) * self.product)
+ else:
+ piece.textB = str((piece.b+2)) + "*" + str(self.product)
+
+
+ def draw_label(self,ctx,piece,text,xIni,yIni):
+ #print "Dibujando ",text
+ stroke_r,stroke_g,stroke_b = 0,0,0
+
+ alpha = 1
+ if (piece.player.color != None):
+ xocolor = piece.player.color
+ stroke_r,stroke_g,stroke_b,alpha = style.Color(xocolor.get_stroke_color(),1.0).get_rgba()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+
+ ctx.select_font_face ("Sans",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_NORMAL)
+ ctx.set_font_size (20)
+ x_bearing, y_bearing, width, height, x_advance, y_advance = ctx.text_extents (text)
+ x = 0.5-(width/2 + x_bearing)
+ y = 0.5-(height/2 + y_bearing)
+ ctx.move_to (xIni+x+(dominoview.SIZE/2), yIni+y+(dominoview.SIZE/2))
+ ctx.show_text (text)
+
+
+class PieceProcessorFractions:
+
+ """
+ Este es un PieceProccesor que dibuja fracciones en forma numerica y grafica
+ vamos a trabajar con:
+ 0
+ 1/6
+ 2/6 = 1/3
+ 3/6 = 1/2 = 2/4
+ 4/6 = 2/3
+ 5/6
+ 6/6 = 1 = 2/2 = 3/3
+ A su vez se puede mostrar en forma grafica o en forma numerica
+ textA lo voy a representar siempre numericamente y textB lo voy a representar graficamente
+
+ """
+
+ def get_name(self):
+ return _("Fractions")
+
+ def alter_labels(self,pieces):
+ for n in range(0,len(pieces)):
+ piece = pieces[n]
+ # altero textA
+ piece.textA = self.alter_label(piece.a)
+ # pongo una G al comienzo para saber
+ # que las tengo que representar graficamente
+ piece.textB = "G"+self.alter_label(piece.b)
+
+ def alter_label(self,val):
+ if (val == 0):
+ return "0"
+ elif (val == 1):
+ return "1/6"
+ elif (val == 2):
+ if (random.random() > .5):
+ return "2/6"
+ else:
+ return "1/3"
+ elif (val == 3):
+ rand = random.random()
+ if (rand < .33):
+ return "3/6"
+ elif (rand < .66):
+ return "1/2"
+ else:
+ return "2/4"
+ elif (val == 4):
+ if (random.random() > .5):
+ return "4/6"
+ else:
+ return "2/3"
+ elif (val == 5):
+ return "5/6"
+ elif (val == 6):
+ rand = random.random()
+ if (rand < .25):
+ return "6/6"
+ elif (rand < .5):
+ return "3/3"
+ elif (rand < .75):
+ return "2/2"
+ else:
+ return "1"
+
+
+ def draw_label(self,ctx,piece,text,xIni,yIni):
+
+ stroke_r,stroke_g,stroke_b = 0,0,0
+ border_r,border_g,border_b = 0.5,0.5,0.5
+
+ alpha = 1
+ if (piece.player.color != None):
+ xocolor = piece.player.color
+ stroke_r,stroke_g,stroke_b,alpha = style.Color(xocolor.get_stroke_color(),1.0).get_rgba()
+ #border_r,border_g,border_b,aplha = style.Color(xocolor.get_fill_color(),1.0).get_rgba()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+
+ if (text[0] != "G"):
+ #print "Dibujando ",text
+ ctx.select_font_face ("Sans",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_NORMAL)
+ ctx.set_font_size (20)
+ x_bearing, y_bearing, width, height, x_advance, y_advance = ctx.text_extents (text)
+ x = 0.5-(width/2 + x_bearing)
+ y = 0.5-(height/2 + y_bearing)
+ ctx.move_to (xIni+x+(dominoview.SIZE/2), yIni+y+(dominoview.SIZE/2))
+ ctx.show_text (text)
+ else:
+ text = text[1:]
+ xCenter = xIni+(dominoview.SIZE/2)
+ yCenter = yIni+(dominoview.SIZE/2)
+ radio = 22
+ ctx.set_line_width(2)
+
+ if ((text == "0") or (text == "1")):
+ ctx.move_to (xCenter + radio , yCenter)
+ ctx.arc (xCenter, yCenter, radio, 0, 2*M_PI)
+ if (text == "0"):
+ ctx.stroke()
+ if (text == "1"):
+ ctx.fill_preserve()
+ else:
+ numerador = int(text[0])
+ denominador = int(text[2])
+ ctx.move_to (xCenter, yCenter)
+ angulo_porcion = 2 * M_PI / denominador
+ angulo_inicial = 0
+ #print "numerador",numerador,"denominador",denominador,"angulo_porcion",angulo_porcion
+ # relleno las fracciones del numerador
+ for n in range(0,numerador):
+ xIni = math.cos(angulo_inicial) * radio
+ yIni = math.sin(angulo_inicial) * radio
+ #print "N",n,"xIni",xIni,"yIni",yIni
+ ctx.line_to (xCenter + xIni, yCenter + yIni)
+ ctx.arc (xCenter, yCenter, radio, angulo_inicial, angulo_inicial + angulo_porcion)
+ ctx.line_to (xCenter, yCenter)
+ ctx.close_path()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+ ctx.fill()
+ angulo_inicial = angulo_inicial + angulo_porcion
+
+ # pinto los bordes
+ ctx.move_to (xCenter, yCenter)
+ angulo_porcion = 2 * M_PI / denominador
+ angulo_inicial = 0
+ #print "numerador",numerador,"denominador",denominador,"angulo_porcion",angulo_porcion
+ ctx.set_source_rgb (border_r,border_g,border_b)
+ for n in range(0,denominador):
+ xIni = math.cos(angulo_inicial) * radio
+ yIni = math.sin(angulo_inicial) * radio
+ #print "N",n,"xIni",xIni,"yIni",yIni
+ ctx.line_to (xCenter + xIni, yCenter + yIni)
+ ctx.arc (xCenter, yCenter, radio, angulo_inicial, angulo_inicial + angulo_porcion)
+ ctx.line_to (xCenter, yCenter)
+ ctx.close_path()
+ ctx.stroke()
+ angulo_inicial = angulo_inicial + angulo_porcion
+
+
+
+class PieceProcessorPoints:
+
+ """
+ Este es un PieceProccesor que dibuja los valores con puntos
+ Es interesante ver como seria un caso en
+ el que no sea texto lo que pongamos sino imagenes
+
+ """
+
+ def get_name(self):
+ return _("Points")
+
+ def alter_labels(self,pieces):
+ print "No hace nada"
+
+
+ def draw_label(self,ctx,piece,text,xIni,yIni):
+
+ stroke_r,stroke_g,stroke_b = 0,0,0
+ alpha = 1
+ if (piece.player.color != None):
+ xocolor = piece.player.color
+ stroke_r,stroke_g,stroke_b,alpha = style.Color(xocolor.get_stroke_color(),1.0).get_rgba()
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+
+ xCenter = xIni+(dominoview.SIZE/2)
+ yCenter = yIni+(dominoview.SIZE/2)
+
+ separa = (dominoview.SIZE/4)
+ radio = 4
+
+ #
+ # *1 *2
+ # *3 *4 *5
+ # *6 *7
+ #
+
+ # 1
+ if (text == "2") or (text == "3") or (text == "4") or (text == "5") or (text == "6"):
+ ctx.arc (xCenter-separa, yCenter-separa, radio, 0, 2*M_PI)
+ ctx.fill ()
+ # 2
+ if (text == "4") or (text == "5") or (text == "6"):
+ ctx.arc (xCenter+separa, yCenter-separa, radio, 0, 2*M_PI)
+ ctx.fill ()
+
+ # 3
+ if (text == "6"):
+ ctx.arc (xCenter-separa, yCenter, radio, 0, 2*M_PI)
+ ctx.fill ()
+
+ #4
+ if (text == "1") or (text == "3") or (text == "5"):
+ ctx.arc (xCenter, yCenter, radio, 0, 2*M_PI)
+ ctx.fill ()
+
+ # 5
+ if (text == "6"):
+ ctx.arc (xCenter+separa, yCenter, radio, 0, 2*M_PI)
+ ctx.fill ()
+
+ # 6
+ if (text == "4") or (text == "5") or (text == "6"):
+ ctx.arc (xCenter-separa, yCenter+separa, radio, 0, 2*M_PI)
+ ctx.fill ()
+
+ # 7
+ if (text == "2") or (text == "3") or (text == "4") or (text == "5") or (text == "6"):
+ ctx.arc (xCenter+separa, yCenter+separa, radio, 0, 2*M_PI)
+ ctx.fill ()
+
diff --git a/dominoplayer.py b/dominoplayer.py
new file mode 100644
index 0000000..0e389b0
--- /dev/null
+++ b/dominoplayer.py
@@ -0,0 +1,212 @@
+import gobject
+import gtk
+import math, random
+
+import pygtk
+pygtk.require('2.0')
+import getopt
+
+import logging
+from gettext import gettext as _
+import sugar
+from sugar.activity import activity
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.xocolor import XoColor
+
+import dominoview
+from dominoview import Tile
+from dominopiece import DominoPiece
+
+
+class DominoPlayer:
+
+ """
+ Jugadores (automaticos o humanos) del domino
+ """
+
+ def __init__(self,game,number):
+ self.number = number
+ self.name = _('Player ')+str(self.number)
+ self.game = game
+ self._pieces = []
+ self.order_piece_selected = 0
+ self.playing = False
+ self.color = None
+ # se usa para saber si este usuario paso la ultima vuelta
+ self.has_passed = False
+
+ def set_pieces(self,pieces):
+ self._pieces = pieces
+ for n in range(0,len(self._pieces)):
+ piece = self._pieces[n]
+ piece.player = self
+ piece.state = DominoPiece.PIECE_PLAYER
+ self.order_piece_selected = 0
+
+ def get_pieces(self):
+ return self._pieces
+
+ def play(self):
+ #print "Play player",self.number
+ self.playing = True
+ #print "Cant piezas",len(self._pieces)
+ if (self == self.game.ui_player):
+ #print "Abilitando botones"
+ self.game.game_state = self.game.GAME_STATE_SELECT_PIECE
+ if (len(self.game.pieces) > 0):
+ # si hay piezas puede pedir pero no pasar
+ self.game.btnNew.props.sensitive = True
+ self.game.btnPass.props.sensitive = False
+ else:
+ # si no hay piezas no puede pedir pero si pasar
+ self.game.btnNew.props.sensitive = False
+ self.game.btnPass.props.sensitive = True
+
+
+ def end_play(self):
+ if (self == self.game.ui_player):
+ #print "Deshabilitando botones"
+ self.game.btnPass.props.sensitive = False
+ self.game.btnNew.props.sensitive = False
+ #print "End player",self.number
+ self.playing = False
+ self.game.next_player(self.number).play()
+
+
+ def remove_piece(self,piece):
+ cantPieces = len(self._pieces)
+ for n in range(0,len(self._pieces)):
+ p = self._pieces[n]
+ if (piece == p):
+ self._pieces[n] = cantPieces
+ self._pieces.remove(cantPieces)
+ return
+
+ def get_status(self):
+ if (len(self._pieces) > 0):
+ return self.name+' - '+str(len(self._pieces))+' '+_('pieces')+'. '
+ else:
+ return self.name+' - '+_('WIN')+'!!!!. '
+
+
+class SimpleAutoPlayer(DominoPlayer):
+
+ """
+ Jugador automatico simple
+ Busca la primera ficha que pueda ubicarse en alguna de las posiciones
+ si no encuentra una pide
+ NO TIENE NINGUNA ESTRATEGIA
+
+ """
+
+ def play(self):
+ #print "Jugando automatico"
+ if self.game.start == None:
+ # si no hay ninguna pieza en el tablero ponemos la primera
+ piece = self._pieces[0]
+ n,p = self.game.cantX / 2 - 1,self.game.cantY / 2
+ self._put_piece(piece,n,p)
+
+ # seteamos comienzo y fin del domino
+ startTile = Tile(n,p)
+ startTile.value = piece.a
+ startTile.piece = piece
+ self.game.start = startTile
+
+ endTile = Tile(n + 1,p)
+ endTile.value = piece.b
+ endTile.piece = piece
+ self.game.end = endTile
+
+ else:
+ #print "automatica siguiente"
+ # buscamos si tenemos alguna ficha que corresponda
+ # en el comienzo
+ ok = False
+ piece = self._get_piece_with_value(self.game.start.value)
+ if (piece != None):
+ n,p,piece,ok = self._test_good_position(self.game.start,piece)
+ if (ok):
+ self._put_piece(piece,n,p)
+ if (not ok):
+ # en el fin
+ piece = self._get_piece_with_value(self.game.end.value)
+ if (piece != None):
+ n,p,piece,ok = self._test_good_position(self.game.end,piece)
+ if (ok):
+ self._put_piece(piece,n,p)
+ if (not ok):
+ # pido una hasta que sea valida o no hayan mas disponibles
+ # si no encontramos pedimos hasta que alguna sirva
+ while (not ok):
+ #print "Pido pieza"
+ pieces = self.game.take_pieces(1)
+ if (len(pieces) > 0):
+ piece = pieces[0]
+ piece.player = self
+ self.get_pieces().append(piece)
+ n,p,piece,ok = self._test_good_position(self.game.start,piece)
+ if (ok):
+ self._put_piece(piece,n,p)
+ if (not ok):
+ # en el fin
+ n,p,piece,ok = self._test_good_position(self.game.end,piece)
+ if (ok):
+ self._put_piece(piece,n,p)
+ else:
+ ok = True # No hay mas piezas
+ self.has_passed = True
+ if (not ok):
+ self.has_passed = True
+
+ # juega el siguiente jugador
+ self.end_play()
+
+ def _put_piece(self,piece,n,p):
+ self.piece_selected = None
+ x,y = self.game.table.get_tile_position(n,p)
+ self.game.put_piece(self,piece,n,p)
+
+
+ # elige una pieza que tenga un valor
+ def _get_piece_with_value(self,value):
+ for n in range(0,len(self._pieces)):
+ piece = self._pieces[n]
+ if (piece.player == self):
+ #print "get_piece_with_value",piece.a, piece.b
+ if (piece.a == value) or (piece.b == value):
+ return piece
+ return None
+
+
+
+
+ def _test_good_position(self,tile,piece):
+ n,p = tile.n,tile.p
+ # Pruebo con las cuatro posiciones que rodean a n,p
+ # con la pieza en cuatro posiciones
+ for i in range(0,3):
+ # Combino las cuatro posiciones posibles
+ if (i == 0):
+ piece.vertical = False
+ piece.reversed = False
+ if (i == 1):
+ piece.vertical = True
+ piece.reversed = False
+ if (i == 2):
+ piece.vertical = False
+ piece.reversed = True
+ if (i == 3):
+ piece.vertical = True
+ piece.reversed = True
+ if (self.game.test_good_position(piece,n+1,p)):
+ return n+1,p,piece,True
+ if (self.game.test_good_position(piece,n,p+1)):
+ return n,p+1,piece,True
+ if (self.game.test_good_position(piece,n-1,p)):
+ return n-1,p,piece,True
+ if (self.game.test_good_position(piece,n,p-1)):
+ return n,p-1,piece,True
+ # Si no encuentro ninguna posicion valida devuelvo None en la piece
+ return n,p,piece,False
+
diff --git a/dominoview.py b/dominoview.py
new file mode 100644
index 0000000..ee8fa85
--- /dev/null
+++ b/dominoview.py
@@ -0,0 +1,261 @@
+#!/usr/bin/env python
+
+### Piezas del domino
+### By Gonzalo Odiard, 2006 godiard at gmail.com
+### GPL License - http://www.gnu.org/copyleft/gpl.html
+
+
+import gobject
+import gtk
+import cairo
+import rsvg
+
+import pygtk
+pygtk.require('2.0')
+import getopt
+
+import logging
+from gettext import gettext as _
+import sugar
+from sugar.graphics.icon import Icon
+
+import cairoutils
+
+
+# SIZE Es el ancho de una ficha (y la mitads del largo)
+# podemos imaginar el tablero dividido en cuadrados de lado SIZE
+SIZE = 60
+# Si se quiere usar fichas mas grandes, se puede usar SIZE = 70 y cambiar _drawLabel el scale = 3
+
+
+SCREEN_HEIGHT = gtk.gdk.screen_height()
+SCREEN_WIDTH = gtk.gdk.screen_width()
+
+
+class Tile:
+
+ """
+ Informacion de cada posicion del tablero
+ """
+
+ def __init__ (self,n,p):
+ self.n = n
+ self.p = p
+ self.value = -1
+ self.piece = None
+
+class DominoTableView():
+
+ """
+ Dibuja una grilla sobre la que se van a poner las fichas
+ Ademas tiene metodos para saber a que casillero corresponde una posicion del mouse
+ o donde ubicar una ficha
+ """
+
+ __gtype_name__ = 'DominoTableView'
+
+ def __init__(self,**kwargs):
+ self.cantX = int(SCREEN_WIDTH / SIZE) - 1
+ self.cantY = int( ( SCREEN_HEIGHT - (SIZE*3.5) ) / SIZE )
+ self.margenX = int ((SCREEN_WIDTH - SIZE * self.cantX) /2)
+ self.limitTable = SIZE * self.cantY
+ print "Table cantX",self.cantX,"cantY",self.cantY
+
+
+ def paint(self,ctx):
+
+ # agrego 2,2 para que la grilla quede en la base de las piezas (por la perspectiva)
+ alto = 5
+ ctx.move_to(alto, alto)
+
+ ctx.rectangle(self.margenX + alto, 0 + alto, SIZE * self.cantX + alto, SIZE * (self.cantY) + alto)
+ ctx.set_source_rgb (204.0/255.0, 204.0/255.0, 204.0/255.0)
+ ctx.fill()
+
+
+ ctx.set_line_width(1)
+ ctx.set_source_rgb (1, 1, 0)
+
+ for n in range(0,self.cantY+1):
+ ctx.move_to(self.margenX + alto, n * SIZE + alto)
+ ctx.line_to(SCREEN_WIDTH - self.margenX + alto,n*SIZE + alto)
+ ctx.stroke()
+
+ ctx.move_to(0, 0)
+ for n in range(0,self.cantX+1):
+ ctx.move_to(self.margenX + n * SIZE + alto, 0 + alto)
+ ctx.line_to(self.margenX + n * SIZE + alto , self.limitTable + alto)
+ ctx.stroke()
+
+ def get_tile_position(self,n,p):
+ return self.margenX + n * SIZE, (p-1) * SIZE
+
+ def get_tile_coord(self,x,y):
+ return (x - self.margenX) / SIZE, (y / SIZE) +1
+
+ def show_status(self,ctx,text):
+
+ xIni = 10
+ yIni = 5
+
+ stroke_r,stroke_g,stroke_b = 0,0,0
+ alpha = 0.6
+ ctx.set_source_rgba (stroke_r,stroke_g,stroke_b,alpha)
+
+ ctx.select_font_face ("Sans",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_NORMAL)
+ ctx.set_font_size (12)
+ x_bearing, y_bearing, width, height, x_advance, y_advance = ctx.text_extents (text)
+
+ radio = 16
+
+ cairoutils.draw_round_rect(ctx,xIni, yIni, width + radio * 2, height * 2, radio)
+ ctx.stroke()
+
+ ctx.move_to (xIni + radio + x_bearing , yIni + height)
+ ctx.show_text (text)
+ #print "w", width, "h", height,"x_b",x_bearing,"y_b",y_bearing
+
+ def show_scores(self,ctx,score_list):
+ print "scores"
+ alto = 5
+ ctx.move_to(alto, alto)
+
+ ctx.rectangle(self.margenX + alto, 0 + alto, SIZE * self.cantX + alto, SIZE * (self.cantY) + alto)
+ ctx.set_source_rgb (204.0/255.0, 204.0/255.0, 204.0/255.0)
+ ctx.fill()
+
+ ctx.set_line_width(1)
+ ctx.set_source_rgb (1, 1, 0)
+ ctx.rectangle(self.margenX + alto, 0 + alto, SIZE * self.cantX + alto, SIZE * (self.cantY) + alto)
+ ctx.stroke()
+
+ altoRenglon = 40
+
+ stroke_r,stroke_g,stroke_b = 0,0,0
+ alpha = 1
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+
+ ctx.select_font_face ("Sans",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_NORMAL)
+ ctx.set_font_size (30)
+
+
+ x = self.margenX + 200
+ y = altoRenglon * 2
+ ctx.move_to (x,y)
+
+ ctx.move_to (x+300,y)
+ ctx.show_text (_("Played"))
+ ctx.move_to (x+450,y)
+ ctx.show_text (_("Win"))
+ ctx.move_to (x+600,y)
+ ctx.show_text (_("Lost"))
+ y = y + altoRenglon
+ ctx.move_to (x,y)
+
+ for n in range(0,len(score_list)):
+ game_points = score_list[n]
+ ctx.show_text (game_points.name)
+ ctx.move_to (x+350,y)
+ ctx.show_text (str(game_points.played))
+ ctx.move_to (x+500,y)
+ ctx.show_text (str(game_points.win))
+ ctx.move_to (x+650,y)
+ ctx.show_text (str(game_points.lost))
+ y = y + altoRenglon
+ ctx.move_to (x,y)
+
+
+
+ def help(self,ctx):
+
+
+ altoRenglon = 45
+ x = self.margenX + 20
+ y = altoRenglon * 4
+
+ ctx.set_line_width(1)
+ ctx.set_source_rgb (1, 1, 0)
+ ctx.rectangle(self.margenX + 10, altoRenglon * 3, SIZE * self.cantX - 10, y + altoRenglon * 4)
+ ctx.stroke()
+
+
+ stroke_r,stroke_g,stroke_b = 0,0,0
+ alpha = 1
+ ctx.set_source_rgb (stroke_r,stroke_g,stroke_b)
+
+ ctx.select_font_face ("Sans",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_NORMAL)
+ ctx.set_font_size (30)
+ #x_bearing, y_bearing, width, height, x_advance, y_advance = ctx.text_extents ("M")
+
+ ctx.move_to (x,y)
+ ctx.show_text (_("You can select a piece with the arrow keys and use it with enter."))
+
+ y = y + altoRenglon
+ ctx.move_to (x,y)
+ ctx.show_text (_("When you selected the piece, you can move it to the place "))
+
+ y = y + altoRenglon
+ ctx.move_to (x,y)
+ ctx.show_text (_("with the arrows , turn it with space and place it with enter."))
+
+ y = y + altoRenglon
+ ctx.move_to (x,y)
+ ctx.show_text (_("If you want use another piece, press escape."))
+
+ y = y + altoRenglon
+ ctx.move_to (x+80,y)
+ ctx.show_text (_("You can use the cursors to move too."))
+
+ y = y + altoRenglon
+ ctx.move_to (x+80,y)
+ ctx.show_text (_("And use triangle to select, circle to rotate"))
+
+ y = y + altoRenglon
+ ctx.move_to (x+80,y)
+ ctx.show_text (_("and X to use another piece."))
+
+ self.show_svg(ctx,"icons/cursors.svg",x,y - ( altoRenglon * 2.75))
+ self.show_svg(ctx,"icons/gamekeys.svg",x,y - ( altoRenglon * 1.25))
+
+
+
+
+ def show_svg(self,ctx,file_name,x,y):
+ h = rsvg.Handle(file_name)
+ surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
+ temp_ctx = cairo.Context(surf)
+ h.render_cairo(temp_ctx)
+ ctx.translate(x,y)
+ ctx.set_source_surface(surf)
+ ctx.paint()
+ ctx.translate(-x,-y)
+
+
+
+ def msg_end_game(self,ctx,win):
+
+ #snippet_normalize (cr, width, height)
+ ctx.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_BOLD)
+
+ text = ""
+ if (win):
+ ctx.set_font_size (100)
+ text = _("You win!!!")
+ else:
+ ctx.set_font_size (60)
+ text = _("Sorry, you lost")
+
+ x_bearing, y_bearing, width, height, x_advance, y_advance = ctx.text_extents (text)
+ x = (SCREEN_WIDTH - width) / 2
+ y = (SCREEN_HEIGHT - height) / 2
+ ctx.move_to (x, y)
+
+ ctx.text_path (text)
+ ctx.set_source_rgb (0.5,0.5,1)
+ ctx.fill_preserve ()
+ ctx.set_source_rgb (0,0,0)
+ ctx.set_line_width (2)
+ ctx.stroke ()
+
+
+
diff --git a/icons/cursors.svg b/icons/cursors.svg
new file mode 100644
index 0000000..4441258
--- /dev/null
+++ b/icons/cursors.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ viewBox="0 0 55 55"
+ id="svg120"
+ xml:space="preserve"><defs
+ id="defs133">
+
+ </defs><g
+ id="g902"><path
+ d="m 27.577168,50.240568 c 12.43,0 22.503,-10.067 22.503,-22.496 0,-12.431999 -10.073,-22.5109991 -22.503,-22.5109991 -12.426,0 -22.4970012,10.0790001 -22.4970012,22.5109991 0,12.429 10.0710012,22.496 22.4970012,22.496 z"
+ id="path85"
+ style="fill:#ffffff;fill-opacity:1" /><path
+ d="m 50.258621,28.211206 a 21.494253,23.074713 0 1 1 -42.9885061,0 21.494253,23.074713 0 1 1 42.9885061,0 z"
+ transform="translate(-1.1842006,-0.47413793)"
+ id="path103"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 41.342991,14.350767 c -1.325037,-1.310657 -3.481863,-1.294017 -4.818102,0.0057 l -8.918113,8.674043 -8.869285,-8.773025 c -1.325038,-1.310658 -3.455711,-1.319454 -4.791949,-0.01977 -1.33624,1.299669 -1.371363,3.414987 -0.04632,4.725644 l 8.869285,8.773026 -8.918113,8.674042 c -1.33624,1.29967 -1.345208,3.389551 -0.02017,4.700206 1.325037,1.310658 3.455711,1.319455 4.791949,0.01977 l 8.918114,-8.674043 8.869286,8.773027 c 1.325036,1.310656 3.481862,1.294015 4.8181,-0.0057 1.336241,-1.299669 1.345209,-3.38955 0.02016,-4.700206 l -8.869285,-8.773027 8.918113,-8.674043 c 1.336239,-1.299669 1.371361,-3.414986 0.04632,-4.725643 z"
+ id="rect877"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><path
+ d="M 8.7715517,28.645833 11.063218,26.828304"
+ id="path907"
+ style="stroke-width:1px" /><path
+ d="M 10.984195,28.408764 9.0876437,27.065373"
+ id="path909"
+ style="stroke-width:1px" /><path
+ d="m 11.810474,26.568715 c -0.02123,1.502402 -0.01917,0.731322 -0.0018,2.336708 -0.969485,-0.604003 -1.202822,-0.707742 -2.1190416,-1.188744"
+ id="path911"
+ style="fill:#000000;fill-opacity:1;stroke:none" /><path
+ d="m 42.560269,26.568715 c 0.02123,1.502402 0.01917,0.731322 0.0018,2.336708 0.969485,-0.604003 1.202822,-0.707742 2.119042,-1.188744"
+ id="path911-2"
+ style="fill:#000000;fill-opacity:1;stroke:none" /><path
+ d="m 26.411813,10.227087 c 1.502402,-0.02123 0.731322,-0.01917 2.336708,-0.0018 C 28.144518,9.2558024 28.040779,9.0224654 27.559777,8.1062454"
+ id="path911-2-5"
+ style="fill:#000000;fill-opacity:1;stroke:none" /><path
+ d="m 26.411813,45.484119 c 1.502402,0.02123 0.731322,0.01917 2.336708,0.0018 -0.604003,0.969485 -0.707742,1.202822 -1.188744,2.119042"
+ id="path911-2-5-6"
+ style="fill:#000000;fill-opacity:1;stroke:none" /></svg> \ No newline at end of file
diff --git a/icons/gamekeys.svg b/icons/gamekeys.svg
new file mode 100644
index 0000000..9e783ba
--- /dev/null
+++ b/icons/gamekeys.svg
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ viewBox="0 0 55 55"
+ id="svg120"
+ xml:space="preserve"><defs
+ id="defs133">
+
+ </defs><g
+ id="g845"><g
+ id="g841"><path
+ d="m 20.880505,26.979242 a 9.5145051,9.5145052 0 1 1 -19.0290102,0 9.5145051,9.5145052 0 1 1 19.0290102,0 z"
+ id="path1012"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.97098964;stroke-opacity:1" /><rect
+ width="10.069767"
+ height="10.069767"
+ ry="0"
+ x="6.3311167"
+ y="21.944357"
+ id="rect1016"
+ style="fill:none;stroke:#000000;stroke-width:0.93023288;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ id="g833"><path
+ d="m 36.983953,44.158 a 9.5145051,9.5145052 0 1 1 -19.02901,0 9.5145051,9.5145052 0 1 1 19.02901,0 z"
+ id="path1012-6"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.97098964;stroke-opacity:1" /><g
+ transform="translate(1.0165042,0.69535529)"
+ id="g1140"><rect
+ width="12.211441"
+ height="0.12092438"
+ x="-18.201794"
+ y="49.360634"
+ transform="matrix(0.70612764,-0.70808457,0.70808457,0.70612764,0,0)"
+ id="rect1116"
+ style="fill:none;stroke:#000000;stroke-width:0.87907565;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+ width="12.211441"
+ height="0.12092438"
+ x="-55.526817"
+ y="-12.156536"
+ transform="matrix(-0.70808457,-0.70612764,0.70612764,-0.70808457,0,0)"
+ id="rect1116-3"
+ style="fill:none;stroke:#000000;stroke-width:0.87907565;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g><g
+ transform="translate(-1.2158963,0.30024171)"
+ id="g1152"
+ style="fill:#ffffff;fill-opacity:1"><path
+ d="m 21.099138,28.013649 a 9.7593393,9.8383617 0 1 1 -19.5186784,0 9.7593393,9.8383617 0 1 1 19.5186784,0 z"
+ transform="matrix(0.97491283,0,0,0.96708227,17.630029,-16.423399)"
+ id="path1012-5"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1" /><path
+ d="M 32.24138,9.1266136 24.391901,22.905285 16.383961,9.2181013 32.24138,9.1266136 z"
+ transform="matrix(0.66942893,0,0,-0.67776695,12.409739,20.722717)"
+ id="path1150"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.48459351;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ id="g825"><path
+ d="m 53.262689,26.979242 a 9.5145051,9.5145052 0 1 1 -19.02901,0 9.5145051,9.5145052 0 1 1 19.02901,0 z"
+ id="path1012-1"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.97098964;stroke-opacity:1" /><path
+ d="m 48.980848,26.979242 a 5.232664,5.2326642 0 1 1 -10.465328,0 5.232664,5.2326642 0 1 1 10.465328,0 z"
+ id="path1063"
+ style="fill:none;stroke:#000000;stroke-width:1.03467202;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> \ No newline at end of file
diff --git a/icons/scores.svg b/icons/scores.svg
new file mode 100644
index 0000000..017a216
--- /dev/null
+++ b/icons/scores.svg
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#000000">
+ <!ENTITY fill_color "#AAAAAA">
+]>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="55"
+ height="55"
+ viewBox="0 0 55 55"
+ id="svg120"
+ xml:space="preserve"
+ sodipodi:version="0.32"
+ inkscape:version="0.46+devel"
+ sodipodi:docname="scores.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+ id="metadata25"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1280"
+ inkscape:window-height="950"
+ id="namedview23"
+ showgrid="false"
+ inkscape:zoom="4.2909091"
+ inkscape:cx="-15.03178"
+ inkscape:cy="27.5"
+ inkscape:window-x="0"
+ inkscape:window-y="25"
+ inkscape:current-layer="svg120" /><defs
+ id="defs133"><inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 27.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="55 : 27.5 : 1"
+ inkscape:persp3d-origin="27.5 : 18.333333 : 1"
+ id="perspective27" />
+
+ <inkscape:perspective
+ id="perspective103"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" /></defs><path
+ style="fill:#ffffff;fill-opacity:1"
+ id="path85"
+ d="m 27.030899,50.469601 c 12.43,0 22.503,-10.067 22.503,-22.496 0,-12.431999 -10.073,-22.5109993 -22.503,-22.5109993 -12.426,0 -22.4970014,10.0790003 -22.4970014,22.5109993 0,12.429 10.0710014,22.496 22.4970014,22.496 z"
+ sodipodi:nodetypes="csssc" /><g
+ transform="matrix(0.92071889,0,0,0.91256758,1.601103,-2.3415007)"
+ id="g1021"><g
+ transform="translate(-3.1078918,-1.3837867)"
+ id="g1016"><path
+ d="m 30.762712,35.88983 c 0.0017,3.828951 1.355749,8.10662 4.927355,10.034011 1.782099,1.17092 4.244097,1.765389 5.093837,3.94904"
+ id="path941"
+ style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 30.413139,35.88983 c -0.0017,3.828951 -1.355749,8.10662 -4.927355,10.034011 -1.782099,1.17092 -4.244097,1.765389 -5.093837,3.94904"
+ id="path941-9"
+ style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 18.612006,51.504239 15.137942,-0.145557 9.099346,-0.08749"
+ id="path979"
+ style="stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="translate(0.80900671,0)"
+ id="g1008"><path
+ d="m 64.555082,53.608149 a 11.069915,11.419491 0 1 1 -22.139826,-0.01375 l 11.069912,0.0073 z"
+ transform="matrix(0.97475714,0,0,1.3796368,-25.217647,-57.357906)"
+ id="path146"
+ style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 15.461223,21.304558 c -5.887723,2.860782 -2.73218,13.407796 3.33341,9.458674 0.37965,-0.02563 0.746031,-0.162163 1.088887,-0.349992"
+ id="path930"
+ style="fill:none;stroke:&stroke_color;;stroke-width:3.36578608;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path
+ d="m 38.16628,21.304558 c 5.887723,2.860782 2.73218,13.407796 -3.33341,9.458674 -0.37965,-0.02563 -0.746031,-0.162163 -1.088887,-0.349992"
+ id="path930-5"
+ style="fill:none;stroke:&stroke_color;;stroke-width:3.36578608;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg>
diff --git a/locale/es/LC_MESSAGES/org.laptop.Domino.mo b/locale/es/LC_MESSAGES/org.laptop.Domino.mo
new file mode 100644
index 0000000..9ffb7f8
--- /dev/null
+++ b/locale/es/LC_MESSAGES/org.laptop.Domino.mo
Binary files differ
diff --git a/locale/es/activity.linfo b/locale/es/activity.linfo
new file mode 100644
index 0000000..e81a88e
--- /dev/null
+++ b/locale/es/activity.linfo
@@ -0,0 +1,2 @@
+[Activity]
+name = Domino
diff --git a/po/Domino.pot b/po/Domino.pot
new file mode 100644
index 0000000..3561f43
--- /dev/null
+++ b/po/Domino.pot
@@ -0,0 +1,118 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-09-22 22:23-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: activity/activity.info:2
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:123
+msgid "Domino"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominogame.py:346
+msgid "Stack"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoplayer.py:29
+msgid "Player "
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoplayer.py:87
+msgid "pieces"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoplayer.py:89
+msgid "WIN"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:29
+msgid "Simple"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:75
+msgid "Table of"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:135
+msgid "Fractions"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:267
+msgid "Points"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:147
+msgid "Played"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:149
+msgid "Win"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:151
+msgid "Lost"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:191
+msgid "You can select a piece with the arrow keys and use it with enter."
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:195
+msgid "When you selected the piece, you can move it to the place "
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:199
+msgid "with the arrows , turn it with space and place it with enter."
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:203
+msgid "If you want use another piece, press escape."
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:207
+msgid "You can use the cursors to move too."
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:211
+msgid "And use triangle to select, circle to rotate"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:215
+msgid "and X to use another piece."
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:243
+msgid "You win!!!"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:246
+msgid "Sorry, you lost"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:100
+msgid "Start"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:106
+msgid "Get piece"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:112
+msgid "Pass"
+msgstr ""
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:118
+msgid "Scores"
+msgstr ""
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..cd7fc6a
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1 @@
+encoding: UTF-8
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 0000000..ac3e8f8
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,118 @@
+# Spanish translations for PACKAGE package.
+# Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Gonzalo Odiard <godiard@gmail.com>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-09-22 22:23-0300\n"
+"PO-Revision-Date: 2009-09-22 22:25-0300\n"
+"Last-Translator: Gonzalo Odiard <godiard@gmail.com>\n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: activity/activity.info:2
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:123
+msgid "Domino"
+msgstr "Domino"
+
+#: /home/gonzalo/Activities/Domino.activity/dominogame.py:346
+msgid "Stack"
+msgstr "Pozo"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoplayer.py:29
+msgid "Player "
+msgstr "Jugador"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoplayer.py:87
+msgid "pieces"
+msgstr "piezas"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoplayer.py:89
+msgid "WIN"
+msgstr "Gano"
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:29
+msgid "Simple"
+msgstr "Simple"
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:75
+msgid "Table of"
+msgstr "Tabla del"
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:135
+msgid "Fractions"
+msgstr "Fracciones"
+
+#: /home/gonzalo/Activities/Domino.activity/dominopieceprocessor.py:267
+msgid "Points"
+msgstr "Puntos"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:147
+msgid "Played"
+msgstr "Jugados"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:149
+msgid "Win"
+msgstr "Ganados"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:151
+msgid "Lost"
+msgstr "Perdidos"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:191
+msgid "You can select a piece with the arrow keys and use it with enter."
+msgstr "Puedes elegir una pieza con las flechas y utilizarla con enter."
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:195
+msgid "When you selected the piece, you can move it to the place "
+msgstr "Una vez elegida la pieza, la mueves hasta el lugar donde la pondras"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:199
+msgid "with the arrows , turn it with space and place it with enter."
+msgstr "con las flechas, puedes girarla con la tecla espacio y ponerla con enter."
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:203
+msgid "If you want use another piece, press escape."
+msgstr "Si quieres utilizar otra ficha, presiona escape."
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:207
+msgid "You can use the cursors to move too."
+msgstr "Tambien puedes usar los cursores"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:211
+msgid "And use triangle to select, circle to rotate"
+msgstr "El triangulo para seleccionar, el circulo para girar"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:215
+msgid "and X to use another piece."
+msgstr "y la X para usar otra pieza"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:243
+msgid "You win!!!"
+msgstr "Ganaste!!!"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoview.py:246
+msgid "Sorry, you lost"
+msgstr "Lo siento, perdiste"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:100
+msgid "Start"
+msgstr "Comenzar"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:106
+msgid "Get piece"
+msgstr "Pedir pieza"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:112
+msgid "Pass"
+msgstr "Pasar"
+
+#: /home/gonzalo/Activities/Domino.activity/dominoactivity.py:118
+msgid "Scores"
+msgstr "Puntajes"
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..bd1e319
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+if __name__ == "__main__":
+ bundlebuilder.start()
+