Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/BatallaNaval.activity/BatallaNaval.py
diff options
context:
space:
mode:
Diffstat (limited to 'BatallaNaval.activity/BatallaNaval.py')
-rw-r--r--BatallaNaval.activity/BatallaNaval.py249
1 files changed, 133 insertions, 116 deletions
diff --git a/BatallaNaval.activity/BatallaNaval.py b/BatallaNaval.activity/BatallaNaval.py
index ceee1ee..ea99a1d 100644
--- a/BatallaNaval.activity/BatallaNaval.py
+++ b/BatallaNaval.activity/BatallaNaval.py
@@ -7,14 +7,11 @@ import gtk
import logging
import random
-try:
- from sugar.activity.activity import Activity, ActivityToolbox
-except:
- pass
-
+# Permite definir un Log que filtra mensajes a la salida estándar dependiendo de nivel elegido.
log = logging.getLogger('BatallaNaval')
log.setLevel(logging.DEBUG)
+# Diccionario que contiene el nombre y largo de cada barco
lista_barcos = {
"Portaaviones": 5,
"Acorazado": 4,
@@ -23,6 +20,8 @@ lista_barcos = {
"Destructor": 2}
class PanelPrincipal(gtk.HBox):
+ ''' Panel Principal es un Widget que contiene ambos tableros y se encarga
+ de crear los barcos en posiciones al azar para cada tablero '''
def __init__(self):
gtk.HBox.__init__(self, True)
@@ -34,23 +33,25 @@ class PanelPrincipal(gtk.HBox):
barcos_propios = crear_barcos()
for barco in barcos_propios:
self.tablero1.agregar_barco(barco, True)
- log.debug("barco:%s, %s (%s, %s)" % (barco.name, barco.orientacion, barco.pos[0], barco.pos[1]))
+ log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1]))
log.debug("Barcos Enemigos")
self.barcos_enemigos = crear_barcos()
for barco in self.barcos_enemigos:
self.tablero2.agregar_barco(barco, False)
- log.debug("barco:%s, %s (%s, %s)" % (barco.name, barco.orientacion, barco.pos[0], barco.pos[1]))
+ log.debug("barco:%s, %s (%s, %s)" % (barco.nombre, barco.orientacion, barco.pos[0], barco.pos[1]))
self.add(self.tablero1)
self.add(self.tablero2)
- self.show_all()
-
self.jugadas_enemigas = [] # Lleva un registro de las jugadas hechas por la computadora
+
+ self.show_all()
# Carga barcos remotos
def cargar_barcos(self, barcos):
+ ''' Esta función es llamada cuando me conecto en red con otro usuario, recibo
+ una tupla con los datos de los barcos enemigos. '''
log.debug("Cargando barcos enemigos")
self.tablero2.barcos = []
for dato in barcos:
@@ -64,19 +65,25 @@ class PanelPrincipal(gtk.HBox):
self.tablero2.agregar_barco(barco, False)
log.debug("barco:%s, %s (%s, %s)" % (barco.name, barco.orientacion, barco.pos[0], barco.pos[1]))
- # Cuando el enemigo juega sobre mi tablero, hago la judada y le respondo si fue tocado
def jugada_red(self, x, y):
+ ''' Callback de colaboración para la señal Play.
+ Cuando el enemigo juega sobre mi tablero, reflejo la judada y le respondo si fue tocado '''
return self.tablero1.jugada(self.tablero1.filas[x-1][y-1])
- # Cuando yo mismo hice una jugada sobre el tablero enemigo, si hay colaboración actualizo según la respuesta
def jugada_hecha(self, x, y):
- # Si hay colaboración, indico al oponente la jugada que hice
- if self.colaboracion:
+ ''' Cuando yo mismo hice una jugada sobre el tablero enemigo
+ si la actividad está compartida indico al oponente la jugada que hice,
+ en caso contrario me simulo una jugada random del enemigo. '''
+
+ # Si estoy compartiendo con alguien, indico al oponente la jugada que hice
+ if self.colaboracion and self.colaboracion.entered:
+ log.debug("Señalo jugada a los participantes")
self.colaboracion.Play(x, y)
return
# Sinó, la computadora hace una jugada al azar sobre el tablero propio
if len(self.jugadas_enemigas) == 100:
+ log.error("Alcanzó las 100 jugadas.")
return
ok = False
@@ -86,14 +93,64 @@ class PanelPrincipal(gtk.HBox):
ok = True
self.jugadas_enemigas.append((x, y))
- self.tablero1.filas[x-1][y-1].clicked()
+ self.tablero1.jugada(self.tablero1.filas[x-1][y-1])
+
+class Barco(gtk.Frame):
+ ''' Esta clase representa un barco, tiene nombre, largo, orientación y posición.
+ Como es un widget puede ser mostrado en la pantalla y tiene un texto con el nombre del barco '''
+ horizontal = 'H'
+ vertical = 'V'
+
+ def __init__(self, nombre, largo, pos, orientacion = horizontal):
+ gtk.Frame.__init__(self)
+ self.nombre = nombre
+ self.largo = largo
+ self.pos = pos
+
+ # Agrega una etiqueta con el nombre del barco
+ self.label = gtk.Label(nombre)
+ self.add(self.label)
+
+ self.set_orientacion(orientacion) # Graba la orientación y ajusta la etiqueta a dicha orientación.
+
+ def set_orientacion(self, orientacion):
+ ''' Graba la orientación y ajusta la etiqueta a dicha orientación. '''
+ self.orientacion = orientacion
+ if self.orientacion == Barco.horizontal:
+ self.label.set_angle(0)
+ else:
+ self.label.set_angle(90)
+
+ def get_inicio(self):
+ return self.pos
+
+ def get_fin(self):
+ if self.orientacion == Barco.horizontal:
+ return self.pos[0], self.pos[1] + self.largo - 1
+ else:
+ return self.pos[0] + self.largo - 1, self.pos[1]
+
+ def get_filas(self):
+ return range(self.get_inicio()[0], self.get_fin()[0]+1)
+
+ def get_cols(self):
+ return range(self.get_inicio()[1], self.get_fin()[1]+1)
+
+ def get_celdas(self):
+ return [(f, c) for f in self.get_filas() for c in self.get_cols()]
+
def crear_barcos():
- barcos = [Barco(b[0], b[1], None) for b in lista_barcos.items()]
+ ''' Parte de la lista_barcos para crear un conjunto de barcos en posiciones al azar. '''
- celdas_ocupadas = []
+ # Convierte la lista de definición en una lista de objetos Barco sin posición definida
+ barcos = [Barco(nombre, largo, None) for nombre, largo in lista_barcos.items()]
+
+ celdas_ocupadas = [] # Llevo una lista de las celdas ya ocupadas por los barcos
for barco in barcos:
+ # Para cada barco me mantengo en un loop hasta que encuentre coordenadas al azar que no
+ # intersecten con ningún barco ya ubicado.
ok = False
while not ok:
# Determino al azar si es horizontal o vertical
@@ -107,41 +164,46 @@ def crear_barcos():
barco.set_orientacion(Barco.vertical)
posx = random.randint(1, 10-barco.largo+1)
posy = random.randint(1, 10)
-
barco.pos = (posx, posy)
- ok = True
- for celda in barco.get_celdas():
- if celda in celdas_ocupadas:
- ok = False
- if ok:
+
+ # Verifico si la posición elegida no intersecciona con las celdas ya ocupadas por otros barcos
+ # Convierto las listas en sets y aplico intersección
+ interseccion = set(barco.get_celdas()) & set(celdas_ocupadas)
+ if not interseccion:
+ ok = True
celdas_ocupadas.extend(barco.get_celdas())
return barcos
class Celda(gtk.Button):
-
- def __init__(self, pos, clicked_cb):
+ ''' Esta clase representa una celda del tablero, como es subclase de button se le puede
+ conectar la señal "clicked".
+ También presenta funciones para ocultar y colorearse dependiendo de si tocó un barco o dió agua. '''
+
+ def __init__(self, pos):
gtk.Button.__init__(self)
self.pos = pos
-
- self.connect("clicked", clicked_cb)
def ocultar(self):
+ ''' Oculta permanentemente la celda, de modo que show_all no la muestre '''
self.set_no_show_all(True)
self.hide()
- def tocado(self):
- color = gtk.gdk.Color(65535,65535/2,0)
+ def colorear(self, color):
self.modify_bg(gtk.STATE_NORMAL, color)
self.modify_bg(gtk.STATE_PRELIGHT, color)
self.show() # Por si está oculta atrás de un barco
+
+ def tocado(self):
+ self.colorear( gtk.gdk.Color(65535,65535/2,0) )
def agua(self):
- color = gtk.gdk.Color(0,0,65535/2)
- self.modify_bg(gtk.STATE_NORMAL, color)
- self.modify_bg(gtk.STATE_PRELIGHT, color)
- self.show() # Por si está oculta atrás de un barco
-
+ self.colorear( gtk.gdk.Color(0,0,65535/2) )
+
+
class Tablero(gtk.Frame):
+ ''' Define un tablero, el tablero está definido con una tabla exterior que permite poner
+ los títulos de las filas y las columnas (que a su vez son tablas) y una tabla interior
+ que tiene todas las celdas del tablero (tabla_celdas). '''
def __init__(self, llamada_jugada_hecha):
gtk.Frame.__init__(self)
@@ -159,62 +221,65 @@ class Tablero(gtk.Frame):
label = gtk.Label(char)
tabla_letras.attach(label, 0, 1, i-1, i)
- # Se hace una tabla para ubicar las letras, los números y el tablero
+ # Se hace una tabla para ubicar las letras, los números y la tabla de celdas
self.tabla = gtk.Table(2, 2, False)
self.add(self.tabla)
+ # Opciones para las tablas de letras y números.
opciones = gtk.SHRINK|gtk.FILL
- label = gtk.Label(" ")
+ label = gtk.Label(" ") # Para dar más espacio a la columna de letras
self.tabla.attach(label, 0, 1, 0, 1, xoptions=opciones, yoptions=opciones)
-
self.tabla.attach(tabla_numeros, 1, 2, 0, 1, xoptions=opciones, yoptions=opciones)
self.tabla.attach(tabla_letras, 0, 1, 1, 2, xoptions=opciones, yoptions=opciones)
- self.filas = []
-
# El tablero es otra tabla
self.tabla_celdas = gtk.Table(10, 10, True)
self.tabla.attach(self.tabla_celdas, 1, 2, 1, 2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL|gtk.EXPAND)
-
+
+ self.filas = []
+ # Creo todas las celdas, las guardo en la colección de filas y las adjunto al tablero
for i in range(1, 11):
- row = []
+ fila = []
for j in range(1, 11):
- left = j - 1
- top = i - 1
- celda = Celda((i, j), self.celda_clickeada)
- row.append(celda)
- self.tabla_celdas.attach(celda, left, j, top, i)
- #print label.get_text()
- self.filas.append(row)
+ celda = Celda((i, j))
+ celda.connect("clicked", self.celda_clickeada)
+ fila.append(celda)
+ self.tabla_celdas.attach(celda, j-1, j, i-1, i)
+ self.filas.append(fila)
- self.barcos = [] # Los barcos que hay en el tablero
+ # Los barcos que hay en el tablero
+ self.barcos = []
+ # Callback para cuando el jugador hace una jugada en el tablero
self.llamada_jugada_hecha = llamada_jugada_hecha
- def agregar_barco(self, barco, show):
+ def agregar_barco(self, barco, mostrar):
+ ''' Agrega un barco al tablero, si mostrar=True sustituye las celdas que ocupa por el barco. '''
self.barcos.append(barco)
- if show:
- for i in barco.get_filas():
- for j in barco.get_cols():
- self.ocultar_celda(i, j)
- izq = barco.get_inicio()[1]-1
- der = barco.get_fin()[1]
- arr = barco.get_inicio()[0]-1
- aba = barco.get_fin()[0]
- self.tabla_celdas.attach(barco, izq, der, arr, aba)
-
+ if mostrar:
+ # Oculta las celdas que ocupa el barco
+ for i, j in barco.get_celdas():
+ self.ocultar_celda(i, j)
+
+ # Obtiene los extremos del barco y lo adjunta a la tabla
+ arr, izq = barco.get_inicio()
+ aba, der = barco.get_fin()
+ self.tabla_celdas.attach(barco, izq-1, der, arr-1, aba)
+
def ocultar_celda(self, i, j):
self.filas[i-1][j-1].ocultar()
def celda_clickeada(self, celda):
- # Cuando hay definido un callback de jugadas hechas, significa que es el tablero en el que puedo jugar
+ ''' Cuando hay definido un callback de jugadas hechas, significa que en este tablero puedo jugar.
+ Realizo la jugada y notifico al callback '''
if self.llamada_jugada_hecha:
# Este es el callback para cuando clickean una celda
self.jugada(celda)
self.llamada_jugada_hecha(celda.pos[0], celda.pos[1])
def jugada(self, celda):
+ ''' verifica si la jugada da en algún barco o en el agua y manda la señal correcta a la celda '''
tocado = False
for barco in self.barcos:
if celda.pos in barco.get_celdas():
@@ -222,59 +287,16 @@ class Tablero(gtk.Frame):
celda.tocado()
if not tocado:
celda.agua()
-
+
+ log.debug("Pos:%s Tocado:%s", str(celda.pos), tocado)
return tocado
-class Barco(gtk.Frame):
-
- horizontal = 'H'
- vertical = 'V'
-
- def __init__(self, nombre, largo, pos, orientacion = horizontal):
- #gtk.Label.__init__(self, nombre)
- gtk.Frame.__init__(self)
- self.nombre = nombre
- self.largo = largo
- self.pos = pos
- self.label = gtk.Label(nombre)
- self.add(self.label)
- self.set_orientacion(orientacion)
-
- def set_orientacion(self, orientacion):
- self.orientacion = orientacion
- if self.orientacion == Barco.horizontal:
- self.label.set_angle(0)
- else:
- self.label.set_angle(90)
-
- def get_inicio(self):
- return self.pos
-
- def get_fin(self):
- if self.orientacion == Barco.horizontal:
- return self.pos[0], self.pos[1] + self.largo - 1
- else:
- return self.pos[0] + self.largo - 1, self.pos[1]
-
- def get_filas(self):
- return range(self.get_inicio()[0], self.get_fin()[0]+1)
-
- def get_cols(self):
- return range(self.get_inicio()[1], self.get_fin()[1]+1)
-
- def get_celdas(self):
- return [(f, c) for f in self.get_filas() for c in self.get_cols()]
-
-# Esta función es el punto de entrada común para sugar y modo standalone
-# standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar
def init(standalone, ventana_principal):
-
+ ''' Esta función es el punto de entrada común para sugar y modo standalone
+ standalone es un boolean que indica si es Standalone o se ejecuta desde Sugar '''
panel_principal = PanelPrincipal()
if not standalone:
- toolbox = ActivityToolbox(ventana_principal)
- ventana_principal.set_toolbox(toolbox)
- toolbox.show()
ventana_principal.set_canvas(panel_principal)
# Colaboración
@@ -285,24 +307,19 @@ def init(standalone, ventana_principal):
panel_principal.cargar_barcos, # World
panel_principal.jugada_red, # Play
panel_principal.tablero1.barcos)# Mis barcos
-
else:
ventana_principal.add(panel_principal)
panel_principal.colaboracion = None
-
+
ventana_principal.set_title("Batalla Naval - ceibalJAM")
ventana_principal.connect("destroy", lambda wid: gtk.main_quit())
ventana_principal.connect("delete_event", lambda a1, a2: gtk.main_quit())
ventana_principal.show()
-# Este es el procedimiento principal en modo standalone
-def main():
+# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar)
+if __name__ == "__main__":
+ log.addHandler(logging.StreamHandler())
ventana_principal = gtk.Window(gtk.WINDOW_TOPLEVEL)
init(True, ventana_principal)
gtk.main()
- return 0
-
-# Este código se ejecuta sólo cuando se ejecuta directo ese módulo (no cuando se importa desde sugar)
-if __name__ == "__main__":
- main()