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

Diff of /ambar/interfazpnjhablante.py

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

revision 2.6 by TuringTest, Tue Aug 19 22:46:26 2003 UTC revision 2.7 by TuringTest, Sun Aug 24 23:34:41 2003 UTC
# Line 41  class InterfazPNJHablante(InterfazPNJ): Line 41  class InterfazPNJHablante(InterfazPNJ):
41            
42      Contiene los siguientes atributos:      Contiene los siguientes atributos:
43            
44       - __ruta_conversacion (path): la conversacion que es capaz de mantener el PNJ       - __id_conversacion: nombre de la conversacion que es capaz de mantener el PNJ
45       - __personaje (Personaje): el personaje que controlamos       - __personaje (Personaje): el personaje que controlamos
46       - estado (string): el estado en el que se encuentra el interfaz       - estado (string): el estado en el que se encuentra el interfaz
47       - sub_estado (int): algunos estados tienen fases intermedias. Si no, None.       - sub_estado (int): algunos estados tienen fases intermedias. Si no, None.
# Line 54  class InterfazPNJHablante(InterfazPNJ): Line 54  class InterfazPNJHablante(InterfazPNJ):
54    
55       - personaje: se modifica tambi�n al personaje para que tenga a este interfaz como       - personaje: se modifica tambi�n al personaje para que tenga a este interfaz como
56                    controlador                    controlador
57                                        
58       Invariantes:       Invariantes:
59          _conversacion != None          _conversacion != None
60          __personaje != None          __personaje != None
61          len(_visitas) >= 0          len(_visitas) >= 0
62          len(cronos) >= 0          len(cronos) >= 0
63          len(_fragmentos) >= 0          len(_fragmentos) >= 0
64          self.visita[i].activo  <--> len(self._fragmentos) > 0          self.visita[i].activo  <--> len(self._fragmentos) > 0
65       """       """
66    
67      VERSION_DESC_CONVERSACIONES = '2.0.0'      VERSION_DESC_CONVERSACIONES = '2.0.0'
68    
69            
70      DIR_DESC_CONVERSACIONES = 'conversaciones'      DIR_DESC_CONVERSACIONES = 'conversaciones'
71        DIR_DESC_GENERICAS = 'generico'
72      DIR_DESC_ESPECIALES = 'modulos_especiales'      DIR_DESC_ESPECIALES = 'modulos_especiales'
73      EXT_DESC_CONVERSACIONES = '.xml'      EXT_DESC_CONVERSACIONES = '.xml'
74            
# Line 82  class InterfazPNJHablante(InterfazPNJ): Line 83  class InterfazPNJHablante(InterfazPNJ):
83          self.__temporizador = None          self.__temporizador = None
84          self.__interlocutor = None          self.__interlocutor = None
85          self.__velocidad = 0.05 # TO DO: parametrizar la velocidad de reaccion del PNJ          self.__velocidad = 0.05 # TO DO: parametrizar la velocidad de reaccion del PNJ
86          self.__keywords = [] # TO DO: añadir una lista de keywords que el PNJ "entiende" en el diálogo entre PJs          self.__keywords = [] # TO DO: añadir una lista de keywords que el PNJ "entiende" en el diálogo entre PJs
87                    
88          self.__ruta_conversacion = os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_CONVERSACIONES)          self.id_conversacion = id_conversacion
89          self.__ruta_especiales = os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_ESPECIALES)          self.__guion_activo = None
         self.__guion_activo = None  
90                    
91          self.__temas = {}          self.__temas = {}
92          self.__temas_especiales = {}          self.__temas_especiales = {}
93          for tema in InterfazPNJHablante.TEMAS_ESPECIALES:          self.__temas_genericos = {}
94                  if not self.__encuentra_tema_especial(tema):          
95                     trazar("No esta definido el tema especial de tipo " + tema, "pnj")          for tema in InterfazPNJHablante.TEMAS_ESPECIALES:
96                  else:                  if not self.__encuentra_tema_especial(tema):
97                     trazar("Inicializado el tema " + tema, "pnj")                     trazar("No esta definido el tema especial de tipo " + tema, "pnj")
98                                    else:
99                       trazar("Inicializado el tema " + tema, "pnj")
100                    
101        def __ruta_conversacion(self, id_conversacion=None):
102            if not id_conversacion: id_conversacion = self.id_conversacion
103            return os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_CONVERSACIONES)
104        
105        def __ruta_especial(self, id_conversacion=None):
106            if not id_conversacion: id_conversacion = self.id_conversacion
107            return os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_ESPECIALES)
108                    
109      def __setattr__(self, name, value):      def __setattr__(self, name, value):
110          """Realiza ajustes autom�ticos al modificar cualquier par�metro"""          """Realiza ajustes autom�ticos al modificar cualquier par�metro"""
111    
# Line 110  class InterfazPNJHablante(InterfazPNJ): Line 119  class InterfazPNJHablante(InterfazPNJ):
119          else:          else:
120              # En otro caso, asignar y ya esta              # En otro caso, asignar y ya esta
121              self.__dict__[name] = value              self.__dict__[name] = value
122                    
123      # Mé�todos privados      # Mé�todos privados
124    
125      def __encuentra_tema(self, nombretema, ruta = None):      def __encuentra_tema(self, nombretema, ruta = None):
126          """Localiza un tema por su nombre. Si es necesario lo carga desde disco a la cache de temas."""          """Localiza un tema por su nombre. Si es necesario lo carga desde disco a la cache de temas."""
127                    
128          tema = self.__temas.get(nombretema, None)          tema = self.__temas.get(nombretema, None)
129          if tema: return tema          if tema: return tema
130    
131          if not ruta: ruta = self.__ruta_conversacion          if not ruta: ruta = self.__ruta_conversacion()
132          try:          try:
133                  self.__cargar_modulo(nombretema)              self.__temas[nombretema] = self.__cargar_modulo(nombretema)
134          except IOError:          except IOError:
135              return None              return None
136                    
137          return self.__temas.get(nombretema, None)          return self.__temas.get(nombretema, None)
138            
139      def __encuentra_tema_especial(self, nombretema, ruta = None):      def __encuentra_tema_especial(self, nombretema, ruta = None):
140          """Localiza un tema por su nombre. Si es necesario lo carga desde disco a la cache de temas."""          """Localiza un tema por su nombre. Si es necesario lo carga desde disco a la cache de temas."""
141                    
142          tema = self.__temas_especiales.get(nombretema, None)          tema = self.__temas_especiales.get(nombretema, None)
143          if tema:          if tema:
144                  return tema                  return tema
145    
146          if not ruta: ruta = self.__ruta_especiales          if not ruta: ruta = self.__ruta_especial()
147          try:          try:
148                  self.__cargar_modulo(nombretema, ruta, especial=1)              self.__temas_especiales[nombretema] = self.__cargar_modulo(nombretema, ruta)
149            except IOError:
150                return None
151            
152            return self.__temas_especiales.get(nombretema, None)
153        
154        def __encuentra_tema_generico(self, nombretema, ruta = None):
155            """Localiza un tema por su nombre. Si es necesario lo carga desde disco a la cache de temas."""
156            
157            tema = self.__temas_genericos.get(nombretema, None)
158            if tema:
159                    return tema
160            
161            if not ruta: ruta = self.__ruta_especial(InterfazPNJHablante.DIR_DESC_GENERICAS)
162            try:
163                self.__temas_genericos[nombretema] = self.__cargar_modulo(nombretema, ruta)
164          except IOError:          except IOError:
165              return None              return None
166                    
167          return self.__temas.get(nombretema, None)          return self.__temas_genericos.get(nombretema, None)
168            
169                    
170      def __cargar_modulo(self, id_modulo, ruta=None, especial=0):      def __cargar_modulo(self, id_modulo, ruta=None):
171          #archivo = os.path.join(Modulo.DIR_DESC_MODULOS, "prueba" + Modulo.EXT_DESC_MODULOS)          #archivo = os.path.join(Modulo.DIR_DESC_MODULOS, "prueba" + Modulo.EXT_DESC_MODULOS)
172          if not ruta: ruta = self.__ruta_conversacion          if not ruta: ruta = self.__ruta_conversacion()
173          archivo = os.path.join(ruta, id_modulo + InterfazPNJHablante.EXT_DESC_CONVERSACIONES)          archivo = os.path.join(ruta, id_modulo + InterfazPNJHablante.EXT_DESC_CONVERSACIONES)
174          arbol_xml = minidom.parse(archivo)          arbol_xml = minidom.parse(archivo)
175          elem_desc_modulo = arbol_xml.documentElement          elem_desc_modulo = arbol_xml.documentElement
176          macros = [ ("$interlocutor", "Personaje"),          macros = [ ("$interlocutor", "Personaje"),
177                     ("$tutora", "Personaje"),                     ("$pnj", "Personaje"),
178                     ("$sala", "Sala")]#,                     ("$sala", "Sala")]#,
179  #                  ("$tema", "Modulo") ]  #                  ("$tema", "Modulo") ]
180                                                                                                                    
181          macros_extra = {}          macros_extra = {}
182          if not especial:          return Modulo(elem_desc_modulo, macros, macros_extra)
183                  self.__temas[id_modulo] = Modulo(elem_desc_modulo, macros, macros_extra)          
184          else:          if not especial:
185                  self.__temas_especiales[id_modulo] = Modulo(elem_desc_modulo, macros, macros_extra)                  self.__temas[id_modulo] = Modulo(elem_desc_modulo, macros, macros_extra)
186            else:
187                    self.__temas_especiales[id_modulo] = Modulo(elem_desc_modulo, macros, macros_extra)
188          return          return
189    
190    
191      def __fallar(self, tema, macros):      def __fallar(self, nombretema, macros):
192                tema = self.__temas_especiales[nombretema]
193              guion_equivocado = tema.mejor_guion()              guion_equivocado = tema.mejor_guion()
194              if not guion_equivocado: raise Exception("Error en modulo de conversacion: no quedan guiones activos en el tema por defecto.")              if not guion_equivocado:
195                    tema = self.__encuentra_tema_generico(nombretema)
196                    guion_equivocado = tema.mejor_guion()
197                    if not guion_equivocado:
198                        raise Exception("Error en modulo de conversacion: no quedan guiones activos en el tema por defecto.")
199              guion_equivocado.ejecutar(macros)              guion_equivocado.ejecutar(macros)
200              self.__reanudar_iniciativa()              self.__reanudar_iniciativa()
201                    
202    
203      def __temporizar_nueva_iniciativa(self):      def __temporizar_nueva_iniciativa(self):
204          """Establece el tiempo necesario para activar la iniciativa"""          """Establece el tiempo necesario para activar la iniciativa"""
205          from mundo import Mundo                  from mundo import Mundo        
206          try:          try:
207                  if self.__temporizador:                  if self.__temporizador:
208                          self.__temporizador.parar()                      self.__temporizador.parar()
209                  activacion = FechaHoraMineRel( segundos = (random() + 0.5) * self.__velocidad * FechaHoraMine.SEGUNDOS_POR_HORA )                  activacion = FechaHoraMineRel( segundos = (random() + 0.5) * self.__velocidad * FechaHoraMine.SEGUNDOS_POR_HORA )
210                  trazar("Activada iniciativa para dentro de %s horas Mine" % repr(activacion), "pnj", 2)                  trazar("Activada iniciativa para dentro de %s horas Mine" % repr(activacion), "pnj", 2)
211                  self.__temporizador = CronoMine(Mundo.cronoMine_control, activacion, lambda x: self.__disparar_iniciativa())                  self.__temporizador = CronoMine(Mundo.cronoMine_control, activacion, lambda x: self.__disparar_iniciativa())
212          except:          except:
213                  escribir("Error inesperado al temporizar la iniciativa")                  escribir("Error inesperado al temporizar la iniciativa")
214                                    
215                            
216      def __pausar_iniciativa(self):      def __pausar_iniciativa(self):
217          if self.__temporizador:          if self.__temporizador:
218              try:              try:
219                  trazar("Pausando la iniciativa del pnj", "pnj", 2)                  trazar("Pausando la iniciativa del pnj", "pnj", 2)
220                  # TO DO: comprobar que no se pausa repetidas veces.                  # TO DO: comprobar que no se pausa repetidas veces.
221                  self.__temporizador.pausar()                  self.__temporizador.pausar()
222              except:              except:
223                  escribir("Error inesperado al pausar la iniciativa")                  escribir("Error inesperado al pausar la iniciativa")
224            
225      def __reanudar_iniciativa(self):      def __reanudar_iniciativa(self):
226          if self.__temporizador:          if self.__temporizador:
227              try:              try:
228                  trazar("Reanudando la iniciativa del pnj", "pnj", 2)                  trazar("Reanudando la iniciativa del pnj", "pnj", 2)
229                  self.__temporizador.reanudar()                  self.__temporizador.reanudar()
230              except:              except:
231                  escribir("Error inesperado al reanudar la iniciativa")                  escribir("Error inesperado al reanudar la iniciativa")
232    
233      def __disparar_iniciativa(self):      def __disparar_iniciativa(self):
234          """Activa el modulo de iniciativa propia de la conversacion"""          """Activa el modulo de iniciativa propia de la conversacion"""
235          trazar("Activando iniciativa del pnj", "pnj")          trazar("Activando iniciativa del pnj", "pnj")
236          iniciativa = self.__encuentra_tema_especial("iniciativa_propia")          iniciativa = self.__encuentra_tema_especial("iniciativa_propia")
237          if iniciativa:          if iniciativa:
238                  macros = { "$interlocutor": self.__interlocutor,                  macros = { "$interlocutor": self.__interlocutor,
239                             "$tutora": self.__personaje,                             "$pnj": self.__personaje,
240                             "$sala": self.__personaje.sala }                             "$sala": self.__personaje.sala }
241                  iniciativa.ejecutar(macros)                  iniciativa.ejecutar(macros)
242                  self.__temporizador = None                  self.__temporizador = None
243                  self.__temporizar_nueva_iniciativa()                  self.__temporizar_nueva_iniciativa()
244          else:          else:
245                  self.__temporizador = None                  self.__temporizador = None
246                                    
247    
248      # -------------------------------------------------      # -------------------------------------------------
# Line 221  class InterfazPNJHablante(InterfazPNJ): Line 252  class InterfazPNJHablante(InterfazPNJ):
252      def conversa_personaje(self, personaje, comando, nombretema):      def conversa_personaje(self, personaje, comando, nombretema):
253          """Metodo llamado cuando otro personaje habla con este PNJ"""          """Metodo llamado cuando otro personaje habla con este PNJ"""
254                    
255    #       LOGICA PARA CANCELAR +HABLAR CUANDO HABLA CON OTRO PNJ DE MAYOR CARISMA        
256    #       if visita.activo:
257    #          if visita.pj_activo.atrib["carisma"] > personaje.atrib["carisma"]  : #visita.pj_activo.aura > personaje.controlador._DialogoNormal__personaje.aura:
258    #               personaje.controlador.conn().send(visita.pnj.nombre +" est� hablando con " + visita.pj_activo.nombre)
259    #               return
260    #          else:
261    #              self.anular_conversacion()
262            
263          self.__interlocutor = personaje          self.__interlocutor = personaje
264          self.__pausar_iniciativa()          self.__pausar_iniciativa()
265          macros = { "$interlocutor": personaje,          macros = { "$interlocutor": personaje,
266                     "$tutora": self.__personaje,                     "$pnj": self.__personaje,
267                     "$sala": personaje.sala }                     "$sala": personaje.sala }
268                    
269          if nombretema in InterfazPNJHablante.TEMAS_ESPECIALES or \          if nombretema in InterfazPNJHablante.TEMAS_ESPECIALES or \
270             not self.__encuentra_tema(nombretema):             not self.__encuentra_tema(nombretema):
271                  trazar("No existe el tema %s" % nombretema, "pnj")                  trazar("No existe el tema %s" % nombretema, "pnj")
272                  self.__fallar(self.__temas_especiales["tema_no_encontrado"], macros)                  self.__fallar("tema_no_encontrado", macros)
273          else:          else:
274              tema = self.__temas[nombretema]              tema = self.__temas[nombretema]
275              guion = tema.mejor_guion()              guion = tema.mejor_guion()
276              if guion:              if guion:
277                  # Nueva conversacion con exito                  # Nueva conversacion con exito
278                  guion.ejecutar(macros)                  guion.ejecutar(macros)
279                  self.__reanudar_iniciativa()                  self.__reanudar_iniciativa()
280                  self.__temporizar_nueva_iniciativa()                  self.__temporizar_nueva_iniciativa()
281              else:              else:
282                  trazar("El tema %s está agotado" % nombretema, "pnj")                  trazar("El tema %s está agotado" % nombretema, "pnj")
283                  self.__fallar(self.__temas_especiales["tema_agotado"], macros)                  self.__fallar("tema_agotado", macros)
284                    
285          trazar("Ejecutado el tema " + nombretema, "pnj")          trazar("Ejecutado el tema " + nombretema, "pnj")
286          #self._modulo.ejecutar(None)          #self._modulo.ejecutar(None)
287                    
288          return          return
289            
290          visita = self._visitas[0]          visita = self._visitas[0]
291          if visita.activo:          if visita.activo:
292             if visita.pj_activo.atrib["carisma"] > personaje.atrib["carisma"]  : #visita.pj_activo.aura > personaje.controlador._DialogoNormal__personaje.aura:             if visita.pj_activo.atrib["carisma"] > personaje.atrib["carisma"]  : #visita.pj_activo.aura > personaje.controlador._DialogoNormal__personaje.aura:
293                  personaje.controlador.conn().send(visita.pnj.nombre +" est� hablando con " + visita.pj_activo.nombre)                  personaje.controlador.conn().send(visita.pnj.nombre +" est� hablando con " + visita.pj_activo.nombre)
294                  return                  return
295             else:             else:
296                 self.anular_conversacion()                 self.anular_conversacion()
297          respuesta = visita.responder(personaje, comando, nombretema.lower())          respuesta = visita.responder(personaje, comando, nombretema.lower())
298          escribir("Tema " + visita.estado())          escribir("Tema " + visita.estado())
299          #print respuesta[len(respuesta)-1]          #print respuesta[len(respuesta)-1]
300          if visita.estado() == Visita.ENCONTRADO or visita.estado() == Visita.OFFTOPIC:          if visita.estado() == Visita.ENCONTRADO or visita.estado() == Visita.OFFTOPIC:
301             visita.activar(respuesta)             visita.activar(respuesta)
302                    
303          nombre = visita.pnj.nombre[0].lower() + visita.pnj.nombre[1:]          nombre = visita.pnj.nombre[0].lower() + visita.pnj.nombre[1:]
304          if comando == "decir":          if comando == "decir":
305              visita.pj_activo.actuar("dice a " + nombre + " algo acerca de '" + nombretema + "'")                      visita.pj_activo.actuar("dice a " + nombre + " algo acerca de '" + nombretema + "'")        
306              personaje.controlador.conn().send("Dices a " + nombre + " algo sobre '" + nombretema + "'")              personaje.controlador.conn().send("Dices a " + nombre + " algo sobre '" + nombretema + "'")
307          else:          else:
308              visita.pj_activo.actuar("pregunta a " + nombre + " acerca de '" + nombretema + "'")              visita.pj_activo.actuar("pregunta a " + nombre + " acerca de '" + nombretema + "'")
309              personaje.controlador.conn().send("Preguntas a " + nombre + " sobre '" + nombretema + "'")              personaje.controlador.conn().send("Preguntas a " + nombre + " sobre '" + nombretema + "'")
310                    
311                                                                                                            
312      def controlar_personaje(self, personaje):      def controlar_personaje(self, personaje):
313          """Pasar a estar controlando un personaje.          """Pasar a estar controlando un personaje.
314                    
315          Requiere:          Requiere:
316            self.__personaje == None            self.__personaje == None
317            personaje != None            personaje != None
318          """          """
319          self.__personaje = personaje          self.__personaje = personaje
320    
321                    
322    
323      def anular_conversacion(self):      def anular_conversacion(self):
324          self._fragmentos = []          self._fragmentos = []
325          self._visitas[0].activo = None          self._visitas[0].activo = None
326          for crono in self.cronos:          for crono in self.cronos:
327            # Anula los cronos que no se han ejecutado a�n, asignandoles la funci�n nula            # Anula los cronos que no se han ejecutado a�n, asignandoles la funci�n nula
328              crono.vencimiento_func = lambda x: None              crono.vencimiento_func = lambda x: None
329    
330                                    
# Line 304  class InterfazPNJHablante(InterfazPNJ): Line 343  class InterfazPNJHablante(InterfazPNJ):
343          """Si no quedan personajes, desactiva el temporizador de iniciativa"""          """Si no quedan personajes, desactiva el temporizador de iniciativa"""
344                    
345          if personaje == self.__interlocutor:          if personaje == self.__interlocutor:
346                  self.__interlocutor = None                  self.__interlocutor = None
347                  if self.__guion_activo:                  if self.__guion_activo:
348                          trazar("Cancelando la conversacion por abandono del interlocutor", "pnj")                          trazar("Cancelando la conversacion por abandono del interlocutor", "pnj")
349                          self.__guion_activo.cancelar()                          self.__guion_activo.cancelar()
350                    
351          pjs = [ personaje for personaje in self.__personaje.sala.personajes.values() \          pjs = [ personaje for personaje in self.__personaje.sala.personajes.values() \
352                                           if isinstance(personaje.controlador, InterfazPNJHablante) ]                                           if isinstance(personaje.controlador, InterfazPNJHablante) ]
353          trazar("Quedan %s personajes jugadores en la sala" % len(pjs), "pnj", 2)          trazar("Quedan %s personajes jugadores en la sala" % len(pjs), "pnj", 2)
354          if len(pjs) == 1:          if len(pjs) == 1:
355                  trazar("Desactivando la iniciativa del pnj", "pnj", 2)                  trazar("Desactivando la iniciativa del pnj", "pnj", 2)
356                  if self.__temporizador:                  if self.__temporizador:
357                      try:                                      try:                
358                          self.__temporizador.parar()                          self.__temporizador.parar()
359                          self.__temporizador = None                          self.__temporizador = None
360                      except:                      except:
361                          escribir("Error inesperado al pausar la iniciativa")                          escribir("Error inesperado al pausar la iniciativa")
362                                                    
363                                                    
364      def habla_personaje(self, personaje, mensaje):      def habla_personaje(self, personaje, mensaje):
# Line 327  class InterfazPNJHablante(InterfazPNJ): Line 366  class InterfazPNJHablante(InterfazPNJ):
366          pass          pass
367          # TO DO: añadir una lista de keywords que el PNJ "entiende" en el diálogo entre PJs          # TO DO: añadir una lista de keywords que el PNJ "entiende" en el diálogo entre PJs
368          for palabra in mensaje.split():          for palabra in mensaje.split():
369                  if palabra in self.__keywords:                  if palabra in self.__keywords:
370                          self.__reaccionar(palabra)                          self.__reaccionar(palabra)
371    
372    
373    

Legend:
Removed from v.2.6  
changed lines
  Added in v.2.7

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