def findShortestPath(from_input, to_input):
    prolog = Prolog()
    loadDatabase(prolog)
    prolog_query = "path(" + from_input + "," + to_input + ",PATH,COST)"
    shortest_path_result = list(prolog.query(prolog_query))
    path_list = []
    shortest_path_lst = shortest_path_result

    if len(shortest_path_lst) <= 0:
        return False

    for i in range(len(shortest_path_lst[0]['PATH'])):
        path_list.append(str(shortest_path_result[0]['PATH'][i]))

    train_query = "theTrainIs(" + str(path_list) + ",TRAIN)"
    train_result = list(prolog.query(train_query))

    train_list = []
    for i in range(len(train_result[0]['TRAIN'])):
        train_list.append(str(train_result[0]['TRAIN'][i]))

    path_type_list = []
    include_walk_query = "includeWalk(" + str(train_list) + ",PATH_TYPE)"
    include_walk_result = list(prolog.query(include_walk_query))
    for i in range(len(include_walk_result[0]['PATH_TYPE'])):
        path_type_list.append(str(include_walk_result[0]['PATH_TYPE'][i]))

    print("Train: " + str(train_list))
    print ""
    print("Train+Walk: " + str(path_type_list))
    print ""
    print("TrainLen: " + str(len(train_list)) + "->" +
          str(len(path_type_list)))

    return path_list, shortest_path_result[0]['COST']
Beispiel #2
0
def _query(pl=None, query=None, debug=False):
    if not query:
        return
    if not pl:
        pl = Prolog()
        pl.consult('init.pl')
    if isinstance(query[0], str):
        query = [query]
    query_list = []
    var_list = []
    for pred, args in query:
        arg_list = []
        for arg in args:
            if (isinstance(arg, str) and arg[:3] == '_v:'):
                # and arg[0] == arg[0].upper()
                var = arg[3:]
                var_list += [var]
                arg_list += [var]
            elif (isinstance(arg, str) and '^^' in arg):
                arg_list += [arg]
            elif (isinstance(arg, list)):
                arg_list += [f"{arg}"]
            else:
                arg_list += [f"'{arg}'"]
        arg_str = ','.join(arg_list)
        query_list += [pred + '(' + arg_str + ')']
    query_str = ','.join(query_list)
    if debug:
        print(query_str, end="\n\n")
    return var_list, pl.query(query_str)
Beispiel #3
0
 def __init__( self, director, dificuldade ):
     super( GameLayer, self ).__init__()
     
     self.director = director
     self.tabuleiro = []
     self.offsetX = director.get_window_size()[0]/3
     self.offsetY = director.get_window_size()[1]/8
     lado = 45
     self.lado = lado
     self.dificuldade = dificuldade
     
     self.cpu = False
     
     self.prolog = Prolog()
     self.prolog.consult("reversi.pl")
     self.tabMatriz = list(self.prolog.query("novotab(X)"))[0]['X']
     self.matriz = deepcopy(self.tabMatriz)
     
     pyglet.font.add_directory('.')
     self.jogadorAtivo = Label("Jogador: Player1", font_name = 'Blood Of Dracula', font_size = 22,
                              x = 20, y = 350)
     self.add(self.jogadorAtivo)
     self.dif = Label("Dificuldade: " + self.dificuldade, font_name = 'Blood Of Dracula', font_size = 16,
                              x = 20, y = 300)
     self.add(self.dif)
     self.p = list(self.prolog.query("winner(" + str(self.tabMatriz) + ", P0, P1, P2)"))[0]
     self.p1 = Label("P1: " + str(self.p['P1']) + self.dificuldade, font_name = 'Bloodsuckers', font_size = 26,
                              x = 20, y = 200)
     self.p2 = Label("P1: " + str(self.p['P2']) + self.dificuldade, font_name = 'Bloodsuckers', font_size = 26,
                              x = 20, y = 150)
     self.add(self.p1)
     self.add(self.p2)
     
     #Batch que vai segurar todos os pecas
     self.spriteBatch = BatchNode()
     self.add(self.spriteBatch)
     
     size = 8*self.lado
     for i in range(8):
         l = []
         for j in range(8):
             peca = Peca(self.tabMatriz[i][j], (j*lado + lado/2, size - (i*lado + lado/2)))
             l.append(peca)
             self.spriteBatch.add(peca)
         self.tabuleiro.append(l)
         
     self.spriteBatch.add(Sprite("tabuleiro.png", 
                                 (self.tabuleiro[4][4].position[0] - lado/2, self.tabuleiro[4][4].position[1] + lado/2) 
                                 , 0, 1, 32), 0)
     
     self.spriteBatch.position = (self.offsetX, self.offsetY)
     self.spriteBatch.scale = 1.0        
     
     self.hud = GameHud()
     self.add(self.hud)
     
     self.schedule(self.gameLoop)
Beispiel #4
0
def main():
    def notify(t):
        print "move disk from %s pole to %s pole." % tuple(t)
    notify.arity = 1
        
    prolog = Prolog()
    registerForeign(notify)
    prolog.consult("hanoi.pl")
    list(prolog.query("hanoi(%d)" % N))
Beispiel #5
0
 def prologInitialization(self):
     print "@Agent: Prolog initialization",
     self.prolog = Prolog()
     self.prolog.consult("pl/agent.pl")
     if (self.logToFile):
         self.prolog.query("redirect_output('logs/%s-kb%d.xml')" %
                           (self.username, self.currentLoop)).next()
     if (self.verbose):
         self.prolog.query("assert(verbose)").next()
     print "done"
Beispiel #6
0
def main():  #digunakan untuk membuat fungsi main()
    N = 3  #pendeklarasian nilai N adalah 3
    INTERACTIVITY = True

    prolog = Prolog()
    tower = Tower(N, INTERACTIVITY)
    notifier = Notifier(tower.move)
    registerForeign(notifier.notify)
    prolog.consult("prolog_file/hanoi.pl")
    list(prolog.query("hanoi(%d)" % N))
Beispiel #7
0
def main():
    N = 3
    INTERACTIVITY = True
    
    prolog = Prolog()
    tower = Tower(N, INTERACTIVITY)
    notifier = Notifier(tower.move)
    registerForeign(notifier.notify)
    prolog.consult("hanoi.pl")
    list(prolog.query("hanoi(%d)" % N))
Beispiel #8
0
def main():
    N = 3
    INTERACTIVITY = True

    prolog = Prolog()
    tower = Tower(N, INTERACTIVITY)
    notifier = Notifier(tower.move)
    registerForeign(notifier.notify)
    prolog.consult("hanoi.pl")
    list(prolog.query("hanoi(%d)" % N))
Beispiel #9
0
def imprimirRest():
    p = Prolog()
    p.consult('rest.pl')
    resultados = []
    for result in p.query("restaurante(A,_,_,_,_)"):
        r = result["A"]
        resultados.append(str(r))
    log = file("log.txt", "a")
    log.write(str(resultados) + "\n")
    log.close()
    return resultados
Beispiel #10
0
def restaurantesXtipo(tipocomida):
    p = Prolog()
    p.consult("rest.pl")
    resultados = []
    for restaurante in p.query("restaurantesXtipo(A," + tipocomida + ")"):
        r = restaurante["A"]
        resultados.append(str(r))
    log = file("log.txt", "a")
    log.write(str(resultados) + "\n")
    log.close()
    return resultados
Beispiel #11
0
def imprimirPlato():
    p = Prolog()
    p.consult("plati.pl")
    resultados = []
    for plato in p.query("platillo(_,A,_,_,_)"):
        r = plato["A"]
        resultados.append(str(r))
    log = file("log.txt", "a")
    log.write(str(resultados) + "\n")
    log.close()
    return resultados
Beispiel #12
0
    def __init__(self):

        # http://nullege.com/codes/search/pyswip.prolog.Prolog.query
        self.__root = ''
        self.__on_prolog = 'prolog'
        self.__of_prolog = 'halt.'

        # Preguntas
        self.__a_animal = 'animal(X).'
        self.__prolog = Prolog()
        self._probando()
Beispiel #13
0
def buscaRestaurantesXPais(pais):
    p = Prolog()
    p.consult("plati.pl")
    resultados = []
    for restaurante in p.query("buscaRestXPais(Nombre," + pais + ")"):
        r = restaurante["Nombre"]
        resultados.append(str(r))
    log = file("log.txt", "a")
    log.write(str(resultados) + "\n")
    log.close()
    return resultados
Beispiel #14
0
def main():
    prolog = Prolog()
    prolog.consult("coins.pl")
    count = int(input("How many coins (default: 100)? ") or 100)
    total = int(input("What should be the total (default: 500)? ") or 500)
    for i, soln in enumerate(prolog.query("coins(S, %d, %d)." % (count,total))):
        S = zip(soln["S"], [1, 5, 10, 50, 100])
        print(i, end=" ")
        for c, v in S:
            print("%dx%d" % (c,v), end=" ")
        print()
    list(prolog.query("coins(S, %d, %d)." % (count,total)))
Beispiel #15
0
def main():
    prolog = Prolog()
    prolog.consult("puzzle1.pl")
    for soln in prolog.query("solve(B)."):
        #B = eval(soln["B"])
        B = soln["B"]
        # [NW,N,NE,W,E,SW,S,SE]
        print "%d %d %d" % tuple(B[:3])
        print "%d   %d"   % tuple(B[3:5])
        print "%d %d %d" % tuple(B[5:])
        
        cont = raw_input("Press 'n' to finish: ")
        if cont.lower() == "n": break
Beispiel #16
0
def platillosXrestIngrediente(restaurante, ingrediente):
    p = Prolog()
    p.consult("plati.pl")
    resultados = []
    resultados.append("Lista de platillos de " + restaurante +
                      " que incluyen " + ingrediente + ":")
    for restaurante in p.query("platillosXrestIngrediente(" + restaurante +
                               ",Nombre,Sabor,Pais," + ingrediente + ")"):
        resultados.append(restaurante["Nombre"])
    log = file("log.txt", "a")
    log.write(str(resultados) + "\n")
    log.close()
    return resultados
Beispiel #17
0
def main():
    prolog = Prolog()
    prolog.consult("puzzle1.pl")
    for soln in prolog.query("solve(B)."):
        #B = eval(soln["B"])
        B = soln["B"]
        # [NW,N,NE,W,E,SW,S,SE]
        print "%d %d %d" % tuple(B[:3])
        print "%d   %d"   % tuple(B[3:5])
        print "%d %d %d" % tuple(B[5:])
        
        cont = raw_input("Press 'n' to finish: ")
        if cont.lower() == "n": break
def main():
    prolog = Prolog()
    prolog.consult("puzzle.pl")  #membaca file prolog (puzzle.pl)
    for soln in prolog.query("solusi(B)."):
        #B = eval(soln["B"])
        B = soln["B"]
        # [NW,N,NE,W,E,SW,S,SE]
        print("%d %d %d" % tuple(B[:3]))
        print("%d   %d" % tuple(B[3:5]))
        print("%d %d %d" % tuple(B[5:]))

        cont = input("Tekan 'n' untuk selesai: ")
        if cont.lower() == "n": break
Beispiel #19
0
  def diagnose(self, symptoms, age_group=None):
    """Returns a list of possible diagnosis, if any, given a list of symptoms.

    For example, if german measles has the symptoms 'runny nose', 'fever',
    'headache' and 'rash', the system will return a list containing a dict with
    the diagnosis.

      symptoms = ['runnynose', 'fever', 'headache', 'rash']
      doctor = Doctor('medical')
      results = doctor.diagnose(symptoms)

      results
      >>> [{'Diagnosis': 'germanmeasles'}]

    The diagnosis can be accessed with the key 'Diagnosis'.
    NOTE: The capital D is important.

      diagnosis = results[0]
      diagnosis['Diagnosis']
      >>> 'germanmeasles'
    """

    prolog = Prolog()

    if age_group is not None:
      prolog.assertz('age_group(patient,%s)' % age_group)

    for symptom in symptoms:
      prolog.assertz('symptom(patient,%s)' % symptom)

    prolog.consult(self.prolog_file)
    return list(prolog.query('hypothesis(patient,Diagnosis)'))
def main():
    prolog = Prolog()
    prolog.consult("prolog_file/puzzle1.pl")  #membuka file prolog puzzle.pl
    for soln in prolog.query(
            "solve(B)."):  #menjalankan predikat solve seperti pada file prolog

        B = soln["B"]
        # [NW,N,NE,W,E,SW,S,SE]
        print("%d %d %d" % tuple(B[:3]))  #mencetak angka pada papan
        print("%d   %d" % tuple(B[3:5]))
        print("%d %d %d" % tuple(B[5:]))

        cont = input("Press 'n' to finish: ")
        if cont.lower() == "n": break  #jika ditekan n, program selesai
Beispiel #21
0
    def modified_run(self):
        try:
            from pyswip.prolog import Prolog
            p = Prolog()
            p.assertz('setup_prolog(1)')
            list(p.query('setup_prolog(1)'))
        except:
            print('----------------------')
            print('There is a problem with SWI-Prolog Installation')
            print('Please, check if you have it installed with shared Libraries')
            print('Installation guide: https://github.com/yuce/pyswip/blob/master/INSTALL')
            print('----------------------')

        orig_run(self)
Beispiel #22
0
def findShortestPath(from_input, to_input):
    prolog = Prolog()
    loadDatabase(prolog)
    prolog_query = "path(" + from_input + "," + to_input + ",PATH,COST)"
    shortest_path_result = list(prolog.query(prolog_query))
    path_list = []
    shortest_path_lst = shortest_path_result

    if len(shortest_path_lst) <= 0:
        return False

    for i in range(len(shortest_path_lst[0]['PATH'])):
        path_list.append(str(shortest_path_result[0]['PATH'][i]))

    return path_list, shortest_path_result[0]['COST']
Beispiel #23
0
def main():
    registerForeign(hello)
    prolog = Prolog()
    #prolog.assertz("father(michael,john)")
    #prolog.assertz("father(michael,gina)")
    #list(prolog.query("father(michael,X), hello(X)"))
    Query(readFileSee('/home/tyler/Documents/Github/crosswordSolver/word_list.txt')))
Beispiel #24
0
    def modified_run(self):
        try:
            from pyswip.prolog import Prolog
            p = Prolog()
            p.assertz('setup_prolog(1)')
            list(p.query('setup_prolog(1)'))
        except:
            print('----------------------')
            print('There is a problem with SWI-Prolog Installation')
            print(
                'Please, check if you have it installed with shared Libraries')
            print(
                'Installation guide: https://github.com/yuce/pyswip/blob/master/INSTALL'
            )
            print('----------------------')

        orig_run(self)
def main():
    prolog = Prolog()
    
    a1 = PL_new_term_refs(2)
    a2 = a1 + 1
    t = PL_new_term_ref()
    ta = PL_new_term_ref()

    animal2 = PL_new_functor(PL_new_atom("animal"), 2)
    assertz = PL_new_functor(PL_new_atom("assertz"), 1)

    PL_put_atom_chars(a1, "gnu")
    PL_put_integer(a2, 50)
    PL_cons_functor_v(t, animal2, a1)
    PL_cons_functor_v(ta, assertz, t)
    PL_call(ta, None)
    
    print(list(prolog.query("animal(X,Y)", catcherrors=True)))
Beispiel #26
0
 def prologInitialization(self):
     print "@Agent: Prolog initialization",
     self.prolog = Prolog()
     self.prolog.consult("pl/agent.pl")
     if (self.logToFile):
         self.prolog.query("redirect_output('logs/%s-kb%d.xml')" % (self.username, self.currentLoop)).next()
     if (self.verbose):
         self.prolog.query("assert(verbose)").next()
     print "done"
Beispiel #27
0
    def partial_diagnosis(self, symptoms):

        prolog = Prolog()

        for file in self.prolog_files:
            prolog.consult(file)

        differntial_diagnosis = []

        for symptom in symptoms:
            for result in prolog.query("hasSymptom(Illness, %s)" % symptom):
                differntial_diagnosis.append(result["Illness"])

        sick_list = []

        # Removes multiple illnesses from the list
        sick_list = list(set(differntial_diagnosis))

        return sick_list
Beispiel #28
0
def main():
    prolog = Prolog()

    a1 = PL_new_term_refs(2)
    a2 = a1 + 1
    t = PL_new_term_ref()
    ta = PL_new_term_ref()

    animal2 = PL_new_functor(PL_new_atom("animal"), 2)
    assertz = PL_new_functor(PL_new_atom("assertz"), 1)
    PL_put_atom_chars(a1, "gnu")
    PL_put_integer(a2, 50)
    # PL_cons_functor(t, animal2, a1, a2)
    PL_cons_functor_v(t, animal2, a1)
    PL_cons_functor_v(ta, assertz, t)
    PL_call(ta, None)

    #    prolog.assertz("animal(gnu, 50)")
    print list(prolog.query("animal(X,Y)", catcherrors=True))
Beispiel #29
0
  def partial_diagnosis(self, symptoms):

    prolog = Prolog()

    for file in self.prolog_files:
      prolog.consult(file)

    differntial_diagnosis = []

    for symptom in symptoms:
      for result in prolog.query('hasSymptom(Illness, %s)' % symptom):
        differntial_diagnosis.append(result['Illness'])

    sick_list = []

    # Removes multiple illnesses from the list
    sick_list = list(set(differntial_diagnosis))

    return sick_list
    def test_load_database(self):
        try:
            prolog = Prolog()
            loadDatabase(prolog)

        except:
            print("ERROR: cannot load database")

        finally:
            # do something after show msg
            pass
Beispiel #31
0
def run_prolog(pipe):
    prolog = Prolog()
    while True:
        request = pipe.recv()
        if request == 0:
            break
        request, args = request
        func = getattr(prolog, request)
        result = func(*args)
        if result is not None:
            result = list(result)
        pipe.send(result)
Beispiel #32
0
def buscaRestaurantesXNombre(nombre):
    p = Prolog()
    p.consult("rest.pl")
    resultados = []
    for restaurante in p.query("buscaRest(" + nombre + ",A,B,C,D)"):
        temporal = []
        tipo = restaurante["A"]
        ubicacion = restaurante["B"]
        telefono = str(restaurante["C"])
        jornada = restaurante["D"]
        temporal.append(str(tipo))
        temporal.append(str(ubicacion))
        temporal.append(str(telefono))
        temporal.append(str(jornada))
        temporal.append("Fin de restaurante")
        resultados.append(temporal)
        temporal = []
    log = file("log.txt", "a")
    log.write(str(resultados) + "\n")
    log.close()
    return resultados
Beispiel #33
0
def buscaPlatillosRest(restaurante):
    p = Prolog()
    p.consult("plati.pl")
    resultados = []
    for restaurante in p.query("platillosXrest(" + restaurante +
                               ",Nombre,Sabor,Pais,Ingredientes)"):
        temporal = []
        temporal.append("Nombre: " + str(restaurante["Nombre"]))
        temporal.append("Sabor: " + str(restaurante["Sabor"]))
        temporal.append("Pais de origen: " + restaurante["Pais"])
        t = ""
        for i in list(restaurante["Ingredientes"]):
            t += str(i) + " - "
        temporal.append(str("Ingredientes: " + t))
        t = ""
        resultados.append(temporal)
        temporal = []
    log = file("log.txt", "a")
    log.write(str(resultados) + "\n")
    log.close()
    return resultados
Beispiel #34
0
def main():
    prolog = Prolog()

    #membuka file coins.pl
    prolog.consult("prolog_file/coins.pl")

    #mendeklarasi nilai count dan total
    #menginputkan nilai count dan nilai total berupa angka
    count = int(input("Berapa jumlah koin(default: 100)? ") or 100)
    total = int(input("Jumlah target total (default: 500)? ") or 500)

    #melakukan perulangan dengan menampilkan nilai yang ada di dalam list
    #enumerate berfungsi untuk mengembalikan sebuah objek iterable yang setiap itemnya memiliki indeks
    #memanggil fungsi coins pada prolog
    for i, soln in enumerate(prolog.query("coins(S, %d, %d)." %
                                          (count, total))):
        # [1,5,10,50,100]
        S = zip(soln["S"], [1, 5, 10, 50, 100])
        print(i),  #cetak nilai

        #melakukan perulangan untuk menampilkan angka perkalian
        for c, v in S:
            print("%dx%d" % (c, v)),  #cetak perkalian
        print  #cetak hasil perulangan

    #fungsi list yaitu mengembalikan list berisi anggota-anggota dari objek yang menjadi argumennya
    #jika argumennya kosong, maka fungsi ini akan mengembalikan list kosong
    #jika argumennya berisikan data, maka yang digunakan adalah data-data yang digunakan dari list tersebut
    #hasil akhirnya akan menampilkan perhitungan perkalian dari jumlah nilai yang diinputkan
    list(prolog.query("coins(S, %d, %d)." % (count, total)))
Beispiel #35
0
    def diagnose(self, symptoms, age_group=None):
        """Returns a list of possible diagnosis, if any, given a list of symptoms.

    For example, if german measles has the symptoms 'runny nose', 'fever',
    'headache' and 'rash', the system will return a list containing a dict with
    the diagnosis.

      symptoms = ['runnynose', 'fever', 'headache', 'rash']
      doctor = Doctor('medical')
      results = doctor.diagnose(symptoms)

      results
      >>> [{'Diagnosis': 'germanmeasles'}]

    The diagnosis can be accessed with the key 'Diagnosis'.
    NOTE: The capital D is important.

      diagnosis = results[0]
      diagnosis['Diagnosis']
      >>> 'germanmeasles'
    """

        prolog = Prolog()

        if age_group is None:
            age_group = 'none'

        patient = 'patient'
        self._query_and_log(prolog.assertz,
                            'age_group(%s,%s)' % (patient, age_group))
        for symptom in symptoms:
            self._query_and_log(prolog.assertz,
                                'symptom(%s,%s)' % (patient, symptom))

        for file in self.prolog_files:
            prolog.consult(file)

        return list(
            self._query_and_log(prolog.query,
                                'hypothesis(%s,Diagnosis)' % patient))
Beispiel #36
0
class MainController:
    def __init__(self):

        # http://nullege.com/codes/search/pyswip.prolog.Prolog.query
        self.__root = ''
        self.__on_prolog = 'prolog'
        self.__of_prolog = 'halt.'

        # Preguntas
        self.__a_animal = 'animal(X).'
        self.__prolog = Prolog()
        self._probando()

    def _verifica_animal(self):
        self.__prolog.consult(self.__root)
        print '\nprolog dame ejemplos de animales: '
        for soln in self.__prolog.query(self.__a_animal):
            X = soln["X"]
            print X

    def _probando(self):
        Question().run()
Beispiel #37
0
def main():
    # Initialize the prolog code
	prolog = Prolog()
	prolog.consult("talking_to_kid.pl")
	item = 'slides'
	stop = False
	first = True
	positive = True

	# Main program loop
	while not stop:
		#Ask someone a question based on their previous answer
		if first:
            # If this is the first question, we have a neutral statement
			first = False
			response = query(item, 'Hello!', '?')
		else:
			if positive:
                # We pick a random positive prefix and suffix if they answered positively previously
				response = query(item, random.choice(positivePrefix), random.choice(positiveSuffix))
			else:
                # We pick a random negative prefix and suffix if they answered 'no' to the previous queries
				response = query(item, random.choice(negativePrefix), random.choice(negativeSuffix))
		if response:
			#If the response is True, ask a followup
			followup = list(prolog.query('followup({}, Y)'.format(item)))
			# Retrieve a random followup question related to the item (Since some items can have multiple followups)
			followup_item = random.choice(followup)['Y']
			followup_true = askFollow(followup_item)
			# If the followup is true, then we can say that they like the item. Otherwise they dislike it
            # We add the item to the knowledge base as something that is liked or disliked by asserting this to the prolog script.
            if followup_true:
				prolog.assertz('like({})'.format(item))
				positive = True # Remember the positivity of the statement to change the statement
			else:
				prolog.assertz('dislike({})'.format(item))
				positive = False

		else:
Beispiel #38
0
def main():
    prolog = Prolog()
    prolog.consult("coins.pl")
    count = int(input("How many coins (default: 100)? ") or 100)
    total = int(input("What should be the total (default: 500)? ") or 500)
    for i, soln in enumerate(prolog.query("coins(S, %d, %d)." % (count,total))):
        # [1,5,10,50,100]
        S = list(zip(soln["S"], [1, 5, 10, 50, 100]))
        print(i, end=' ')
        for c, v in S:
            print("%dx%d" % (c,v), end=' ')
        print()
    list(prolog.query("coins(S, %d, %d)." % (count,total)))
Beispiel #39
0
def main():
    registerForeign(hello)
    prolog = Prolog()
    prolog.assertz("father(michael,john)")
    prolog.assertz("father(michael,gina)")    
    list(prolog.query("father(michael,X), hello(X)"))
Beispiel #40
0
class Agent():
    
# The Agent class' point of entry is the mainLoop method.
# This method cycles through simulations and exits when it receives a 'bye'
# message or encounters an anomalous situation. The mainLoop method calls the
# perceiveActLoop, which encapsulates message reception and handling.
# If an action-request message is received, the processActionRequest method is
# called.
# This in turn calls the processPerception method, which uses the various other
# process* methods to update the agent's KB with information from the
# perception.
# Decision making takes place in the processActionRequest method.

    #----------------------------------------------------------------------------------------------#
    def __init__(self, USER, PASS, logToFile, massimHost, perceptServerHost, perceptServerPort, dummy, communication, verbose):
        self.firstTurn = True
        self.username = USER
        self.password = PASS
        
        self.dummy = dummy
        if (dummy):
            print "@Agent: Running in dummy mode."
        self.auxTimeDummy = 10 #10 milisegundos para ejecutar dummy
        
        self.communication = communication
        if (communication):
            print "@Agent: Running with communication protocol activated."
        
        self.verbose = verbose
        if (verbose):
            print "@Agent: Running in verbose mode."
        
        self.logToFile = logToFile
        if (logToFile):
            print "@Agent: Logging to file."
            sys.stdout = open('logs/%s-log.txt' % USER, 'w')
        else:
            pass
        self.log = sys.stdout

        self.massimHost = '127.0.0.1'
        if (massimHost):
            self.massimHost = massimHost
        self.deadline = 0
        print "@Agent: Basic initialization",
        self.massimConnection = MASSimConnection(self.massimHost, 12300, USER, PASS)
        
        self.perceptServerHost = perceptServerHost
        self.perceptServerPort = perceptServerPort  
        if (perceptServerPort and perceptServerHost):
            self.perceptConnection = PerceptConnection(perceptServerHost, int(perceptServerPort), USER)
        else:
            self.perceptConnection = VortexPerceptConnection()
        print "done"



    #----------------------------------------------------------------------------------------------#
    def connect(self):
        # Connect and authenticate to the MASSim server.
        try:
            self.massimConnection.connect()
        except:
            print "@Agent: Error during connection attempt to the MASSim server."
            quit()



    #----------------------------------------------------------------------------------------------#
    def disconnect(self):
        # Let both the MASSim server and the percept server know that we will no
        # longer be connecting.
        self.massimConnection.disconnect()
        self.perceptConnection.disconnect()
        if (self.logToFile):
           self.log.close()
           self.log = sys.__stdout__
           sys.stdout = sys.__stdout__



    #----------------------------------------------------------------------------------------------#
    def prologInitialization(self):
        print "@Agent: Prolog initialization",
        self.prolog = Prolog()
        self.prolog.consult("pl/agent.pl")
        if (self.logToFile):
            self.prolog.query("redirect_output('logs/%s-kb%d.xml')" % (self.username, self.currentLoop)).next()
        if (self.verbose):
            self.prolog.query("assert(verbose)").next()
        print "done"



    #----------------------------------------------------------------------------------------------#
    def prologFinalization(self):
        print "@Agent: Prolog finalization",
        self.prolog.query("retractall(k(_))").next()
        self.prolog.query("retractall(b(_))").next()
        self.prolog.query("retractall(h(_))").next()
        self.prolog.query("retractall(myName(_))").next()
        self.prolog.query("retractall(visibleNode(_))").next()
        self.prolog.query("retractall(notVisible(_))").next()
        self.prolog.query("retractall(explored(_))").next()
        self.prolog.query("retractall(notExplored(_))").next()
        self.prolog.query("retractall(inRange(_))").next()
        self.prolog.query("retractall(buyCount(_,_))").next()
        if self.verbose:
            self.prolog.query("saveKB('-%d')" % self.currentLoop).next()
        self.prolog.query("close_output").next()
        self.prolog = None
        print "done"



    #----------------------------------------------------------------------------------------------#
    def processSimulationStart(self, msg_dict):

        def roleHardCode(username):
            roledict = { '1'  : 'explorer'
                       , '2'  : 'explorer'
                       , '3'  : 'repairer'
                       , '4'  : 'repairer'
                       , '5'  : 'saboteur'
                       , '6'  : 'saboteur'
                       , '7'  : 'sentinel'
                       , '8'  : 'sentinel'
                       , '9'  : 'inspector'
                       , '10' : 'inspector'
                       }
            number = username[-1:]
            if (number == '0'):
                number = '10'
            return roledict[number]
            
        defaultVisionRange = { 'explorer' : 2
                             , 'repairer' : 1
                             , 'saboteur' : 1
                             , 'sentinel' : 3
                             , 'inspector': 1
                             }

        self.role = roleHardCode(self.username)
        self.prolog_role_file = "pl/%s.pl" % (self.role)
        self.prolog.consult(self.prolog_role_file)

        if self.username[-1] == '0':
            team = self.username[:-2]
        else:
            team = self.username[:-1]
        for x in range(1,11):
            self.prolog.query("assertOnce(k(agentRole(%s%d, %s)))" % (team, x, roleHardCode(str(x)))).next()

        self.prolog.query("updateMyName(%s)" % self.username).next()
        if (self.communication):
            self.prolog.query("conectar(%s)" % self.username).next()
            self.prolog.query("registrar([d3lp0r, %s], mapc)" % self.role).next()
        print "@Agent: Saving the visual range of %s: %s" % (self.role, defaultVisionRange[self.role])
        self.prolog.query("assert(myVisionRange(%s))" % defaultVisionRange[self.role]).next()
        self.prolog.query("assert(k(agentVisionRange(0,%s,%s)))" % (self.username, defaultVisionRange[self.role])).next()



    #----------------------------------------------------------------------------------------------#
    def merge_percepts(self, msg_dict_public, msg_dict_difference):
        msg_dict_public['position'].extend(       msg_dict_difference.get('position',       []))
        msg_dict_public['vis_verts'].extend(      msg_dict_difference.get('vis_verts',      []))
        msg_dict_public['vis_edges'].extend(      msg_dict_difference.get('vis_edges',      []))
        msg_dict_public['vis_ents'].extend(       msg_dict_difference.get('vis_ents',       []))
        msg_dict_public['probed_verts'].extend(   msg_dict_difference.get('probed_verts',   []))
        msg_dict_public['surveyed_edges'].extend( msg_dict_difference.get('surveyed_edges', []))
        msg_dict_public['inspected_ents'].extend( msg_dict_difference.get('inspected_ents', []))



    #----------------------------------------------------------------------------------------------#
    def processNodes(self, msg_dict):
        # First, we obtain all the probed vertices.
        # Then, for each visible vertex, we check whether the vertx is among the probed vertices.
        # If it is, it's information is updated with it's value.
        # Otherwise, it's information is updated with the value unknown.
        probed_verts = msg_dict.get('probed_verts', [])
        self.prolog.query("retractall(inRange(_))").next()
        for x in msg_dict.get('vis_verts', []):
            self.prolog.query("asserta(inRange(%s))" % x['name']).next()
            # in_pv == "in probed vertices"
            in_pv = False
            for pv in probed_verts:
                if (pv['name'] == x['name']):
                    in_pv = True
                    break
            if (in_pv):
                self.prolog.query('updateNodeValue(%s,%s)' % (x['name'], pv['value'])).next()
            else:
                self.prolog.query('updateNodeValue(%s,unknown)' % x['name']).next()
            self.prolog.query('updateNodeTeam(%s,%s)' % (x['name'], x['team'])).next()



    #----------------------------------------------------------------------------------------------#
    def processEdges(self, msg_dict):
        # We update the map state with edges.
        for e in msg_dict.get('vis_edges', []):
            self.prolog.query("updateEdge(%s,%s,unknown)" % (e['node1'], e['node2'])).next()
        for e in msg_dict.get('surveyed_edges', []):
            self.prolog.query("updateEdge(%s,%s,%s)" % (e['node1'], e['node2'], e['weight'])).next()



    #----------------------------------------------------------------------------------------------#
    def processEntities(self, msg_dict_private, msg_dict_public):
        # Process the rest of the visible entities.
        for vis_ent in msg_dict_public['vis_ents']:
            self.prolog.query("updateEntityTeamPosition(%s,%s,%s,%s)" % (vis_ent['name'], vis_ent['team'], vis_ent['node'], vis_ent['status'])).next()

        # Proceso las entidades en la percepcion compartida.
        # Si o si son de tu equipo, luego el team se fija a el propio.
        for p in msg_dict_public.get('position', []):
            # Get my own team name from the list of visible entities.
            team = 'd3lp0r'
            for e in msg_dict_public['vis_ents']:
                if (unicode(self.username) == e['name']):
                    team = e['team']
                    break

            # Caso especial: cuando soy yo mismo.
            if (p['name'] == 'self'):
                parameters = ( self.username
                             , team
                             , p['node']
                             , self.role
                             , msg_dict_private['energy']
                             , msg_dict_private['max_energy']
                             , msg_dict_private['health']
                             , msg_dict_private['max_health']
                             , msg_dict_private['strength']
                             , msg_dict_private['vis_range']
                             )
                self.prolog.query("updateEntity(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" % parameters).next()
            else:
                parameters = ( p['name']
                             , team
                             , p['node']
                             , p['health']
                             , p['max_health']
                             , p['vis_range']
                             )
                self.prolog.query("updateTeammateEntity(%s,%s,%s,%s,%s,%s)" % parameters).next()

        # Proceso las entidades inspeccionadas.
        for e in msg_dict_public['inspected_ents']:
            parameters = ( e['name']
                         , e['team']
                         , e['node']
                         , e['role']
                         , e['energy']
                         , e['max_energy']
                         , e['health']
                         , e['max_health']
                         , e['strength']
                         , e['vis_range']
                         )
            self.prolog.query("updateEntity(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" % parameters).next()



    #----------------------------------------------------------------------------------------------#
    def processPerception(self, msg_dict_private, msg_dict_public):
        # Actualizamos cada uno de los campos individuales del agente.
        self.prolog.query("updateStep(%s)"              % msg_dict_private['step']).next()
        self.prolog.query("updateMaxEnergyDisabled(%s)" % msg_dict_private['max_energy_disabled']).next()
        self.prolog.query("updateLastAction(%s)"        % msg_dict_private['last_action']).next()
        self.prolog.query("updateLastActionResult(%s)"  % msg_dict_private['last_action_result']).next()
        self.prolog.query("updateMoney(%s)"             % msg_dict_private['money']).next()
        self.prolog.query("updateScore(%s)"             % msg_dict_private['score']).next()
        self.prolog.query("updateZoneScore(%s)"         % msg_dict_private['zone_score']).next()
        self.prolog.query("updateLastStepScore(%s)"     % msg_dict_private['last_step_score']).next()
        self.processNodes(msg_dict_public)
        self.processEdges(msg_dict_public)
        self.processEntities(msg_dict_private, msg_dict_public)
        self.prolog.query("updatePhase").next()



    #----------------------------------------------------------------------------------------------#
    def processActionRequest(self, action_id, msg_dict_private, msg_dict_public):
        print "@Agent: received request-action. id: %s" % action_id

        # Synchronize perceptions with others.
        if (self.firstTurn):
            msg_dict_difference = self.perceptConnection.send_and_recv(msg_dict_public, True)
            print "@Agent: first turn running, requesting history from percept server."
            print_message(msg_dict_difference)
        else:
            msg_dict_difference = self.perceptConnection.send_and_recv(msg_dict_public)
        self.merge_percepts(msg_dict_public, msg_dict_difference)

        # Process perception.
        self.processPerception(msg_dict_private, msg_dict_public)
        
        # Decide action.
        now = time.time()
        if self.dummy or (now > self.deadline):
            query_result = self.prolog.query("execDummy(X)").next()
        else:
            self.remainingTime = self.deadline - now
            query_result = self.prolog.query("run(%s, X)" % self.remainingTime).next()
        actionList   = query_result['X']

        if   (len(actionList) == 1):
            action_xml = action(action_id, actionList[0])
            action_str = actionList[0]
            print "@Agent: action: %s" % actionList[0]
        elif (len(actionList) == 2):
            print "@Agent: action: %s %s" % (actionList[0], actionList[1])
            action_str = '%s(%s)' % (actionList[0], actionList[1])
            action_xml = action(action_id, actionList[0], actionList[1])
        else:
            print "@Agent: error in returned action."
            print "@Agent: return value: %s" % actionList
            action_xml = action(action_id, "skip")
            action_str = 'skip'
        return (action_xml, action_str)



    #----------------------------------------------------------------------------------------------#
    def perceiveActLoop(self):
        # Receive simulation start notification.
        print "@Agent: Waiting for message from MASSim server."

        xml = self.massimConnection.receive()
        msg_type, _, msg_dict, _ = parse(xml)

        quitPerceiveActLoop = False
        while (not quitPerceiveActLoop):
            
            xml = self.massimConnection.receive()
            msg_type, action_id, msg_dict_private, msg_dict_public = parse(xml)

            # Apparently, the sim-start message is not received at the very beginning. 
            self.processSimulationStart(msg_dict)

            if (msg_type == 'sim-start'):
                print "\n\n===== NEW SIMULATION =====\n\n"
                print "@Agent: Received simulation start notification."
                print_message(msg_dict)
                print "@Agent: Processing simulation start...",
                self.processSimulationStart(msg_dict)
                print "done"
                quitPerceiveActLoop = False
            elif (msg_type == 'request-action'):
                print "@Agent: %s receiving perception from server..." % self.username
                self.turnStartTime = time.time()
                self.deadline = self.massimConnection.messageReceived + msg_dict_private['total_time'] / 1000 - 0.2 # VALOR A CAMBIAR
                print "------------------------------------------------------------"
                print "@Agent: Step: %s" % msg_dict_private['step']

                # Primera fase deliberativa: el agente considera por si mismo que accion realizar.
                action_xml, action_str = self.processActionRequest(action_id, msg_dict_private, msg_dict_public)

                # Segunda fase: los agentes se comunican entre si, y se reconsideran las acciones.
                if (self.communication):
                    self.prolog.query("communicateAndResolveConflicts(%s, NewAction)" % action_str).next()

                # Send the action to the MASSim server.
                self.massimConnection.send(action_xml)
                self.firstTurn = False
            elif (msg_type == 'sim-end'):
                print "@Agent: Received sim-end"
                print_message(msg_dict_private)
                quitPerceiveActLoop = True
            elif (msg_type == 'bye'):
                print "@Agent: Received bye"
                print_message(msg_dict_private)
                self.quit = True
                quitPerceiveActLoop = True
            else:
                print "@Agent: In area 51."
                print_message(msg_dict_private)
                quitPerceiveActLoop = True
                self.quit = True



    #----------------------------------------------------------------------------------------------#
    def mainLoop(self):
        self.quit = False
        agent.connect()
        self.currentLoop = 0
        while (not self.quit):
            self.currentLoop += 1
            self.prologInitialization()
            try:
                self.perceiveActLoop()
            except socket.error:
                self.prolog.query("catch(saveKB('-fin-%d'),E,writeln(E))" % self.currentLoop).next()
                sys.exit(0)
            self.prologFinalization()
        if not self.logToFile:
            raw_input("\nFinished. Press ENTER to continue...")
        agent.disconnect()