Esempio n. 1
0
class AI():
    id = 0
    life = 10
    level = 1
    vision = 3
    freePlace = 0
    nbPlayer = []

    inventory = {"linemate": 0, "deraumere": 0, "sibur": 0, "mendiane": 0, "phiras": 0, "thystame": 0}
    cases = []
    listCommand = []
    broadcastMessage = []

    ignoreMessage = 0
    asking = 0
    firstAction = True
    firstReceive = True
    listChild = []

    def __init__(self, optManager):
        self.optManager = optManager
        self.socket = Socket(optManager)
        self.id = randint(1, 100000)

        for i in range(0, 80):
            self.cases.append(["-1"])

    def signalHandler(*args):
        for child in args[0].listChild:
            os.kill(child, signal.SIGTERM)
        sys.exit()

    def countNbPlayer(self, message):
        self.nbPlayer = counterPlayer

    def broadcastLevel(self):
        if self.listCommand == []:
            self.listCommand.append("broadcast " + self.optManager.nameEquip + " /l " + str(self.level))

    def broadcastMoveTo(self, message):
        orientation = int(message[0])
        walk = []

        if self.life < 10:
            return

        print ("ORIENTATION:", orientation)
        if orientation == 1:
            walk = ["avance"]
        elif orientation == 2:
            walk = ["avance", "gauche", "avance"]
        elif orientation == 3:
            walk = ["gauche", "avance"]
        elif orientation == 4:
            walk = ["gauche", "avance", "gauche", "avance"]
        elif orientation == 5:
            walk = ["gauche", "gauche", "avance"]
        elif orientation == 6:
            walk = ["droite", "avance", "droite", "avance"]
        elif orientation == 7:
            walk = ["droite", "avance"]
        elif orientation == 8:
            walk = ["avance", "droite", "avance"]

        walk.append("voir")
        for move in walk:
            Macro.CommandRef[move](self, True)

    def readBroadcast(self):
        idx = 0
        while idx < len(self.broadcastMessage):
            message = self.broadcastMessage[0]
            if message[1] == '/a':
                Macro.BroadcastRespRef[message[1]](self, message)
                self.broadcastMessage.pop(idx)
                idx = -1
            elif message[1] == '/l' and int(message[2]) != self.level:
                self.broadcastMessage.pop(idx)
                idx = -1
            idx += 1

        idx = 0

        print ("CAN I READ broadcast LEVEL ?", self.listCommand)
        if self.listCommand == []:
            if self.broadcastMessage != []:
                message = self.broadcastMessage[0]
                print ("|-^-| broadcast:", message)
                if message[1] != '/l':
                    Macro.BroadcastRespRef[message[1]](self, message)
                    self.broadcastMessage.pop(0)

            idxLast = -1
            i = 0
            while i < len(self.broadcastMessage):
                if self.broadcastMessage[i][1] == '/l':
                    idxLast = i
                i += 1

            if idxLast != -1:
                Macro.BroadcastRespRef["/l"](self, self.broadcastMessage[-1])

            idx = 0
            while idx < len(self.broadcastMessage):
                if self.broadcastMessage[idx][1] == '/l':
                    self.broadcastMessage.pop(idx)
                    idx = -1
                idx += 1

    def broadcastIncrease(self, message):
        myID = int(message[2])
        idAlly = int(message[3])
        if myID == self.id:
            for elem in self.nbPlayer:
                if elem == idAlly:
                    return
            self.nbPlayer.append(idAlly)
            print ("Increased PLAYER: ", idAlly)

    def broadcastRequest(self, message):
        self.socket.sendData("broadcast " + self.optManager.nameEquip + " /r " + str(self.id))
        self.listCommand.append("broadcast " + self.optManager.nameEquip + " /r " + str(self.id))

    def broadcastAnswer(self, message):
        self.listCommand.append("broadcast " + self.optManager.nameEquip + " /a " + message[2] + " " + str(self.id))
        self.socket.sendData("broadcast " + self.optManager.nameEquip + " /a " + message[2] + " " + str(self.id))

    def isRes(self, elem):
        if elem != "joueur" and elem != "" and elem != "-1" and elem != "nourriture":
            return True
        return False

    def isLevelComplete(self):
        levelRef = Macro.LevelRef[self.level]

        for elem in levelRef:
            if self.isRes(elem):
                if levelRef[elem] > self.inventory[elem]:
                    return False
        return True

    def putResOnCase(self, idx = 0):
        ressourceCase = dict(Macro.LevelRef[0])

        for elem in self.cases[0]:
            if self.life > 10:
                break
            if elem == "nourriture":
                self.funcPrend(idx, True)

        for elem in self.cases[0]:
            if self.isRes(elem):
                ressourceCase[elem] += 1
        for elem in ressourceCase:
            if elem != "joueur":
                if ressourceCase[elem] < Macro.LevelRef[self.level][elem]:
                    self.listCommand.append("pose " + elem + " " + str(0))

                    self.inventory[elem] -= 1
                    self.cases[0].append(elem)
                    return -1
                elif ressourceCase[elem] > Macro.LevelRef[self.level][elem]:
                    self.listCommand.append("prend " + elem + " " + str(0))
                    self.inventory[elem] += 1
                    self.cases[0].remove(elem)
                    return -1
        return 0

    def getCase(self, message):
        message = message.replace("{", "").replace("}", "")
        listCase = message.split(",")

        for idx, case in enumerate(listCase):
            self.cases[idx] = case[1:].split(" ")
        for command in self.listCommand:
            if command.find("prend") != -1:
                try:
                    info = command.split(" ")
                    self.cases[info[2]].remove(info[1])
                except:
                    eprint("ERROR DANS L ANTICIPATION PREND")
                    continue
            if command.find("pose") != -1:
                try:
                    info = command.split(" ")
                    self.cases[info[2]].append(info[1])
                except:
                    eprint("ERROR DANS L ANTICIPATION POSE")
                    continue

    def getCaseLevel(self):
        for idx, case in enumerate(self.cases):
            for elem in case:
                if self.isRes(elem):
                    ret = Macro.LevelRef[self.level][elem] - self.inventory[elem]
                    if ret > 0 and not "joueur" in case:
                        print ("Is there a player:", case)
                        return idx
        return -1

    def getCaseIncant(self):
        ret = (-1, -1)
        for idx, elem in enumerate(self.cases):
            nbAction = self.canIncant(idx)
            if nbAction != -1 and (nbAction < ret[1] or ret[1] == -1):
                ret = (idx, nbAction)
            if getIdxMax(self.vision) < idx:
                break
        if ret[0] == -1:
            return -1
        return ret[0]

    def canIncant(self, idx = 0):
        levelRef = dict(Macro.LevelRef[self.level])
        ressourceCase = dict(Macro.LevelRef[0])
        invRef = dict(self.inventory)

        if len(self.cases[idx]) > 0 and self.cases[idx][0] == "-1":
            return -1

        for elem in self.cases[idx]:
            if elem != "nourriture" and elem != "":
                ressourceCase[elem] += 1

        ret = 0
        for elem in ressourceCase:
            if ressourceCase[elem] > levelRef[elem] or ressourceCase[elem] < levelRef[elem]:
                ret = 1
        if ret == 0:
            return 0

        ret = 0
        tmpCase = dict(ressourceCase)
        for elem in ressourceCase:
            if elem != "nourriture" and elem != "joueur":
                tmpCase[elem] += invRef[elem]
                if tmpCase[elem] < levelRef[elem]:
                    ret = 1
        if ret == 1:
            return -1

        action = 0
        for elem in ressourceCase:
            if ressourceCase[elem] > levelRef[elem]:
                while ressourceCase[elem] > levelRef[elem]:
                    action += 1
                    ressourceCase[elem] -= 1
            elif ressourceCase[elem] > levelRef[elem]:
                while ressourceCase[elem] < levelRef[elem]:
                    action += 1
                    ressourceCase[elem] += 1
        if self.level == 1 and self.cases[idx].count("joueur") > 1:
            return -1
        elif self.level != 1 and self.cases[idx].count("joueur") > Macro.LevelRef[self.level]["joueur"]:
            return -1
        return action

    def funcDroite(self, broadcast = False):
        if broadcast is True:
            self.socket.sendData("droite")
            self.listCommand.append("droite")
            return
        self.listCommand.append("droite")

    def funcGauche(self, broadcast = False):
        if broadcast is True:
            self.socket.sendData("gauche")
            self.listCommand.append("gauche")
            return
        self.listCommand.append("gauche")

    def funcAvance(self, broadcast = False):
        if broadcast is True:
            self.socket.sendData("avance")
            self.listCommand.append("avance")
            return
        self.listCommand.append("avance")

    def funcVoir(self, broadcast = False):
        if broadcast is True:
            self.socket.sendData("voir")
            self.listCommand.append("voir")
            return
        self.listCommand.append("voir")

    def funcPrend(self, idx, food = False):
        case = self.cases[idx]

        if food is True:
            if "nourriture" in case:
                self.listCommand.append("prend nourriture " + str(idx))
                case.remove("nourriture")
            return

        for res in case:
            if self.isRes(res):
                if self.inventory[res] + 1 <= Macro.LevelRef[self.level][res]:
                    self.inventory[res] += 1
                    self.listCommand.append("prend " + res + " " + str(idx))
                    case.remove(res)
                else:
                    eprint("Doesn't need 'prend " + res + "'")

    def funcExpulse(self):
        self.listCommand.append("expulse")

    def funcIncantation(self, idx = 0):
        print ("Func incantation")
        if self.putResOnCase(idx) == -1:
            return
        self.listCommand.append("incantation")

    def connectNewPlayer(self):
        pid = os.fork()
        if pid == 0:
            FNULL = open(os.devnull, 'w')
            FTEST = open("test", "w+")
            self.listChild.append(subprocess.Popen("./zappy_ai " + " -n " + self.optManager.nameEquip + " -p " + str(self.optManager.port) + " -h " + self.optManager.host, stdout=FTEST, shell=True))
            sys.exit()

    def funcFork(self):
        self.listCommand.append("fork")

    def isRessource(self, ressource):
        for i in range(0, len(self.cases)):
            for res in self.cases[i]:
                if res == ressource:
                    return i
        return -1

    def blind(self):
        count = 0
        for i in range(0, getNbCaseLevel(self.vision)):
            for elem in self.cases[i]:
                if elem == "-1":
                    count += 1
        total = getNbCaseLevel(self.vision)

        if count / total >= 0.75:
            return True
        return False

    def moveTo(self, idx, simulate = False):
        caseTmp = list(self.cases[idx])
        walk = []
        count = 0
        if idx == 0:
            if simulate is True:
                return 0
            return

        for i, lineValues in enumerate(Macro.LineRef):
            if lineValues[0] <= idx <= lineValues[1]:
                count = i
                break
        for i in range(0, count + 1):
            walk.append("avance")

        line = Macro.LineRef[count]
        middle = (line[0] + line[1]) / 2
        if idx < middle:
            walk.append("gauche")
            while idx < middle:
                walk.append("avance")
                idx += 1
        elif idx > middle:
            walk.append("droite")
            while idx > middle:
                walk.append("avance")
                idx -= 1

        if simulate is True:
            return len(walk)

        if walk == []:
            return
        for move in walk:
            Macro.CommandRef[move](self)
        self.cases[0] = caseTmp

    def getCaseFood(self):
        for i in range(0, len(self.cases)):
            for res in self.cases[i]:
                if res == "nourriture":
                    return i
        return -1

    def needFork(self):
        if self.asking == 0:
            self.broadcastRequest("")
            self.asking = 1
            self.ownTimer = time.time()
        if time.time() - self.ownTimer >= 6.0:
            if self.asking == 1 and len(self.nbPlayer) < 8:
                if self.life > 10:
                    self.funcFork()
                    self.asking = 3

    def checkIncantPlayer(self, idx = 0):
        case = self.cases[idx]

        print ("NB player", case.count("joueur"))
        if case.count("joueur") == Macro.LevelRef[self.level]["joueur"]:
            return True

        if self.putResOnCase() == -1:
            return False

        print ("send broadcast /l")
        if case.count("joueur") < Macro.LevelRef[self.level]["joueur"] and self.life > 10:
            Macro.BroadcastRef["/l"](self)
        return False

    def chooseAnAction(self):
        print ("--- Vision ---")
        printList(self.vision, self.level, self.cases)
        print ("--------------")
        print ("--- Life:", self.life)
        print ("--- Free Place:", self.freePlace)
        print ("--- Inventory:", self.inventory)
        print ("--- Level Complete:", self.isLevelComplete())


        self.constructArmy()
        self.needFork()

        if self.canIncant() != -1 and self.life > 10:
            if self.checkIncantPlayer():
                self.funcIncantation()
            return

        if self.blind():
            self.funcVoir()
            return

        idx = self.getCaseFood()
        if self.life < 10 and idx != -1:
            print ("Get food:", idx)
            self.moveTo(idx)
            if self.checkIncantPlayer(idx):
                self.funcIncantation(idx)
            self.funcPrend(idx, True)
            return

        idx = self.getCaseIncant()
        if idx != -1 and self.life < 10:
            print ("Get incant Case:", idx)
            self.moveTo(idx)
            return

        idx = self.getCaseLevel()
        if idx != -1 and self.life < 10:
            print ("Get Res :", idx)
            self.moveTo(idx)
            self.funcPrend(idx, False)
            return

        idx = self.getCaseFood()
        if idx != -1:
            print ("Get food to stock:", idx)
            self.moveTo(idx)
            self.funcPrend(idx, True)
            return

        caseTmp = list(self.cases[2])
        self.moveTo(2)
        self.cases[0] = caseTmp

    def parseBroadcast(self, message):
        listMessage = message.split(",")
        orientation = listMessage[0].split(" ")[1]
        informations = listMessage[1].split(" ")

        final = []
        if informations[0] == self.optManager.nameEquip:
            final.append(orientation)
            final.extend(informations[1:])
            self.broadcastMessage.append(final)

    def updateInfo(self):
        self.listCommand.append("voir")
        self.listCommand.append("inventaire")
        self.listCommand.append("connect_nbr")

    def upStats(self):
        self.level += 1
        self.vision += 2
        print("STATS UPDATED")

    def receiveMessage(self, listMessage):
        message = listMessage[0]
        listMessage.pop(0)
        print ("<|", time.strftime("%H:%M:%S"), ":", message, " |>")
        print ("<|-", self.listCommand, "-|>")

        if message == "mort":
            sys.exit()

        if message.find("niveau actuel") != -1 and len(self.listCommand) > 0 and self.listCommand[0] != "incantation":
            self.upStats()
            message = ""
        if message.find("message") != -1:
            self.parseBroadcast(message)
            message = ""

        if message == "ok" or message == "ko":
            if message == "ko":
                eprint("-----Error ---")
                eprint(self.listCommand[0])
            if len(self.listCommand) > 0 and self.listCommand[0] != "voir" and (self.listCommand[0] != "incantation" or message == "ko"):
                self.listCommand.pop(0)
            message = ""

        if self.listCommand != [] and message != "":
            if self.listCommand[0] == "voir":
                self.getCase(message)
                self.listCommand.pop(0)
            elif self.listCommand[0] == "inventaire":
                self.life = int(message.replace("{", "").replace("}", "").split(",")[0].split(" ")[1])
                self.listCommand.pop(0)
            elif self.listCommand[0] == "connect_nbr":
                self.freePlace = int(message)
                self.listCommand.pop(0)
            elif self.listCommand[0] == "incantation":
                if message.find("niveau actuel") != -1:
                    self.upStats()
                    self.listCommand.pop(0)

    def constructArmy(self):
        while self.freePlace > 1:
            self.connectNewPlayer()
            self.freePlace -= 1

    def initData(self):
        self.socket.sendData("voir")
        self.listCommand.append("voir")
        self.socket.sendData("connect_nbr")
        self.listCommand.append("connect_nbr")

    def run(self):
        self.ownTimer = time.time()
        self.initData()

        signal.signal(signal.SIGINT, self.signalHandler)
        signal.signal(signal.SIGTERM, self.signalHandler)

        print ("----- My ID", self.id, "-----")
        while True:
            messages = self.socket.selectData()
            if messages != []:
                while messages != []:
                    self.receiveMessage(messages)
            if self.broadcastMessage != []:
                self.readBroadcast()
            if self.listCommand == []:
                self.chooseAnAction()
                self.updateInfo()
                print ("Actions:", self.listCommand)
                for command in self.listCommand:
                    if command.find("prend") != -1 or command.find("pose") != -1:
                        self.socket.sendData(command.split(" ")[0] + " " + command.split(" ")[1])
                    else:
                        self.socket.sendData(command)
Esempio n. 2
0
class AI():
    numClient = 0
    life = 10
    level = 1
    freePlace = 0
    inventory = {"linemate": 0, "deraumere": 0, "sibur": 0, "mendiane": 0, "phiras": 0, "thystame": 0}
    cases = [[], [], [], []]
    lastCommand = ""

    firstAction = True
    firstReceive = True

    def __init__(self, optManager):
        self.optManager = optManager
        self.socket = Socket(optManager)

    def isLevelComplete(self):
        levelRef = Macro.LevelRef[self.level]

        for elem in levelRef:
            if levelRef[elem] > self.inventory[elem]:
                return 0
        return 1

    def canIncant(self):
        levelRef = dict(Macro.LevelRef[self.level])
        ressourceCase = dict(Macro.LevelRef[0])
        invRef = dict(self.inventory)

        for elem in self.cases[0]:
            ressourceCase[elem] += 1

        for elem in invRef:
            if levelRef[elem] < invRef[elem]:
                invRef[elem] = levelRef[elem]

        for elem in ressourceCase:
            invRef[elem] += ressourceCase[elem]

        for elem in levelRef:
            if invRef[elem] > levelRef[elem] or invRef[elem] < levelRef[elem]:
                return 0

        return 1

    def putResOnCase(self):
        ressourceCase = dict(Macro.LevelRef[0])

        for elem in self.cases[0]:
            ressourceCase[elem] += 1
        for elem in ressourceCase:
            while ressourceCase[elem] < Macro.LevelRef[self.level]:
                self.socket.sendData("pose " + elem)
                message = ""
                while message == "":
                    message = self.socket.selectData()
                if message != "ok":
                    eprint("Error in put " + elem)
                ressourceCase[elem] += 1

    def createNeuralNetwork(self, load = False):
        listHidden1 = [Neuron("1", 6, load), Neuron("2", 6, load), Neuron("3", 6, load)]
        listHidden2 = [Neuron("4", 3, load), Neuron("5", 3, load)]
        listHidden3 = [Neuron("6", 2, load)]
        listNetwork = [NeuronLayer(listHidden1), NeuronLayer(listHidden2), NeuronLayer(listHidden3)]

        self.neuralNetwork = NeuralNetwork(listNetwork)

    def getCase(self, message):
        message = message.replace("{", "").replace("}", "")
        listCase = message.split(",")
        self.cases.append(listCase[0][1:].split(" "))
        self.cases.append(listCase[1][1:].split(" "))
        self.cases.append(listCase[2][1:].split(" "))
        self.cases.append(listCase[3][1:].split(" "))

    def getCaseLevel(self, idx):
        case = self.cases[idx]
        if len(case) > 0 and case[0] == "-1":
            return -1
        for elem in case:
            if elem != "nourriture" and elem != "joueur" and elem != '':
                ret = Macro.LevelRef[self.level][elem] - self.inventory[elem]
                if ret > 0:
                    return 1
        return 0

    def getCaseFood(self, idx):
        case = self.cases[idx]
        for elem in case:
            if elem == "nourriture":
                return 1
        return 0

    def getRangeAction(self, actionValue):
        last = 0.000
        for i in range(1, len(Macro.RangeRef)):
            #print (last, actionValue, Macro.RangeRef[i])
            if last <= actionValue < Macro.RangeRef[i]:
                return Macro.ActionRef[last]
            last = Macro.RangeRef[i]
        return ""

    def funcDroite(self):
        self.cases[1] = self.cases[3]
        self.cases[2] = ["-1"]
        self.cases[3] = ["-1"]
        self.socket.sendData("droite")
        self.lastCommand = "droite"

    def funcGauche(self):
        self.cases[3] = self.cases[1]
        self.cases[2] = ["-1"]
        self.cases[1] = ["-1"]
        self.socket.sendData("gauche")
        self.lastCommand = "gauche"

    def funcAvance(self):
        self.cases[0] = self.cases[2]
        self.cases[1] = ["-1"]
        self.cases[2] = ["-1"]
        self.cases[3] = ["-1"]
        self.socket.sendData("avance")
        self.lastCommand = "avance"

    def funcVoir(self):
        self.socket.sendData("voir")
        self.lastCommand = "voir"


    def funcPrend(self):
        case = self.cases[0]
        if len(case) > 0:
            self.socket.sendData("prend " + case[0])
            case.remove(case[0])
        else:
            eprint("Impossible to execute 'prend' ")
        self.lastCommand = "prend"

    def funcExpulse(self):
        print ("Expulse ?")
        self.lastCommand = "prend"

    def funcIncantation(self):
        self.putResOnCase()
        self.socket.sendData("incantation")
        self.lastCommand = "incantation"

    def funcFork(self):
        print ("fork")
        self.lastCommand = "fork"


    def chooseAnAction(self):
        inputs = []
        inputs.append(self.life)
        inputs.append(self.level)
        inputs.append(self.freePlace)

        inputs.append(self.getCaseLevel(0))
        inputs.append(self.getCaseLevel(1))
        inputs.append(self.getCaseLevel(2))
        inputs.append(self.getCaseLevel(3))

        inputs.append(self.getCaseFood(0))
        inputs.append(self.getCaseFood(1))
        inputs.append(self.getCaseFood(2))
        inputs.append(self.getCaseFood(3))

        inputs.append(self.isLevelComplete())
        inputs.append(self.canIncant())

        print ("INPUTS:", inputs)
        actionValue = self.neuralNetwork.update(inputs)[0]
        actionChoosen = self.getRangeAction(actionValue)
        if actionChoosen == "":
            eprint("Error in value of the neuralNetwork:", actionValue)
        print (actionValue, "--->", actionChoosen)
        command = input("Command:")
        if command == "quit":
            self.neuralNetwork.save()
            sys.exit()
        elif command == "learn":
            pass #learn it
        Macro.CommandRef[actionChoosen](self)

    def updateInfo(self):
        message = ""
        self.socket.sendData("inventaire")
        while message == "":
            message = self.socket.selectData()
        self.life = int(message.replace("{", "").replace("}", "").split(",")[0].split(" ")[1])

    def initData(self, message):
        # TODO receive "{xx,xx,,,,}\n9\r\n  with voir + connect_nbr CHANGE PARSING
        message = message.split("\n")
        self.getCase(message[0])
        self.freePlace = int(message[1])
        return False

    def receiveMessage(self, message):
        if self.firstReceive is True:
            self.firstReceive = self.initData(message)
        elif message == "mort":
            return
        if self.lastCommand != "":
            if self.lastCommand == "voir" and message[0] == "{":
                self.getCase(message)
            self.lastCommand = ""
        print (time.strftime("%H:%M:%S"), ":", message)

    def run(self):

        self.createNeuralNetwork(False)
        while True:
            message = self.socket.selectData()
            if message:
                self.receiveMessage(message)
            if self.firstAction is True:
                self.socket.sendData("voir")
                self.socket.sendData("connect_nbr")
                self.firstAction = False
            if self.lastCommand == "" and  self.firstReceive is False:
                self.updateInfo()
                self.chooseAnAction()

            message = ""