diff options
author | Gonzalo Odiard <gonzalo@nautilus.localdomain> | 2009-10-22 03:28:06 (GMT) |
---|---|---|
committer | Gonzalo Odiard <gonzalo@nautilus.localdomain> | 2009-10-22 03:28:06 (GMT) |
commit | cae62c461a6f187bbbd4bb26a080a9f76f9d8b95 (patch) | |
tree | 5e20a332dba42c4e3d06f8b8ab738fb559381d6c |
agrego todos los archivos
-rw-r--r-- | TODO | 35 | ||||
-rw-r--r-- | activity/activity.info | 7 | ||||
-rw-r--r-- | activity/domino-icon.svg | 93 | ||||
-rw-r--r-- | cairoutils.py | 25 | ||||
-rw-r--r-- | dominoactivity.py | 466 | ||||
-rw-r--r-- | dominogame.py | 357 | ||||
-rw-r--r-- | dominopiece.py | 196 | ||||
-rw-r--r-- | dominopieceprocessor.py | 327 | ||||
-rw-r--r-- | dominoplayer.py | 212 | ||||
-rw-r--r-- | dominoview.py | 261 | ||||
-rw-r--r-- | icons/cursors.svg | 44 | ||||
-rw-r--r-- | icons/gamekeys.svg | 65 | ||||
-rw-r--r-- | icons/scores.svg | 91 | ||||
-rw-r--r-- | locale/es/LC_MESSAGES/org.laptop.Domino.mo | bin | 0 -> 1948 bytes | |||
-rw-r--r-- | locale/es/activity.linfo | 2 | ||||
-rw-r--r-- | po/Domino.pot | 118 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | po/es.po | 118 | ||||
-rw-r--r-- | setup.py | 5 |
19 files changed, 2423 insertions, 0 deletions
@@ -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 Binary files differnew file mode 100644 index 0000000..9ffb7f8 --- /dev/null +++ b/locale/es/LC_MESSAGES/org.laptop.Domino.mo 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() + |