/[ambar]/ambar/sala.py
ViewVC logotype

Diff of /ambar/sala.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2.1 by amoyav, Tue Nov 5 11:54:43 2002 UTC revision 2.2 by pabloruiz, Tue Nov 5 22:58:22 2002 UTC
# Line 1  Line 1 
1  #!/usr/bin/env python  #!/usr/bin/env python
2  #  #
3  #Minë. Mundo Interactivo-Narrativo en Español [Tierra-Media]  #Minë. Mundo Interactivo-Narrativo en Español [Tierra-Media]
4  #Copyright (C) 2002  Pablo Ruiz Múzquiz  #Copyright (C) 2002  Pablo Ruiz Múzquiz
5  #  #
6  #  #
7  #This program is free software; you can redistribute it and/or modify  #This program is free software; you can redistribute it and/or modify
8  #it under the terms of the GNU General Public License as published by  #it under the terms of the GNU General Public License as published by
9  #the Free Software Foundation; either version 2 of the License, or  #the Free Software Foundation; either version 2 of the License, or
10  #(at your option) any later version.  #(at your option) any later version.
11  #  #
12  #This program is distributed in the hope that it will be useful,  #This program is distributed in the hope that it will be useful,
13  #but WITHOUT ANY WARRANTY; without even the implied warranty of  #but WITHOUT ANY WARRANTY; without even the implied warranty of
14  #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  #GNU General Public License for more details.  #GNU General Public License for more details.
16  #  #
17  #You should have received a copy of the GNU General Public License  #You should have received a copy of the GNU General Public License
18  #along with this program; if not, write to the Free Software  #along with this program; if not, write to the Free Software
19  #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  #  #
21    
22  #  #
23  #Fichero: sala.py  #Fichero: sala.py
24    
25  """Clase Sala."""  """Clase Sala."""
26    
27    
28  from xml.dom import minidom  from xml.dom import minidom
29  import random  import random
30  import sys  import sys
31  import string  import string
32  import os  import os
33  import cPickle  import cPickle
34    
35  from objeto import *  from objeto import *
36  from utils import *  from utils import *
37  from fechahoramine import *  from fechahoramine import *
38    
39  class Sala:  class Sala:
40      """Una habitacion o sala dentro del juego.      """Una habitacion o sala dentro del juego.
41            
42      Contiene los siguientes atributos:      Contiene los siguientes atributos:
43       - id (string): identifica univocamente a la sala. No puede contener espacios y debe       - id (string): identifica univocamente a la sala. No puede contener espacios y debe
44                      tener el formato: nombre_de_area-identificador_de_sala.                      tener el formato: nombre_de_area-identificador_de_sala.
45       - version (string): versión del sistema de salas.       - version (string): versión del sistema de salas.
46       - autor (string): nombre del autor de la descripción.       - autor (string): nombre del autor de la descripción.
47       - area (string): nombre del area a la que pertenece la sala.       - area (string): nombre del area a la que pertenece la sala.
48       - comentario (string): comentario explicativo del fichero de sala.       - comentario (string): comentario explicativo del fichero de sala.
49       - nombre (string): texto con el nombre corto de la sala, tal como sale en pantalla.       - nombre (string): texto con el nombre corto de la sala, tal como sale en pantalla.
50       - aura (int): nivel de aura de la sala (50 = normal, 0-50 = malvado, 50-100 = bueno).       - aura (int): nivel de aura de la sala (50 = normal, 0-50 = malvado, 50-100 = bueno).
51       - volumen (float): volumen total que puede contener (1 unidad = tamaño de un humano).       - volumen (float): volumen total que puede contener (1 unidad = tamaño de un humano).
52       - luz (int): nivel de iluminación (0 = oscuridad total, 100 = enfrente de Eru).       - luz (int): nivel de iluminación (0 = oscuridad total, 100 = enfrente de Eru).
53       - combate (string): si se puede combatir en esta sala ("si" o "no").       - combate (string): si se puede combatir en esta sala ("si" o "no").
54       - ocultabilidad (int): facilidad de ocultarse (0 = imposible, 100 = seguro).       - ocultabilidad (int): facilidad de ocultarse (0 = imposible, 100 = seguro).
55       - descripcion ({String:any}[]): descripcion de la sala. Consiste en una lista de items,       - descripcion ({String:any}[]): descripcion de la sala. Consiste en una lista de items,
56                                       y cada item es un conjunto de propiedades en forma de                                       y cada item es un conjunto de propiedades en forma de
57                                       diccionario:                                       diccionario:
58                                        - "dificultad" (int): dificultad para percibir el item                                        - "dificultad" (int): dificultad para percibir el item
59                                                              (0 = automatico, 100 = imposible)                                                              (0 = automatico, 100 = imposible)
60                                        - "texto" (string): el texto del item                                        - "texto" (string): el texto del item
61       - salidas ({String:any}[]): lista de salidas de la sala, siendo cada salida un diccionario:       - salidas ({String:any}[]): lista de salidas de la sala, siendo cada salida un diccionario:
62                                   - "direccion" (string): el punto cardinal (norte, sur, etc.)                                   - "direccion" (string): el punto cardinal (norte, sur, etc.)
63                                   - "dificultad" (int): dificultad para percibirla (0-100)                                   - "dificultad" (int): dificultad para percibirla (0-100)
64                                   - "id" (string): el id de la sala a donde se va por ahi                                   - "id" (string): el id de la sala a donde se va por ahi
65                                   - "descripcion" (string): lo que se ve al mirar en esa direccion                                   - "descripcion" (string): lo que se ve al mirar en esa direccion
66                                   - "tipo_cierre" (string): el tipo de cerradura que hay (ninguno,                                   - "tipo_cierre" (string): el tipo de cerradura que hay (ninguno,
67                                                             cerradura, horario, magia)                                                             cerradura, horario, magia)
68                                   - "datos_cierre" (string): información adicional sobre el cierre:                                   - "datos_cierre" (string): información adicional sobre el cierre:
69                                                              * ninguno: vacío                                                              * ninguno: vacío
70                                                              * cerradura: id de objeto llave                                                              * cerradura: id de objeto llave
71                                                              * horario: rango(s) horario(s) de apertura,                                                              * horario: rango(s) horario(s) de apertura,
72                                                                formato hora_ini-hora_fin, separados por                                                                formato hora_ini-hora_fin, separados por
73                                                                comas. Puede incluir un espacio y el id                                                                comas. Puede incluir un espacio y el id
74                                                                de la llave que abre cuando está cerrada                                                                de la llave que abre cuando está cerrada
75                                                              * magia: id de hechizo (sin implementar)                                                              * magia: id de hechizo (sin implementar)
76                                   - "mensaje_cerrado" (string): mensaje que sale si se intenta salir                                   - "mensaje_cerrado" (string): mensaje que sale si se intenta salir
77                                                                 estando cerrada.                                                                 estando cerrada.
78       - objetos ({String:any}[]): lista de objetos de la sala, siendo cada objeto un diccionario:       - objetos ({String:any}[]): lista de objetos de la sala, siendo cada objeto un diccionario:
79                                   - "id" (string): el id del objeto                                   - "id" (string): el id del objeto
80                                   - "probabilidad" (int): probabilidad de que reaparezca cada vez                                   - "probabilidad" (int): probabilidad de que reaparezca cada vez
81                                                           que alguien entra en la sala (0-100)                                                           que alguien entra en la sala (0-100)
82                                   - "maximo" (int): maximos objetos que pueden aparecer (si es                                   - "maximo" (int): maximos objetos que pueden aparecer (si es
83                                                     0, no hay máximo)                                                     0, no hay máximo)
84                                   - "dificultad" (int): dificultad para percibirlo (0-100)                                   - "dificultad" (int): dificultad para percibirlo (0-100)
85                                   - "instancias" (Objeto[]): lista con una o más instancias del                                   - "instancias" (Objeto[]): lista con una o más instancias del
86                                                              objeto real (puede estar vacía si                                                              objeto real (puede estar vacía si
87                                                              probabilidad > 0, porque es posible                                                              probabilidad > 0, porque es posible
88                                                              que reaparezcan objetos más tarde)                                                              que reaparezcan objetos más tarde)
89       - encuentros ({String:any}[]): lista de pnjs propios de la sala, siendo cada encuentro       - encuentros ({String:any}[]): lista de pnjs propios de la sala, siendo cada encuentro
90                                      un diccionario:                                      un diccionario:
91                                      - "id" (string): el id del pnj                                      - "id" (string): el id del pnj
92                                      - "probabilidad" (int): probabilidad de que reaparezca cada                                      - "probabilidad" (int): probabilidad de que reaparezca cada
93                                                              vez que alguien entra en la sala                                                              vez que alguien entra en la sala
94                                                              (0-100)                                                              (0-100)
95                                      - "maximo" (int): maximos pnjs que pueden aparecer (si es                                      - "maximo" (int): maximos pnjs que pueden aparecer (si es
96                                                        0, no hay máximo)                                                        0, no hay máximo)
97                                      - "dificultad" (int): dificultad para percibirlo (0-100)                                      - "dificultad" (int): dificultad para percibirlo (0-100)
98                                      - "descripcion" (string): que aspecto tiene el personaje                                      - "descripcion" (string): que aspecto tiene el personaje
99       - personajes (Personaje{}): diccionario con los personajes que se encuentran en la sala,       - personajes (Personaje{}): diccionario con los personajes que se encuentran en la sala,
100                                indexado por id. NO MODIFICAR DIRECTAMENTE, SINO CON                                indexado por id. NO MODIFICAR DIRECTAMENTE, SINO CON
101                                entrar_personaje() Y salir_personaje()                                entrar_personaje() Y salir_personaje()
102       - n_jugadores (int): numero de personajes de tipo PersonajeJugador dentro de la sala       - n_jugadores (int): numero de personajes de tipo PersonajeJugador dentro de la sala
103       - __fecha_fichero (int): fecha de la ultima modificacion del fichero de descripcion       - __fecha_fichero (int): fecha de la ultima modificacion del fichero de descripcion
104            
105      Al instanciar una sala, se crea nueva y se lee desde el fichero de descripcion de sala,      Al instanciar una sala, se crea nueva y se lee desde el fichero de descripcion de sala,
106      poniendola en su estado inicial. Mas tarde, se puede salvar en un fichero de sala,      poniendola en su estado inicial. Mas tarde, se puede salvar en un fichero de sala,
107      borrarla y cargarla despues, manteniendo su estado (situacion de objetos y personajes      borrarla y cargarla despues, manteniendo su estado (situacion de objetos y personajes
108      contenidos, tanto PJs como PNJs).      contenidos, tanto PJs como PNJs).
109            
110      Importante: al salvar una sala se salvan también todos los objetos y todos los personajes      Importante: al salvar una sala se salvan también todos los objetos y todos los personajes
111      contenidas en ella. El módulo "Pickle" se encarga de todo, incluyendo la resolución del bucle      contenidas en ella. El módulo "Pickle" se encarga de todo, incluyendo la resolución del bucle
112      formado por el atributo "sala" de la clase Personaje.      formado por el atributo "sala" de la clase Personaje.
113    
114      Invariantes:      Invariantes:
115        id != None        id != None
116        version != None        version != None
117        autor != None        autor != None
118        area != None        area != None
119        comentario != None        comentario != None
120        nombre != None        nombre != None
121        aura in range(0,100)        aura in range(0,100)
122        volumen > 0        volumen > 0
123        luz in range(0,100)        luz in range(0,100)
124        combate in ["si", "no"]        combate in ["si", "no"]
125        ocultabilidad in range(0,100)        ocultabilidad in range(0,100)
126    
127        descripcion != None        descripcion != None
128        len(descripcion) >= 0        len(descripcion) >= 0
129        descripcion[i]["dificultad"] in range(0,100)        descripcion[i]["dificultad"] in range(0,100)
130        descripcion[i]["texto"] != None        descripcion[i]["texto"] != None
131    
132        salidas != None        salidas != None
133        len(salidas) >= 0        len(salidas) >= 0
134        salidas[i]["direccion"] != Null        salidas[i]["direccion"] != Null
135        salidas[i]["dificultad"] in range(0,100)        salidas[i]["dificultad"] in range(0,100)
136        salidas[i]["id"] != Null        salidas[i]["id"] != Null
137        salidas[i]["descripcion"] != Null        salidas[i]["descripcion"] != Null
138        salidas[i]["tipo_cierre"] in ("ninguno", "cerradura", "horario", "magia")        salidas[i]["tipo_cierre"] in ("ninguno", "cerradura", "horario", "magia")
139        salidas[i]["datos_cierre"] != Null        salidas[i]["datos_cierre"] != Null
140        salidas[i]["mensaje_cerrado"] != Null        salidas[i]["mensaje_cerrado"] != Null
141    
142        objetos != None        objetos != None
143        len(objetos) >= 0        len(objetos) >= 0
144        objetos[i]["id"] != Null        objetos[i]["id"] != Null
145        objetos[i]["probabilidad"] in range(0,100)        objetos[i]["probabilidad"] in range(0,100)
146        objetos[i]["maximo"] >= 0        objetos[i]["maximo"] >= 0
147        objetos[i]["dificultad"] in range(0,100)        objetos[i]["dificultad"] in range(0,100)
148        objetos[i]["instancias"] != Null        objetos[i]["instancias"] != Null
149    
150        encuentros != None        encuentros != None
151        len(encuentros) >= 0        len(encuentros) >= 0
152        encuentros[i]["id"] != Null        encuentros[i]["id"] != Null
153        encuentros[i]["probabilidad"] in range(0,100)        encuentros[i]["probabilidad"] in range(0,100)
154        encuentros[i]["maximo"] >= 0        encuentros[i]["maximo"] >= 0
155        encuentros[i]["dificultad"] in range(0,100)        encuentros[i]["dificultad"] in range(0,100)
156        encuentros[i]["descripcion"] != Null        encuentros[i]["descripcion"] != Null
157    
158        personajes != None        personajes != None
159        personajes[i].sala == self        personajes[i].sala == self
160    
161        n_jugadores >= 0        n_jugadores >= 0
162        n_jugadores <= len(personajes)        n_jugadores <= len(personajes)
163    
164        __fecha_fichero >= 0        __fecha_fichero >= 0
165      """      """
166    
167      # Version del sistema de descripciones de sala (se incrementa cada vez que cambia      # Version del sistema de descripciones de sala (se incrementa cada vez que cambia
168      # el formato de los ficheros de desc_salas)      # el formato de los ficheros de desc_salas)
169      VERSION_DESC_SALA = '1.2'      VERSION_DESC_SALA = '1.2'
170    
171      # Version del sistema de salas (se incrementa cada vez que varian los atributos      # Version del sistema de salas (se incrementa cada vez que varian los atributos
172      # de la clase Sala)      # de la clase Sala)
173      VERSION_SALA = '1.2'      VERSION_SALA = '1.2'
174    
175      DIR_DESC_SALAS = 'desc_salas'      DIR_DESC_SALAS = 'desc_salas'
176      EXT_DESC_SALAS = '.xml'      EXT_DESC_SALAS = '.xml'
177      DIR_SALAS = 'salas'      DIR_SALAS = 'salas'
178      EXT_SALAS = ''      EXT_SALAS = ''
179                                        
180    
181      def __init__(self, id):      def __init__(self, id):
182          """Crea una sala nueva a partir de un fichero de descripción de sala.          """Crea una sala nueva a partir de un fichero de descripción de sala.
183                    
184          Requiere:          Requiere:
185            id != None            id != None
186            id corresponde con un fichero existente            id corresponde con un fichero existente
187          """          """
188                    
189          self.id = id          self.id = id
190          self.__inicializar_sala()          self.__inicializar_sala()
191    
192    
193      def __inicializar_sala(self):      def __inicializar_sala(self):
194          """Rellena todos los datos de la sala a partir de su fichero          """Rellena todos los datos de la sala a partir de su fichero
195          de descripcion.          de descripcion.
196          """          """
197          self.personajes = {}          self.personajes = {}
198          self.n_jugadores = 0              self.n_jugadores = 0    
199    
200          archivo = os.path.join(Sala.DIR_DESC_SALAS, self.id.split('-')[0],          archivo = os.path.join(Sala.DIR_DESC_SALAS, self.id.split('-')[0],
201                                 self.id + Sala.EXT_DESC_SALAS)                                 self.id + Sala.EXT_DESC_SALAS)
202          stream = open(archivo)          stream = open(archivo)
203          doc_xml = minidom.parse(stream).documentElement          doc_xml = minidom.parse(stream).documentElement
204          stream.close()          stream.close()
205    
206          self.__fecha_fichero = os.path.getmtime(archivo)          self.__fecha_fichero = os.path.getmtime(archivo)
207    
208          self.__iniciar_parseador(doc_xml)          self.__iniciar_parseador(doc_xml)
209    
210          self.__parsear_sala(doc_xml)          self.__parsear_sala(doc_xml)
211          self.__parsear_id(doc_xml)                self.__parsear_id(doc_xml)      
212          self.__parsear_nombre(doc_xml)            self.__parsear_nombre(doc_xml)  
213          self.__parsear_descripcion(doc_xml)          self.__parsear_descripcion(doc_xml)
214          self.__parsear_salidas(doc_xml)          self.__parsear_salidas(doc_xml)
215          self.__parsear_propiedades(doc_xml)          self.__parsear_propiedades(doc_xml)
216          self.__parsear_objetos(doc_xml)          self.__parsear_objetos(doc_xml)
217          self.__parsear_encuentros(doc_xml)          self.__parsear_encuentros(doc_xml)
218    
219                    
220      def __iniciar_parseador(self, doc_xml):      def __iniciar_parseador(self, doc_xml):
221          """Esta función borra todos los nodos de tipo Text de un          """Esta función borra todos los nodos de tipo Text de un
222          elemento DOM"""          elemento DOM"""
223                    
224          for nodo in doc_xml.childNodes[:]:          for nodo in doc_xml.childNodes[:]:
225              if not 'Element:' in str(nodo).split():              if not 'Element:' in str(nodo).split():
226                  doc_xml.childNodes.remove(nodo)                  doc_xml.childNodes.remove(nodo)
227    
228                    
229      def __parsear_sala(self, doc_xml):      def __parsear_sala(self, doc_xml):
230          """Extrae la información del elemento sala:          """Extrae la información del elemento sala:
231              area: el área a la que pertenece la sala              area: el área a la que pertenece la sala
232              autor: el autor de la sala              autor: el autor de la sala
233              version: la versión del tipo de sala"""              version: la versión del tipo de sala"""
234          version_desc_sala = doc_xml.attributes["version"].value.encode('ISO-8859-1')          version_desc_sala = doc_xml.attributes["version"].value.encode('ISO-8859-1')
235    
236          if version_desc_sala != Sala.VERSION_DESC_SALA:          if version_desc_sala != Sala.VERSION_DESC_SALA:
237              raise ValueError("Version incorrecta del fichero descriptor de sala " + self.id + ": " +              raise ValueError("Version incorrecta del fichero descriptor de sala " + self.id + ": " +
238                               version_desc_sala + " cuando se esperaba " + Sala.VERSION_DESC_SALA)                               version_desc_sala + " cuando se esperaba " + Sala.VERSION_DESC_SALA)
239    
240          self.version = Sala.VERSION_SALA          self.version = Sala.VERSION_SALA
241                    
242          self.autor = doc_xml.attributes["autor"].value.encode('ISO-8859-1')          self.autor = doc_xml.attributes["autor"].value.encode('ISO-8859-1')
243          self.area = doc_xml.attributes["area"].value.encode('ISO-8859-1')          self.area = doc_xml.attributes["area"].value.encode('ISO-8859-1')
244          try:          try:
245              self.comentario = doc_xml.attributes["comentario"].value.encode('ISO-8859-1')              self.comentario = doc_xml.attributes["comentario"].value.encode('ISO-8859-1')
246          except:          except:
247              self.comentario = ""              self.comentario = ""
248                    
249    
250      def __parsear_id(self, doc_xml):      def __parsear_id(self, doc_xml):
251          """Extrae el id de la sala"""          """Extrae el id de la sala"""
252          id_fichero = doc_xml.childNodes[0].childNodes[0].data.encode('ISO-8859-1')          id_fichero = doc_xml.childNodes[0].childNodes[0].data.encode('ISO-8859-1')
253          if id_fichero != self.id:          if id_fichero != self.id:
254              raise ValueError("El id no coincide con el nombre del fichero")              raise ValueError("El id no coincide con el nombre del fichero")
255                    
256    
257      def __parsear_nombre(self, doc_xml):      def __parsear_nombre(self, doc_xml):
258          """Extrae el nombre de la sala"""          """Extrae el nombre de la sala"""
259          self.nombre = doc_xml.childNodes[1].childNodes[0].data.encode('ISO-8859-1')          self.nombre = doc_xml.childNodes[1].childNodes[0].data.encode('ISO-8859-1')
260    
261    
262      def __parsear_propiedades(self, doc_xml):        def __parsear_propiedades(self, doc_xml):  
263          """Extrae las propiedades globales de la sala."""          """Extrae las propiedades globales de la sala."""
264          try:          try:
265              self.aura = int(doc_xml.childNodes[4].attributes["aura"].value)              self.aura = int(doc_xml.childNodes[4].attributes["aura"].value)
266          except:          except:
267              self.aura = 50              self.aura = 50
268          try:          try:
269              self.tipo = doc_xml.childNodes[4].attributes["tipo"].value              self.tipo = doc_xml.childNodes[4].attributes["tipo"].value
270          except:          except:
271              self.tipo = 'sin_tipo'              self.tipo = 'sin_tipo'
272          self.volumen = float(doc_xml.childNodes[4].attributes["volumen"].value)          self.volumen = float(doc_xml.childNodes[4].attributes["volumen"].value)
273          self.luz = int(doc_xml.childNodes[4].attributes["luz"].value)          self.luz = int(doc_xml.childNodes[4].attributes["luz"].value)
274          try:          try:
275              self.combate = doc_xml.childNodes[4].attributes["combate"].value              self.combate = doc_xml.childNodes[4].attributes["combate"].value
276          except:          except:
277              self.combate = 'si'              self.combate = 'si'
278          try:          try:
279              self.subtipo =  doc_xml.childNodes[4].attributes["subtipo"].value              self.subtipo =  doc_xml.childNodes[4].attributes["subtipo"].value
280          except:          except:
281              self.subtipo = 'sin_subtipo'              self.subtipo = 'sin_subtipo'
282          self.ocultabilidad = int(doc_xml.childNodes[4].attributes["ocultabilidad"].value)          self.ocultabilidad = int(doc_xml.childNodes[4].attributes["ocultabilidad"].value)
283                    
284    
285      def __parsear_descripcion(self, doc_xml):      def __parsear_descripcion(self, doc_xml):
286          """Extrae el texto y la dificultad asociada de los items de descripcion de la sala"""          """Extrae el texto y la dificultad asociada de los items de descripcion de la sala"""
287                    
288          nodo_descripcion = doc_xml.childNodes[2]          nodo_descripcion = doc_xml.childNodes[2]
289    
290          # Limpiamos todos los subnodos de tipo Text, al igual          # Limpiamos todos los subnodos de tipo Text, al igual
291          # que hacíamos en la función __iniciar_parseador()          # que hacíamos en la función __iniciar_parseador()
292          for nodo in nodo_descripcion.childNodes[:]:          for nodo in nodo_descripcion.childNodes[:]:
293              if not 'Element:' in str(nodo).split():              if not 'Element:' in str(nodo).split():
294                  doc_xml.childNodes[2].childNodes.remove(nodo)                  doc_xml.childNodes[2].childNodes.remove(nodo)
295                    
296          self.descripcion = []          self.descripcion = []
297    
298          for nodo_item in nodo_descripcion.childNodes[:]:          for nodo_item in nodo_descripcion.childNodes[:]:
299    
300              texto_item = ""              texto_item = ""
301              for nodo_parrafo in nodo_item.childNodes[:]:              for nodo_parrafo in nodo_item.childNodes[:]:
302                  texto_item += nodo_parrafo.data.encode('ISO-8859-1')                  texto_item += nodo_parrafo.data.encode('ISO-8859-1')
303                            
304              texto_item = " ".join(texto_item.split())              texto_item = " ".join(texto_item.split())
305    
306              if len(nodo_item._attrs) == 0:              if len(nodo_item._attrs) == 0:
307                  dif_item = 0                  dif_item = 0
308              else:              else:
309                  dif_item = int(nodo_item._attrs.get('dificultad').value)                  dif_item = int(nodo_item._attrs.get('dificultad').value)
310                                    
311              self.descripcion.append({"dificultad": dif_item, "texto": texto_item})              self.descripcion.append({"dificultad": dif_item, "texto": texto_item})
312    
313    
314      def __parsear_decorativos(self, doc_xml):      def __parsear_decorativos(self, doc_xml):
315          """Extrae el texto y la dificultad asociada de los items decorativos de la sala"""          """Extrae el texto y la dificultad asociada de los items decorativos de la sala"""
316                    
317          nodo_decorativos = doc_xml.childNodes[3]          nodo_decorativos = doc_xml.childNodes[3]
318    
319          # Limpiamos todos los subnodos de tipo Text, al igual          # Limpiamos todos los subnodos de tipo Text, al igual
320          # que hacíamos en la función __iniciar_parseador()          # que hacíamos en la función __iniciar_parseador()
321          for nodo in nodo_decorativos.childNodes[:]:          for nodo in nodo_decorativos.childNodes[:]:
322              if not 'Element:' in str(nodo).split():              if not 'Element:' in str(nodo).split():
323                  doc_xml.childNodes[2].childNodes.remove(nodo)                  doc_xml.childNodes[2].childNodes.remove(nodo)
324                    
325          self.decorativos = []          self.decorativos = []
326    
327          for nodo_item in nodo_decorativos.childNodes[:]:          for nodo_item in nodo_decorativos.childNodes[:]:
328    
329              nombre_item = nodo_item._attrs.get('nombre').value.encode('ISO-8859-1')              nombre_item = nodo_item._attrs.get('nombre').value.encode('ISO-8859-1')
330              texto_item = nodo_item._attrs.get('texto').value.encode('ISO-8859-1')              texto_item = nodo_item._attrs.get('texto').value.encode('ISO-8859-1')
331    
332              if len(nodo_item._attrs) == 1:              if len(nodo_item._attrs) == 1:
333                  dif_item = 0                  dif_item = 0
334              else:              else:
335                  dif_item = int(nodo_item._attrs.get('dificultad').value)                  dif_item = int(nodo_item._attrs.get('dificultad').value)
336                                    
337              self.decorativos.append({"nombre": nombre_item, "dificultad": dif_item, "texto": texto_item})              self.decorativos.append({"nombre": nombre_item, "dificultad": dif_item, "texto": texto_item})
338    
339        
340      def __parsear_salidas(self, doc_xml):            def __parsear_salidas(self, doc_xml):      
341          """Extrae toda la información de las salidas de la sala."""          """Extrae toda la información de las salidas de la sala."""
342                    
343          nodo_salidas = doc_xml.childNodes[3]          nodo_salidas = doc_xml.childNodes[3]
344                    
345          # Limpiamos todos los subnodos de tipo Text, al igual          # Limpiamos todos los subnodos de tipo Text, al igual
346          # que hacíamos en la función __iniciar_parseador()          # que hacíamos en la función __iniciar_parseador()
347          for nodo in nodo_salidas.childNodes[:]:          for nodo in nodo_salidas.childNodes[:]:
348              if not 'Element:' in str(nodo).split():              if not 'Element:' in str(nodo).split():
349                  nodo_salidas.childNodes.remove(nodo)                  nodo_salidas.childNodes.remove(nodo)
350    
351          self.salidas = []          self.salidas = []
352    
353          for nodo_salida in nodo_salidas.childNodes[:]:          for nodo_salida in nodo_salidas.childNodes[:]:
354                            
355              direccion_salida = nodo_salida.nodeName.encode('ISO-8859-1')  # oeste, este, norte, etc.              direccion_salida = nodo_salida.nodeName.encode('ISO-8859-1')  # oeste, este, norte, etc.
356              try:              try:
357                  dif_salida = int(nodo_salida._attrs.get('dificultad').value.encode('ISO-8859-1'))                  dif_salida = int(nodo_salida._attrs.get('dificultad').value.encode('ISO-8859-1'))
358              except:              except:
359                  dif_salida = 0                  dif_salida = 0
360              try:              try:
361                  tipo_cierre_salida = nodo_salida._attrs.get('tipo_cierre').value.encode('ISO-8859-1')                  tipo_cierre_salida = nodo_salida._attrs.get('tipo_cierre').value.encode('ISO-8859-1')
362              except:              except:
363                  tipo_cierre_salida = "ninguno"                  tipo_cierre_salida = "ninguno"
364              try:              try:
365                  datos_cierre_salida = nodo_salida._attrs.get('datos_cierre').value.encode('ISO-8859-1')                  datos_cierre_salida = nodo_salida._attrs.get('datos_cierre').value.encode('ISO-8859-1')
366              except:              except:
367                  datos_cierre_salida = ""                  datos_cierre_salida = ""
368              try:              try:
369                  mensaje_cerrado_salida = nodo_salida._attrs.get('mensaje_cerrado').value.encode('ISO-8859-1')                  mensaje_cerrado_salida = nodo_salida._attrs.get('mensaje_cerrado').value.encode('ISO-8859-1')
370              except:              except:
371                  mensaje_cerrado_salida = "Algo te impide pasar"                  mensaje_cerrado_salida = "Algo te impide pasar"
372                                    
373              id_salida = nodo_salida._attrs.get('id').value.encode('ISO-8859-1')              id_salida = nodo_salida._attrs.get('id').value.encode('ISO-8859-1')
374              desc_salida = nodo_salida.childNodes[0].data.encode('ISO-8859-1')              desc_salida = nodo_salida.childNodes[0].data.encode('ISO-8859-1')
375    
376              self.salidas.append({"direccion": direccion_salida,              self.salidas.append({"direccion": direccion_salida,
377                                   "dificultad": dif_salida,                                   "dificultad": dif_salida,
378                                   "id": id_salida,                                   "id": id_salida,
379                                   "descripcion": desc_salida,                                   "descripcion": desc_salida,
380                                   "tipo_cierre": tipo_cierre_salida,                                   "tipo_cierre": tipo_cierre_salida,
381                                   "datos_cierre": datos_cierre_salida,                                   "datos_cierre": datos_cierre_salida,
382                                   "mensaje_cerrado": mensaje_cerrado_salida})                                   "mensaje_cerrado": mensaje_cerrado_salida})
383    
384  #                                 "horario": horario_salida,  #                                 "horario": horario_salida,
385  #                                 "error": error_salida})  #                                 "error": error_salida})
386    
387      def __parsear_objetos(self, doc_xml):      def __parsear_objetos(self, doc_xml):
388          """Extrae toda la información de los objetos que hay en la sala inicialmente."""          """Extrae toda la información de los objetos que hay en la sala inicialmente."""
389    
390          nodo_objetos = doc_xml.childNodes[5]          nodo_objetos = doc_xml.childNodes[5]
391    
392          # Limpiamos todos los subnodos de tipo Text, al igual          # Limpiamos todos los subnodos de tipo Text, al igual
393          # que hacíamos en la función __iniciar_parseador()          # que hacíamos en la función __iniciar_parseador()
394          for nodo in nodo_objetos.childNodes[:]:          for nodo in nodo_objetos.childNodes[:]:
395              if  'Element:' not in str(nodo).split():              if  'Element:' not in str(nodo).split():
396                  nodo_objetos.childNodes.remove(nodo)                  nodo_objetos.childNodes.remove(nodo)
397    
398          self.objetos = []          self.objetos = []
399    
400          for nodo_objeto in nodo_objetos.childNodes[:]:          for nodo_objeto in nodo_objetos.childNodes[:]:
401    
402              id_objeto = nodo_objeto._attrs.get('id').value.encode('ISO-8859-1')              id_objeto = nodo_objeto._attrs.get('id').value.encode('ISO-8859-1')
403              try:              try:
404                  cantidad_objeto = int(nodo_objeto._attrs.get('cantidad').value)                  cantidad_objeto = int(nodo_objeto._attrs.get('cantidad').value)
405              except:              except:
406                  cantidad_objeto = 1                  cantidad_objeto = 1
407              try:              try:
408                  max_objeto = int(nodo_objeto._attrs.get('maximo').value)                  max_objeto = int(nodo_objeto._attrs.get('maximo').value)
409              except:              except:
410                  max_objeto = cantidad_objeto                  max_objeto = cantidad_objeto
411              try:              try:
412                  prob_objeto = int(nodo_objeto._attrs.get('probabilidad').value)                  prob_objeto = int(nodo_objeto._attrs.get('probabilidad').value)
413              except:              except:
414                  prob_objeto = 0                  prob_objeto = 0
415              try:              try:
416                  dif_objeto = int(nodo_objeto._attrs.get('dificultad').value)                  dif_objeto = int(nodo_objeto._attrs.get('dificultad').value)
417              except:              except:
418                  dif_objeto = 0                  dif_objeto = 0
419              desc_objeto = nodo_objeto.childNodes[0].data.encode('ISO-8859-1')              desc_objeto = nodo_objeto.childNodes[0].data.encode('ISO-8859-1')
420    
421              instancias = []              instancias = []
422              for i in range(cantidad_objeto):              for i in range(cantidad_objeto):
423                      instancias.append(Objeto(id_objeto))                      instancias.append(Objeto(id_objeto))
424    
425              self.objetos.append({"id": id_objeto,              self.objetos.append({"id": id_objeto,
426                                   "probabilidad": prob_objeto,                                   "probabilidad": prob_objeto,
427                                   "maximo": max_objeto,                                   "maximo": max_objeto,
428                                   "dificultad": dif_objeto,                                   "dificultad": dif_objeto,
429                                   "instancias": instancias})                                   "instancias": instancias})
430                    
431    
432      def __parsear_encuentros(self, doc_xml):      def __parsear_encuentros(self, doc_xml):
433          """Extrae toda la información de los PNJs que hay en la sala inicialmente."""          """Extrae toda la información de los PNJs que hay en la sala inicialmente."""
434                    
435          nodo_encuentros = doc_xml.childNodes[6]          nodo_encuentros = doc_xml.childNodes[6]
436    
437          # Limpiamos todos los subnodos de tipo Text, al igual          # Limpiamos todos los subnodos de tipo Text, al igual
438          # que hacíamos en la función __iniciar_parseador()          # que hacíamos en la función __iniciar_parseador()
439          for nodo in doc_xml.childNodes[6].childNodes[:]:          for nodo in doc_xml.childNodes[6].childNodes[:]:
440              if 'Element:' not in str(nodo).split(): doc_xml.childNodes[6].childNodes.remove(nodo)              if 'Element:' not in str(nodo).split(): doc_xml.childNodes[6].childNodes.remove(nodo)
441    
442          self.encuentros=[]          self.encuentros=[]
443    
444          for nodo_encuentro in nodo_encuentros.childNodes[:]:          for nodo_encuentro in nodo_encuentros.childNodes[:]:
445              id_encuentro = nodo_encuentro._attrs.get('id').value.encode('ISO-8859-1')              id_encuentro = nodo_encuentro._attrs.get('id').value.encode('ISO-8859-1')
446              try:              try:
447                  cant_encuentro = int(nodo_encuentro._attrs.get('cantidad').value)                  cant_encuentro = int(nodo_encuentro._attrs.get('cantidad').value)
448              except:              except:
449                  cant_encuentro = 1                  cant_encuentro = 1
450              try:              try:
451                  max_encuentro = int(nodo_encuentro._attrs.get('maximo').value)                  max_encuentro = int(nodo_encuentro._attrs.get('maximo').value)
452              except:              except:
453                  max_encuentro = 0                  max_encuentro = 0
454              try:              try:
455                  prob_encuentro = int(nodo_encuentro._attrs.get('probabilidad'))                  prob_encuentro = int(nodo_encuentro._attrs.get('probabilidad'))
456              except:              except:
457                  prob_encuentro = 0                  prob_encuentro = 0
458              try:              try:
459                  dif_encuentro = int(nodo_encuentro._attrs.get('dificultad').value)                  dif_encuentro = int(nodo_encuentro._attrs.get('dificultad').value)
460              except:              except:
461                  dif_encuentro = 0                  dif_encuentro = 0
462              desc_encuentro = nodo_encuentro.childNodes[0].data.encode('ISO-8859-1')              desc_encuentro = nodo_encuentro.childNodes[0].data.encode('ISO-8859-1')
463                            
464              self.encuentros.append({"id": id_encuentro,              self.encuentros.append({"id": id_encuentro,
465                                      "maximo": max_encuentro,                                      "maximo": max_encuentro,
466                                      "probabilidad": prob_encuentro,                                      "probabilidad": prob_encuentro,
467                                      "dificultad": dif_encuentro,                                      "dificultad": dif_encuentro,
468                                      "descripcion": desc_encuentro})                                      "descripcion": desc_encuentro})
469    
470              escribir("Vamos a crear " + str(cant_encuentro) + " pnjs")              escribir("Vamos a crear " + str(cant_encuentro) + " pnjs")
471              for i in range(cant_encuentro):              for i in range(cant_encuentro):
472                  id_unico = id_encuentro + '%' + PersonajeNoJugador_nuevo_id()                  id_unico = id_encuentro + '%' + PersonajeNoJugador_nuevo_id()
473                  escribir("Vamos a crear a " + id_unico)                  escribir("Vamos a crear a " + id_unico)
474                  self.personajes[id_unico] = PersonajeNoJugador(id_unico, self)                  self.personajes[id_unico] = PersonajeNoJugador(id_unico, self)
475    
476    
477      def activar(self):      def activar(self):
478          """Realiza algunos chequeos periodicos siempre que alguien          """Realiza algunos chequeos periodicos siempre que alguien
479          necesita esta sala.          necesita esta sala.
480          """          """
481          from mundo import Mundo          from mundo import Mundo
482    
483          if self.id != Mundo.ID_SALA_LIMBO:          if self.id != Mundo.ID_SALA_LIMBO:
484              # Todos los personajes no controlados deben estar siempre en el limbo,              # Todos los personajes no controlados deben estar siempre en el limbo,
485              # pero es posible que por algún fallo quede alguno suelto por ahí.              # pero es posible que por algún fallo quede alguno suelto por ahí.
486              # Si se da el caso, lo movemos al limbo.              # Si se da el caso, lo movemos al limbo.
487              for personaje in self.personajes.values()[:]:              for personaje in self.personajes.values()[:]:
488                  if personaje.controlador == None:                  if personaje.controlador == None:
489                      escribir("OJO: restaurado pj " + personaje.id + " en sala " + self.id +                      escribir("OJO: restaurado pj " + personaje.id + " en sala " + self.id +
490                               ". Moviendolo al limbo...")                               ". Moviendolo al limbo...")
491                      personaje.liberar()                      personaje.liberar()
492          else:          else:
493              # En el limbo, todos los personajes deben tener la sala original              # En el limbo, todos los personajes deben tener la sala original
494              # a donde devolverlos a la vuelta. Puede que por algún error, haya              # a donde devolverlos a la vuelta. Puede que por algún error, haya
495              # alguno con eso mal. Si es así, lo enviamos a la entrada.              # alguno con eso mal. Si es así, lo enviamos a la entrada.
496              for personaje in self.personajes.values()[:]:              for personaje in self.personajes.values()[:]:
497                  if not hasattr(personaje, "id_sala_original") or \                  if not hasattr(personaje, "id_sala_original") or \
498                     personaje.id_sala_original == Mundo.ID_SALA_LIMBO:                     personaje.id_sala_original == Mundo.ID_SALA_LIMBO:
499                      escribir("OJO: personaje " + personaje.id + " en el limbo ha perdido " +                      escribir("OJO: personaje " + personaje.id + " en el limbo ha perdido " +
500                               "la sala original. Lo mandaremos a la entrada...")                               "la sala original. Lo mandaremos a la entrada...")
501                      personaje.id_sala_original = Mundo.ID_SALA_ENTRADA                      personaje.id_sala_original = Mundo.ID_SALA_ENTRADA
502    
503    
504          archivo = os.path.join(Sala.DIR_DESC_SALAS, self.id.split('-')[0], self.id + Sala.EXT_DESC_SALAS)          archivo = os.path.join(Sala.DIR_DESC_SALAS, self.id.split('-')[0], self.id + Sala.EXT_DESC_SALAS)
505          if self.__fecha_fichero < os.path.getmtime(archivo):          if self.__fecha_fichero < os.path.getmtime(archivo):
506              # Si se modifica el fichero descriptor, recargarlo de nuevo              # Si se modifica el fichero descriptor, recargarlo de nuevo
507              # pero conservando la lista de personajes y los objetos *que no              # pero conservando la lista de personajes y los objetos *que no
508              # sean nativos* de la sala.              # sean nativos* de la sala.
509              escribir("Recargando sala " + self.id + " desde el fichero de descripcion")              escribir("Recargando sala " + self.id + " desde el fichero de descripcion")
510    
511              objetos_guardados = self.objetos              objetos_guardados = self.objetos
512              personajes_guardados = self.personajes              personajes_guardados = self.personajes
513              n_jugadores_guardado = self.n_jugadores              n_jugadores_guardado = self.n_jugadores
514    
515              self.__inicializar_sala()              self.__inicializar_sala()
516    
517              self.personajes = personajes_guardados              self.personajes = personajes_guardados
518              self.n_jugadores = n_jugadores_guardado              self.n_jugadores = n_jugadores_guardado
519              for objeto_guardado in objetos_guardados:              for objeto_guardado in objetos_guardados:
520                  og = ( objeto_guardado["id"], objeto_guardado["probabilidad"] )                  og = ( objeto_guardado["id"], objeto_guardado["probabilidad"] )
521                  if og not in [ (o["id"], o["probabilidad"]) for o in self.objetos ]:                  if og not in [ (o["id"], o["probabilidad"]) for o in self.objetos ]:
522                      self.objetos.append(objeto_guardado)                      self.objetos.append(objeto_guardado)
523    
524    
525      def entrar_personaje(self, personaje):      def entrar_personaje(self, personaje):
526          """Método llamado cuando un personaje entra en la sala.          """Método llamado cuando un personaje entra en la sala.
527                    
528            Requiere:            Requiere:
529              personaje != None              personaje != None
530              personaje not in self.personajes.values()              personaje not in self.personajes.values()
531              personaje.sala == self              personaje.sala == self
532              self.volumen_ocupado() + personaje.volumen_total() <= self.volumen              self.volumen_ocupado() + personaje.volumen_total() <= self.volumen
533    
534            Asegura:            Asegura:
535              personaje in self.personajes.values()              personaje in self.personajes.values()
536            """            """
537    
538          # Actualizar la lista          # Actualizar la lista
539          self.personajes[personaje.id] = personaje          self.personajes[personaje.id] = personaje
540                    
541          # Actualizar el contador de PJs          # Actualizar el contador de PJs
542          from personajejugador import PersonajeJugador          from personajejugador import PersonajeJugador
543          if isinstance(personaje, PersonajeJugador):          if isinstance(personaje, PersonajeJugador):
544              self.n_jugadores += 1              self.n_jugadores += 1
545    
546          # Ver si aparecen o desaparecen objetos          # Ver si aparecen o desaparecen objetos
547          for objeto in self.objetos:          for objeto in self.objetos:
548              if objeto["probabilidad"] > 0:              if objeto["probabilidad"] > 0:
549                  if tirar_porcentaje() <= objeto["probabilidad"]:                  if tirar_porcentaje() <= objeto["probabilidad"]:
550                      if tirar_porcentaje() <= 50:                      if tirar_porcentaje() <= 50:
551                          if len(objeto["instancias"]) > 0:                          if len(objeto["instancias"]) > 0:
552                              del objeto["instancias"][0]                              del objeto["instancias"][0]
553                      else:                      else:
554                          if (objeto["maximo"] == 0 or                          if (objeto["maximo"] == 0 or
555                              len(objeto["instancias"]) < objeto["maximo"]):                              len(objeto["instancias"]) < objeto["maximo"]):
556                              objeto["instancias"].append(Objeto(objeto["id"]))                              objeto["instancias"].append(Objeto(objeto["id"]))
557    
558                            
559      def salir_personaje(self, personaje):      def salir_personaje(self, personaje):
560          """Método llamado cuando un personaje sale de la sala.          """Método llamado cuando un personaje sale de la sala.
561                    
562          Requiere:          Requiere:
563            personaje != None            personaje != None
564            personaje in self.personajes.values()            personaje in self.personajes.values()
565    
566          Asegura:          Asegura:
567            personaje not in self.personajes.values()            personaje not in self.personajes.values()
568          """          """
569                    
570          #print "TRAZA-> Sala[" + self.id + "].salir_personaje(" + personaje.id + ")"          #print "TRAZA-> Sala[" + self.id + "].salir_personaje(" + personaje.id + ")"
571                    
572          # Actualizar la lista          # Actualizar la lista
573          del self.personajes[personaje.id]          del self.personajes[personaje.id]
574            
575          # Actualizar el contador de PJs          # Actualizar el contador de PJs
576          from personajejugador import PersonajeJugador          from personajejugador import PersonajeJugador
577          if isinstance(personaje, PersonajeJugador):          if isinstance(personaje, PersonajeJugador):
578              self.n_jugadores -= 1              self.n_jugadores -= 1
579    
580    
581      def volumen_ocupado(self):      def volumen_ocupado(self):
582          """El total de volumen que ocupa toda la gente y objetos que hay dentro.          """El total de volumen que ocupa toda la gente y objetos que hay dentro.
583          Asegura:          Asegura:
584            return > 0.0            return > 0.0
585            return <= self.volumen            return <= self.volumen
586          """          """
587          ocupado = 0.0          ocupado = 0.0
588          for personaje in self.personajes.values():          for personaje in self.personajes.values():
589              ocupado += personaje.volumen_total()              ocupado += personaje.volumen_total()
590    
591          for objeto in self.objetos:          for objeto in self.objetos:
592              for instancia in objeto["instancias"]:              for instancia in objeto["instancias"]:
593                  ocupado += instancia.volumen()                  ocupado += instancia.volumen()
594    
595          return ocupado          return ocupado
596    
597    
598      def coger_objeto(self, n_objeto, n_instancia):      def coger_objeto(self, n_objeto, n_instancia):
599          """Sacar una instancia de un objeto de la sala.          """Sacar una instancia de un objeto de la sala.
600    
601          n_objeto es el numero de orden dentro de los objetos de la sala, y n_instancia          n_objeto es el numero de orden dentro de los objetos de la sala, y n_instancia
602          es el numero de la instancia, ambos empezando por cero.          es el numero de la instancia, ambos empezando por cero.
603    
604          Devuelve una instancia de clase Objeto.          Devuelve una instancia de clase Objeto.
605    
606          Requiere:          Requiere:
607              n_objeto in range(0, len(self.objetos)-1)              n_objeto in range(0, len(self.objetos)-1)
608              n_instancia in range(0, len(self.objetos[n_objeto]["instancias"])-1)              n_instancia in range(0, len(self.objetos[n_objeto]["instancias"])-1)
609    
610          Asegura:          Asegura:
611              return != None              return != None
612          """          """
613          objeto = self.objetos[n_objeto]          objeto = self.objetos[n_objeto]
614    
615          instancia = objeto["instancias"][n_instancia]          instancia = objeto["instancias"][n_instancia]
616    
617          del objeto["instancias"][n_instancia]          del objeto["instancias"][n_instancia]
618          if len(objeto["instancias"]) == 0 and objeto["probabilidad"] == 0:          if len(objeto["instancias"]) == 0 and objeto["probabilidad"] == 0:
619              del self.objetos[n_objeto]              del self.objetos[n_objeto]
620    
621          instancia.activar()          instancia.activar()
622    
623          return instancia          return instancia
624    
625    
626      def dejar_objeto(self, instancia, dificultad = 0):      def dejar_objeto(self, instancia, dificultad = 0):
627          """Soltar un objeto en la sala.          """Soltar un objeto en la sala.
628    
629          instancia es de clase Objeto. Si ya habia mas instancias con el mismo id en la sala,          instancia es de clase Objeto. Si ya habia mas instancias con el mismo id en la sala,
630          se añade a la lista, y si no, se crea un item nuevo en self.objetos.          se añade a la lista, y si no, se crea un item nuevo en self.objetos.
631    
632          Requiere:          Requiere:
633              instancia != None              instancia != None
634              dificultad in range(0, 100)              dificultad in range(0, 100)
635          """          """
636          encontrado = 0          encontrado = 0
637                    
638          for objeto in self.objetos:          for objeto in self.objetos:
639              if objeto["id"] == instancia.id():              if objeto["id"] == instancia.id():
640                  encontrado = 1                  encontrado = 1
641                  objeto["instancias"].append(instancia)                  objeto["instancias"].append(instancia)
642                  break                  break
643    
644          if not encontrado:          if not encontrado:
645              self.objetos.append({"id":instancia.id(),              self.objetos.append({"id":instancia.id(),
646                                   "probabilidad":0,                                   "probabilidad":0,
647                                   "maximo":0,                                   "maximo":0,
648                                   "dificultad":dificultad,                                   "dificultad":dificultad,
649                                   "instancias":[instancia]})                                   "instancias":[instancia]})
650    
651    
652      def salida_cerrada(self, id_sala_destino):      def salida_cerrada(self, id_sala_destino):
653          """Comprueba si la salida indicada, y si lo está devuelve el id de la llave,          """Comprueba si la salida indicada, y si lo está devuelve el id de la llave,
654          y el mensaje a mostrar si no se puede entrar.          y el mensaje a mostrar si no se puede entrar.
655    
656          Requiere:          Requiere:
657              id_sala_destino apunta a una salida que existe en la sala.              id_sala_destino apunta a una salida que existe en la sala.
658    
659          Devuelve:          Devuelve:
660              una tupla (id_llave, mensaje_error). La id_llave vale None si la puerta está              una tupla (id_llave, mensaje_error). La id_llave vale None si la puerta está
661              abierta, y "" si no se puede abrir.              abierta, y "" si no se puede abrir.
662          """          """
663          for salida in self.salidas:          for salida in self.salidas:
664              if salida["id"] == id_sala_destino:              if salida["id"] == id_sala_destino:
665    
666                  tipo_cierre = salida["tipo_cierre"]                  tipo_cierre = salida["tipo_cierre"]
667                  if tipo_cierre == "ninguno":                  if tipo_cierre == "ninguno":
668    
669                      return (None, "")                      return (None, "")
670    
671                  elif tipo_cierre == "cerradura":                  elif tipo_cierre == "cerradura":
672    
673                      return (salida["datos_cierre"], salida["mensaje_cerrado"])                      return (salida["datos_cierre"], salida["mensaje_cerrado"])
674    
675                  elif tipo_cierre == "magia":                  elif tipo_cierre == "magia":
676    
677                      return ("", salida["mensaje_cerrado"])                      return ("", salida["mensaje_cerrado"])
678    
679                  elif tipo_cierre == "horario":                  elif tipo_cierre == "horario":
680    
681                      # Vamos a procesar el argumento horario, que está en la forma                      # Vamos a procesar el argumento horario, que está en la forma
682                      # "horaini-horafin,horaini-horafin,... idllave"                      # "horaini-horafin,horaini-horafin,... idllave"
683    
684                      # Primero, separar el id de la llave                      # Primero, separar el id de la llave
685                      aux = salida["datos_cierre"].split(" ")                      aux = salida["datos_cierre"].split(" ")
686                      rangos = aux[0].split(",")                      rangos = aux[0].split(",")
687                      if len(aux) > 1:                      if len(aux) > 1:
688                          id_llave = aux[1]                          id_llave = aux[1]
689                      else:                      else:
690                          id_llave = ""                          id_llave = ""
691    
692                      # Luego, ver si la hora actual está dentro de alguno de los rangos                      # Luego, ver si la hora actual está dentro de alguno de los rangos
693                      abierto = 0                      abierto = 0
694                      ahora = FechaHoraMine_ahora()                      ahora = FechaHoraMine_ahora()
695                      for rango in rangos:                      for rango in rangos:
696                          aux = rango.split("-")                          aux = rango.split("-")
697                          hora_ini = int(aux[0])                          hora_ini = int(aux[0])
698                          hora_fin = int(aux[1])                          hora_fin = int(aux[1])
699                          if ahora.hora() >= hora_ini and ahora.hora() < hora_fin:                          if ahora.hora() >= hora_ini and ahora.hora() < hora_fin:
700                              abierto = 1                              abierto = 1
701                              break                              break
702    
703                      if abierto:                      if abierto:
704                          return (None, "")                          return (None, "")
705                      else:                      else:
706                          return (id_llave, salida["mensaje_cerrado"])                          return (id_llave, salida["mensaje_cerrado"])
707    
708    
709      def salvar(self):      def salvar(self):
710          """Graba en un fichero de salas la sala con todo su contenido."""          """Graba en un fichero de salas la sala con todo su contenido."""
711                    
712          #print "TRAZA-> Sala[" + self.id + "].salvar()"          #print "TRAZA-> Sala[" + self.id + "].salvar()"
713                    
714          fichero = open(os.path.join(Sala.DIR_SALAS, self.id + Sala.EXT_SALAS), 'w')          fichero = open(os.path.join(Sala.DIR_SALAS, self.id + Sala.EXT_SALAS), 'w')
715          cPickle.dump(self, fichero)          cPickle.dump(self, fichero)
716          fichero.close()          fichero.close()
717    
718    
719      def __setstate__(self, atributos):      def __setstate__(self, atributos):
720          """Método llamado para restaurar los atributos provinientes de un          """Método llamado para restaurar los atributos provinientes de un
721          pickle."""          pickle."""
722    
723          self.__dict__ = atributos          self.__dict__ = atributos
724    
725          # Verificar la versión.          # Verificar la versión.
726          if not self.__dict__.has_key("version"):          if not self.__dict__.has_key("version"):
727              raise ValueError("Cargada sala " + self.id + " obsoleta: sin versión" +              raise ValueError("Cargada sala " + self.id + " obsoleta: sin versión" +
728                               " cuando se esperaba " + Sala.VERSION_SALA)                               " cuando se esperaba " + Sala.VERSION_SALA)
729    
730          assert(Sala.VERSION_SALA == "1.2")          assert(Sala.VERSION_SALA == "1.2")
731          while self.version != "1.2":          while self.version != "1.2":
732                                                                        
733              if self.version == "1.0":              if self.version == "1.0":
734                  # Versión 1.0 -> 1.1: añadir fecha de modificacion de archivo de descripcion                  # Versión 1.0 -> 1.1: añadir fecha de modificacion de archivo de descripcion
735                  archivo = os.path.join(Sala.DIR_DESC_SALAS, self.id + Sala.EXT_DESC_SALAS)                  archivo = os.path.join(Sala.DIR_DESC_SALAS, self.id + Sala.EXT_DESC_SALAS)
736                  self.__fecha_fichero = os.path.getmtime(archivo)                  self.__fecha_fichero = os.path.getmtime(archivo)
737                  self.version = "1.1"                  self.version = "1.1"
738                  escribir("Convertida sala " + self.id + " a versión 1.1")                  escribir("Convertida sala " + self.id + " a versión 1.1")
739              elif self.version == "1.1":              elif self.version == "1.1":
740                  # Versión 1.1 -> 1.2: cambiar horario y error por tipo_cierre, datos_cierre                  # Versión 1.1 -> 1.2: cambiar horario y error por tipo_cierre, datos_cierre
741                  #                     y mensaje_cerrado                  #                     y mensaje_cerrado
742                  for salida in self.salidas:                  for salida in self.salidas:
743                      horario = salida["horario"]                      horario = salida["horario"]
744                      error = salida["error"]                      error = salida["error"]
745                      del salida["horario"]                      del salida["horario"]
746                      del salida["error"]                      del salida["error"]
747                      if horario == "0-24":                      if horario == "0-24":
748                          salida["tipo_cierre"] = "ninguno"                          salida["tipo_cierre"] = "ninguno"
749                          salida["datos_cierre"] = ""                          salida["datos_cierre"] = ""
750                          salida["mensaje_cerrado"] = ""                          salida["mensaje_cerrado"] = ""
751                      else:                      else:
752                          salida["tipo_cierre"] = "horario"                          salida["tipo_cierre"] = "horario"
753                          salida["datos_cierre"] = horario                          salida["datos_cierre"] = horario
754                          salida["mensaje_cerrado"] = mensaje_cerrado                          salida["mensaje_cerrado"] = mensaje_cerrado
755                  self.version = "1.2"                  self.version = "1.2"
756                  escribir("Convertida sala " + self.id + " a versión 1.2")                  escribir("Convertida sala " + self.id + " a versión 1.2")
757              else:              else:
758                  raise ValueError("Cargada sala " + self.id + " con versión desconocida: " +                  raise ValueError("Cargada sala " + self.id + " con versión desconocida: " +
759                                   self.version + " cuando se esperaba " + Sala.VERSION_SALA)                                   self.version + " cuando se esperaba " + Sala.VERSION_SALA)
760    
761                    
762  # Métodos que se refieren a la clase pero tienen ámbito de clase,  # Métodos que se refieren a la clase pero tienen ámbito de clase,
763  # y no de instancia  # y no de instancia
764    
765    
766  def Sala_cargar(id):  def Sala_cargar(id):
767      """Recupera una sala desde un fichero de salas.      """Recupera una sala desde un fichero de salas.
768    
769      Requiere:      Requiere:
770        id != None        id != None
771        id corresponde con un fichero existente        id corresponde con un fichero existente
772    
773      Asegura:      Asegura:
774        return != None        return != None
775      """      """
776                    
777      #print "TRAZA-> Sala.cargar(" + id + ")"      #print "TRAZA-> Sala.cargar(" + id + ")"
778            
779      fichero = open(os.path.join(Sala.DIR_SALAS, id + Sala.EXT_SALAS), 'r')      fichero = open(os.path.join(Sala.DIR_SALAS, id + Sala.EXT_SALAS), 'r')
780      sala = cPickle.load(fichero)      sala = cPickle.load(fichero)
781      fichero.close()      fichero.close()
782            
783      return sala      return sala
784    
785    
786  # Código para pruebas unitarias del módulo.  # Código para pruebas unitarias del módulo.
787    
788  if (__name__ == '__main__'):  if (__name__ == '__main__'):
789      print "No hay prueba unitaria de módulo. prueba con salatester.py"      print "No hay prueba unitaria de módulo. prueba con salatester.py"

Legend:
Removed from v.2.1  
changed lines
  Added in v.2.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26