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

Diff of /ambar/interfazpnjhablante.py

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

revision 2.7 by TuringTest, Sun Aug 24 23:34:41 2003 UTC revision 2.8 by TuringTest, Fri Sep 5 21:26:01 2003 UTC
# Line 25  Line 25 
25  from interfazpnj import *  from interfazpnj import *
26  from mundo import *  from mundo import *
27  from modulo import *  from modulo import *
28    from guiontemporizado import GuionTemporizado
29  from xml.dom import minidom  from xml.dom import minidom
30  import copy  import copy
31  from cronomine import CronoMine  from cronomine import CronoMine
# Line 63  class InterfazPNJHablante(InterfazPNJ): Line 64  class InterfazPNJHablante(InterfazPNJ):
64          len(_fragmentos) >= 0          len(_fragmentos) >= 0
65          self.visita[i].activo  <--> len(self._fragmentos) > 0          self.visita[i].activo  <--> len(self._fragmentos) > 0
66       """       """
67        
68      VERSION_DESC_CONVERSACIONES = '2.0.0'      VERSION_DESC_CONVERSACIONES = '2.0.0'
69        
70            
71      DIR_DESC_CONVERSACIONES = 'conversaciones'      DIR_DESC_CONVERSACIONES = 'conversaciones'
72      DIR_DESC_GENERICAS = 'generico'      DIR_DESC_GENERICAS = 'generico'
# Line 74  class InterfazPNJHablante(InterfazPNJ): Line 75  class InterfazPNJHablante(InterfazPNJ):
75            
76      TEMAS_ESPECIALES = [ 'iniciativa_propia', 'tema_agotado', 'tema_no_encontrado', 'fuera_de_tema' ]      TEMAS_ESPECIALES = [ 'iniciativa_propia', 'tema_agotado', 'tema_no_encontrado', 'fuera_de_tema' ]
77            
78        
79        #Constructor
80        
81      def __init__(self, id_conversacion):      def __init__(self, id_conversacion):
82          InterfazPNJ.__init__(self)          InterfazPNJ.__init__(self)
83                    trazar("Probando la funcion trazar()")
84          escribir("Cargando el pnj hablante " + id_conversacion)          escribir("Cargando el pnj hablante " + id_conversacion)
85          #Control de iniciativa          #Control de iniciativa
86          self.__temporizador = None          self.__temporizador = None      # Controla la siguiente activación de la iniciativa
87          self.__interlocutor = None          self.__interlocutor = None      # Último personaje con el que habló
88          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
89          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
90                    
91          self.id_conversacion = id_conversacion          self.id_conversacion = id_conversacion
92          self.__guion_activo = None          self.__guion_activo = None      # Guion del diálogo que está en marcha
93            self.__contextos = ['default']
94            self.__historia = {}
95                    
96          self.__temas = {}          self.__temas = {}
97          self.__temas_especiales = {}          self.__temas_especiales = {}
# Line 98  class InterfazPNJHablante(InterfazPNJ): Line 103  class InterfazPNJHablante(InterfazPNJ):
103                  else:                  else:
104                     trazar("Inicializado el tema " + tema, "pnj")                     trazar("Inicializado el tema " + tema, "pnj")
105                                    
     def __ruta_conversacion(self, id_conversacion=None):  
         if not id_conversacion: id_conversacion = self.id_conversacion  
         return os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_CONVERSACIONES)  
       
     def __ruta_especial(self, id_conversacion=None):  
         if not id_conversacion: id_conversacion = self.id_conversacion  
         return os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_ESPECIALES)  
                   
106      def __setattr__(self, name, value):      def __setattr__(self, name, value):
107          """Realiza ajustes autom�ticos al modificar cualquier par�metro"""          """Realiza ajustes autom�ticos al modificar cualquier par�metro"""
108        
109          if name == "personaje":          if name == "personaje":
110              # Si es personaje, liberar al anterior y controlar al nuevo.              # Si es personaje, liberar al anterior y controlar al nuevo.
111              if (self.personaje != None): self.personaje.controlador = None              if (self.personaje != None): self.personaje.controlador = None
# Line 120  class InterfazPNJHablante(InterfazPNJ): Line 117  class InterfazPNJHablante(InterfazPNJ):
117              # En otro caso, asignar y ya esta              # En otro caso, asignar y ya esta
118              self.__dict__[name] = value              self.__dict__[name] = value
119                    
120      # Mé�todos privados      # Métodos privados
121        
122        
123        # Localizar y cargar temas en la caché
124        
125        def __ruta_conversacion(self, id_conversacion=None):
126            if not id_conversacion: id_conversacion = self.id_conversacion
127            return os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_CONVERSACIONES)
128        
129        def __ruta_especial(self, id_conversacion=None):
130            if not id_conversacion: id_conversacion = self.id_conversacion
131            return os.path.join(Modulo.DIR_DESC_MODULOS, id_conversacion, InterfazPNJHablante.DIR_DESC_ESPECIALES)
132                    
133        
134      def __encuentra_tema(self, nombretema, ruta = None):      def __encuentra_tema(self, nombretema, ruta = None):
135          """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."""
136                    
137          tema = self.__temas.get(nombretema, None)          tema = self.__temas.get(nombretema, None)
138          if tema: return tema          if tema: return tema
139        
140          if not ruta: ruta = self.__ruta_conversacion()          if not ruta: ruta = self.__ruta_conversacion()
141          try:          try:
142              self.__temas[nombretema] = self.__cargar_modulo(nombretema)              self.__temas[nombretema] = self.__cargar_modulo(nombretema)
# Line 142  class InterfazPNJHablante(InterfazPNJ): Line 151  class InterfazPNJHablante(InterfazPNJ):
151          tema = self.__temas_especiales.get(nombretema, None)          tema = self.__temas_especiales.get(nombretema, None)
152          if tema:          if tema:
153                  return tema                  return tema
154        
155          if not ruta: ruta = self.__ruta_especial()          if not ruta: ruta = self.__ruta_especial()
156          try:          try:
157              self.__temas_especiales[nombretema] = self.__cargar_modulo(nombretema, ruta)              self.__temas_especiales[nombretema] = self.__cargar_modulo(nombretema, ruta)
# Line 176  class InterfazPNJHablante(InterfazPNJ): Line 185  class InterfazPNJHablante(InterfazPNJ):
185          macros = [ ("$interlocutor", "Personaje"),          macros = [ ("$interlocutor", "Personaje"),
186                     ("$pnj", "Personaje"),                     ("$pnj", "Personaje"),
187                     ("$sala", "Sala")]#,                     ("$sala", "Sala")]#,
188  #                  ("$tema", "Modulo") ]          #                  ("$tema", "Modulo") ]
189                                                            
190                                                                                                                    
191          macros_extra = {}          macros_extra = {}
192          return Modulo(elem_desc_modulo, macros, macros_extra)          return Modulo(elem_desc_modulo, macros, macros_extra)
# Line 186  class InterfazPNJHablante(InterfazPNJ): Line 196  class InterfazPNJHablante(InterfazPNJ):
196          else:          else:
197                  self.__temas_especiales[id_modulo] = Modulo(elem_desc_modulo, macros, macros_extra)                  self.__temas_especiales[id_modulo] = Modulo(elem_desc_modulo, macros, macros_extra)
198          return          return
199        
200        # Controlar la iniciativa del PNJ
201      def __fallar(self, nombretema, macros):      
             tema = self.__temas_especiales[nombretema]  
             guion_equivocado = tema.mejor_guion()  
             if not guion_equivocado:  
                 tema = self.__encuentra_tema_generico(nombretema)  
                 guion_equivocado = tema.mejor_guion()  
                 if not guion_equivocado:  
                     raise Exception("Error en modulo de conversacion: no quedan guiones activos en el tema por defecto.")  
             guion_equivocado.ejecutar(macros)  
             self.__reanudar_iniciativa()  
           
   
202      def __temporizar_nueva_iniciativa(self):      def __temporizar_nueva_iniciativa(self):
203          """Establece el tiempo necesario para activar la iniciativa"""          """Establece el tiempo necesario para activar la iniciativa"""
204          from mundo import Mundo                  from mundo import Mundo        
# Line 229  class InterfazPNJHablante(InterfazPNJ): Line 228  class InterfazPNJHablante(InterfazPNJ):
228                  self.__temporizador.reanudar()                  self.__temporizador.reanudar()
229              except:              except:
230                  escribir("Error inesperado al reanudar la iniciativa")                  escribir("Error inesperado al reanudar la iniciativa")
231        
232      def __disparar_iniciativa(self):      def __disparar_iniciativa(self):
233          """Activa el modulo de iniciativa propia de la conversacion"""          """Activa el modulo de iniciativa propia de la conversacion"""
234          trazar("Activando iniciativa del pnj", "pnj")          trazar("Activando iniciativa del pnj", "pnj")
# Line 238  class InterfazPNJHablante(InterfazPNJ): Line 237  class InterfazPNJHablante(InterfazPNJ):
237                  macros = { "$interlocutor": self.__interlocutor,                  macros = { "$interlocutor": self.__interlocutor,
238                             "$pnj": self.__personaje,                             "$pnj": self.__personaje,
239                             "$sala": self.__personaje.sala }                             "$sala": self.__personaje.sala }
240                  iniciativa.ejecutar(macros)                  guion = iniciativa.mejor_guion(self.__contextos)
241                    if guion:
242                        self.__interlocutor = self.__personaje
243                        self.__activar_guion(guion, macros)
244                  self.__temporizador = None                  self.__temporizador = None
245                  self.__temporizar_nueva_iniciativa()                  self.__temporizar_nueva_iniciativa()
246          else:          else:
247                  self.__temporizador = None                  self.__temporizador = None
248                                    
249        # Controlar la temporización del diálogo activo
250        
251        def __fallar(self, nombretema, macros):
252            """Encuentra una respuesta correcta cuando el PJ ha preguntado por un tema no válido."""
253            guion_equivocado = None
254            if self.__temas_especiales.has_key(nombretema):
255                tema = self.__temas_especiales[nombretema]
256                guion_equivocado = tema.mejor_guion(self.__contextos)
257            if not guion_equivocado:
258                tema = self.__encuentra_tema_generico(nombretema)
259                guion_equivocado = tema.mejor_guion(self.__contextos)
260                if not guion_equivocado:
261                    raise Exception("Error en modulo de conversacion: no quedan guiones activos en el tema por defecto.")
262            self.__activar_guion(guion_equivocado, macros)
263            self.__reanudar_iniciativa()
264        
265        def __activar_guion(self, guion, macros):
266            """Comienza la temporización del guion encontrado"""
267            self.__guion_activo = guion     # Recordar: es un wrapper, "not the Real Thing"
268            self.__contextos = guion.contextos
269            for contexto in guion.contextos:
270                if not self.__historia.has_key(contexto):
271                    self.__historia[contexto] = 0
272                else:
273                    self.__historia[contexto] += 1
274                trazar(str(contexto) + str(self.__historia[contexto]) + " veces", "pnj", 3)
275            guion.ejecutar(macros, finalizar=(lambda guion, cancelado: self.__finalizar_guion(cancelado)))
276            
277        def __finalizar_guion(self, cancelado=0):
278            """Callback que usa el guion activo cuando termina o es cancelado"""
279            if self.esta_hablando():
280                    trazar("Finalizando la conversacion", "pnj")
281                    self.__guion_activo.cancelar_secuencia()
282            self.__guion_activo = None
283                    
284      # -------------------------------------------------      # -------------------------------------------------
285      # Metodos publicos      # Metodos publicos
286      # -------------------------------------------------      # -------------------------------------------------
287            
288        def esta_hablando(self):
289            return self.__guion_activo != None
290        
291      def conversa_personaje(self, personaje, comando, nombretema):      def conversa_personaje(self, personaje, comando, nombretema):
292          """Metodo llamado cuando otro personaje habla con este PNJ"""          """Metodo llamado cuando otro personaje habla con este PNJ
293            
294            Devuelve false cuando el PNJ está hablando con otro personaje y no se les puede interrumpir
295            """
296            
297            if self.esta_hablando() and self.__interlocutor:
298                #Interrumpiendo una conversacion en curso
299                trazar("Esta hablando con " + repr(self.__interlocutor.nombre), "pnj", 2)
300                if self.__interlocutor == personaje:
301                    self.__finalizar_guion()
302                elif personaje.competicion(self.__interlocutor, "carisma", "carisma", malus=6):
303                    #Si el nuevo interlocutor gana la competicion de carisma, distrae al PNJ y cancela la conversacion anterior
304                    trazar("Cancelando una conversacion por una nueva pregunta que interrumpe la anterior", "pnj")
305                    self.__finalizar_guion()
306                else:
307                    return 0
308                    
309  #       LOGICA PARA CANCELAR +HABLAR CUANDO HABLA CON OTRO PNJ DE MAYOR CARISMA          #       LOGICA PARA CANCELAR +HABLAR CUANDO HABLA CON OTRO PNJ DE MAYOR CARISMA        
310  #       if visita.activo:  #       if visita.activo:
# Line 272  class InterfazPNJHablante(InterfazPNJ): Line 326  class InterfazPNJHablante(InterfazPNJ):
326                  self.__fallar("tema_no_encontrado", macros)                  self.__fallar("tema_no_encontrado", macros)
327          else:          else:
328              tema = self.__temas[nombretema]              tema = self.__temas[nombretema]
329              guion = tema.mejor_guion()              guion = tema.mejor_guion(self.__contextos)
330              if guion:              if guion:
331                  # Nueva conversacion con exito                  # Nueva conversacion con exito
332                  guion.ejecutar(macros)                  self.__activar_guion(guion, macros)
333                  self.__reanudar_iniciativa()                  self.__reanudar_iniciativa()
334                  self.__temporizar_nueva_iniciativa()                  self.__temporizar_nueva_iniciativa()
335              else:              else:
# Line 285  class InterfazPNJHablante(InterfazPNJ): Line 339  class InterfazPNJHablante(InterfazPNJ):
339          trazar("Ejecutado el tema " + nombretema, "pnj")          trazar("Ejecutado el tema " + nombretema, "pnj")
340          #self._modulo.ejecutar(None)          #self._modulo.ejecutar(None)
341                    
342          return          return 1
       
         visita = self._visitas[0]  
         if visita.activo:  
            if visita.pj_activo.atrib["carisma"] > personaje.atrib["carisma"]  : #visita.pj_activo.aura > personaje.controlador._DialogoNormal__personaje.aura:  
                 personaje.controlador.conn().send(visita.pnj.nombre +" est� hablando con " + visita.pj_activo.nombre)  
                 return  
            else:  
                self.anular_conversacion()  
         respuesta = visita.responder(personaje, comando, nombretema.lower())  
         escribir("Tema " + visita.estado())  
         #print respuesta[len(respuesta)-1]  
         if visita.estado() == Visita.ENCONTRADO or visita.estado() == Visita.OFFTOPIC:  
            visita.activar(respuesta)  
           
         nombre = visita.pnj.nombre[0].lower() + visita.pnj.nombre[1:]  
         if comando == "decir":  
             visita.pj_activo.actuar("dice a " + nombre + " algo acerca de '" + nombretema + "'")          
             personaje.controlador.conn().send("Dices a " + nombre + " algo sobre '" + nombretema + "'")  
         else:  
             visita.pj_activo.actuar("pregunta a " + nombre + " acerca de '" + nombretema + "'")  
             personaje.controlador.conn().send("Preguntas a " + nombre + " sobre '" + nombretema + "'")  
343                    
344                                                                                                            
345        def anular_conversacion(self):
346            self._fragmentos = []
347            self._visitas[0].activo = None
348            for crono in self.cronos:
349              # Anula los cronos que no se han ejecutado a�n, asignandoles la funci�n nula
350                crono.vencimiento_func = lambda x: None
351        
352        
353      def controlar_personaje(self, personaje):      def controlar_personaje(self, personaje):
354          """Pasar a estar controlando un personaje.          """Pasar a estar controlando un personaje.
355                    
# Line 317  class InterfazPNJHablante(InterfazPNJ): Line 358  class InterfazPNJHablante(InterfazPNJ):
358            personaje != None            personaje != None
359          """          """
360          self.__personaje = personaje          self.__personaje = personaje
   
361                    
   
     def anular_conversacion(self):  
         self._fragmentos = []  
         self._visitas[0].activo = None  
         for crono in self.cronos:  
           # Anula los cronos que no se han ejecutado a�n, asignandoles la funci�n nula  
             crono.vencimiento_func = lambda x: None  
   
                   
362      # -------------------------------------------------      # -------------------------------------------------
363      # Metodos de manejo de eventos (ver controlador.py)      # Metodos de manejo de eventos (ver controlador.py)
364      # -------------------------------------------------      # -------------------------------------------------
# Line 338  class InterfazPNJHablante(InterfazPNJ): Line 369  class InterfazPNJHablante(InterfazPNJ):
369          if not self.__temporizador:          if not self.__temporizador:
370              self.__temporizar_nueva_iniciativa()              self.__temporizar_nueva_iniciativa()
371                    
372        
373      def sale_personaje(self, personaje, nombre_sala_destino):      def sale_personaje(self, personaje, nombre_sala_destino):
374          """Si no quedan personajes, desactiva el temporizador de iniciativa"""          """Si no quedan personajes, desactiva el temporizador de iniciativa"""
375                    
376          if personaje == self.__interlocutor:          if personaje == self.__interlocutor:
377                    trazar("Cancelando la conversacion por abandono del interlocutor", "pnj")
378                  self.__interlocutor = None                  self.__interlocutor = None
379                  if self.__guion_activo:                  self.__finalizar_guion()
                         trazar("Cancelando la conversacion por abandono del interlocutor", "pnj")  
                         self.__guion_activo.cancelar()  
380                    
381          pjs = [ personaje for personaje in self.__personaje.sala.personajes.values() \          pjs = [ personaje for personaje in self.__personaje.sala.personajes.values() \
382                                           if isinstance(personaje.controlador, InterfazPNJHablante) ]                                           if not isinstance(personaje.controlador, InterfazPNJHablante) ]
383          trazar("Quedan %s personajes jugadores en la sala" % len(pjs), "pnj", 2)          trazar("Quedan %s personajes jugadores en la sala" % len(pjs), "pnj", 2)
384          if len(pjs) == 1:          if len(pjs) == 0:
385                  trazar("Desactivando la iniciativa del pnj", "pnj", 2)                  trazar("Desactivando la iniciativa del pnj", "pnj", 2)
386                  if self.__temporizador:                  if self.__temporizador:
387                      try:                                      try:                
# Line 364  class InterfazPNJHablante(InterfazPNJ): Line 394  class InterfazPNJHablante(InterfazPNJ):
394      def habla_personaje(self, personaje, mensaje):      def habla_personaje(self, personaje, mensaje):
395          """ El PNJ intenta entender las conversaciones entre PJs """          """ El PNJ intenta entender las conversaciones entre PJs """
396          pass          pass
397          # 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
398          for palabra in mensaje.split():          for palabra in mensaje.split():
399                  if palabra in self.__keywords:                  if palabra in self.__keywords:
400                          self.__reaccionar(palabra)                          self.__reaccionar(palabra) # To Do: implementar el metodo __reaccionar
401    
402    
403    

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

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