import random from mesa import Agent from othercharacters import dice, Box, Creature, Armor, Weapon from actions import actions, actionsInterpreter from state import AgentState from direction import Direction class Player(Creature): def __init__(self, unique_id, model, n, s, a, w, maxhp, hp, weap, arm, g, w2, w3, listOfChests): super().__init__(unique_id, model, n, s, a, w, maxhp, hp, weap, arm, g) self.name = n self.strength = s self.agility = a self.wisdom = w self.maxHealth = maxhp self.health = hp self.gold = g self.weapon1 = weap self.weapon2 = w2 self.weapon3 = w3 self.armor = arm self.isBox = False self.isCreature = False self.directions = { Direction.N : [0, 1], Direction.E : [1, 0], Direction.S : [0, -1], Direction.W : [-1, 0] } self.direction = Direction.N self.queue = [] self.hasgoalchest = False self.openedchests = 0 self.__listOfChests = listOfChests self.__actionsCollection = [] def meleeAttack(self, opponent): attackValue = self.strength + dice(6) defenseValue = opponent.strength + opponent.armor.defence damage = attackValue - defenseValue if damage > 0: opponent.health = opponent.health - (damage + self.weapon1.damage) def rangeAttack(self, opponent): attackValue = self.agility + dice(6) defenseValue = opponent.agility damage = attackValue - defenseValue if (damage > 0) and (damage + self.weapon2.damage - opponent.armor.defence > 0): opponent.health = opponent.health - (damage + self.weapon2.damage - opponent.armor.defence) def magicAttack(self, opponent): attackValue = self.wisdom + dice(6) defenseValue = opponent.wisdom damage = attackValue - defenseValue if (damage > 0) and (damage + self.weapon3.damage - opponent.armor.mag_protection > 0): opponent.health = opponent.health - (damage + self.weapon3.damage - opponent.armor.mag_protection) def fightOrFlight(self, opponent): combat = True while combat: choice = dice(4) print("dice rolled:", choice) if choice == 1: running_speed = self.agility + dice(6) opponent_speed = opponent.agility + dice(6) if running_speed > opponent_speed: combat = False print("Player ran away") self.step() else: opponent.defaultAttack(self) if self.health <= 0: combat = False print("Player died :/") elif choice == 2: self.meleeAttack(opponent) if opponent.health > 0: opponent.defaultAttack(self) if self.health <= 0: combat = False print("Player died :/") else: combat = False self.gold = self.gold + opponent.gold opponent.gold = 0 opponent.model.grid.remove_agent(opponent) print("Fight won") elif choice == 3: self.rangeAttack(opponent) if opponent.health > 0: opponent.defaultAttack(self) if self.health <= 0: combat = False print("Player died :/") else: combat = False self.gold = self.gold + opponent.gold opponent.gold = 0 opponent.model.grid.remove_agent(opponent) print("Fight won") else: self.magicAttack(opponent) if opponent.health > 0: opponent.defaultAttack(self) if self.health <= 0: combat = False print("Player died :/") else: combat = False self.gold = self.gold + opponent.gold opponent.gold = 0 opponent.model.grid.remove_agent(opponent) print("Fight won") def openChest(self, chest): self.gold = self.gold + chest.gold print("Chest opened. Gold inside:", chest.gold) chest.gold = 0 self.openedchests += 1 self.hasgoalchest = False chest.model.grid.remove_agent(chest) #self.direction = 0 # po osiągnięciu jednego celu 'restartuje sie' na szukanie ścieżki do kolejnego -- NIE ZEROWAĆ OBROTU - to psuje goldState w bfs!!! # if isinstance(chest.loot,Armor): # buffer = self.armor # self.armor = chest.loot # chest.loot = buffer # if isinstance(chest.loot,Weapon): # if chest.loot.type == "Melee": # buffer = self.weapon1 # self.weapon1 = chest.loot # chest.loot = buffer # elif chest.loot.type == "Range": # buffer = self.weapon2 # self.weapon2 = chest.loot # chest.loot = buffer # elif chest.loot.type == "Magic": # buffer = self.weapon3 # self.weapon3 = chest.loot # chest.loot = buffer #- - - - bfs & successor - - - -# def successor(self, append): rotateLeft = AgentState( append.get_x(), append.get_y(), append.get_direction().counterClockwise() ) rotateRight = AgentState( append.get_x(), append.get_y(), append.get_direction().clockwise() ) move_x = 0 move_y = 0 if append.get_direction() == Direction.N: move_y = 1 elif append.get_direction() == Direction.E: move_x = 1 elif append.get_direction() == Direction.S: move_y = -1 elif append.get_direction() == Direction.W: move_x = -1 if append.get_x() + move_x >= 0 and append.get_x() + move_x < 10 and append.get_y() + move_y >=0 and append.get_y() + move_y < 10: moveForward = AgentState( append.get_x() + move_x, append.get_y() + move_y, append.get_direction() ) else: moveForward = None return [ [actions["rotateLeft"], rotateLeft], [actions["moveForward"], moveForward], [actions["rotateRight"], rotateRight] ] def graphsearch(self, fringe, explored, istate, succesorFunction, goalState): finalActionList = [] fringe.append([None, istate]) # at beginning do nothing while len(fringe) != 0: _flag = True if len(fringe) == 0: return False tmpState = fringe.pop(0) # build dictionary parent = tmpState[1].get_predecessor() #fetch paren state tmpState[1].set_predecessor(None) # clear predecessor - don't build a tree chain if parent is None: finalActionList.append([parent, tmpState]) else: finalActionList.append([parent[1], tmpState]) # pair(key, value) - key: parent state, value: current state + action if tmpState[1].get_x() == goalState.get_x() and tmpState[1].get_y() == goalState.get_y(): return finalActionList explored.append(tmpState) tmpList = succesorFunction(tmpState[1]) for newState in tmpList: _flag = True if newState[1] is None: continue for fringeState in fringe: if fringeState[1].get_x() == newState[1].get_x() and fringeState[1].get_y() == newState[1].get_y() and fringeState[1].get_direction() == newState[1].get_direction(): _flag = False for exploredState in explored: if exploredState[1].get_x() == newState[1].get_x() and exploredState[1].get_y() == newState[1].get_y() and exploredState[1].get_direction() == newState[1].get_direction(): _flag = False if _flag: newState[1].set_predecessor(tmpState) fringe.append(newState) return None def step(self): if self.health > 0: print("position: ", self.pos) # print("direction: ", self.direction) if not self.hasgoalchest: # jeśli nie ma wyznaczonej skrzynki do której idzie to robi bfs żeby ją wyznaczyć # self.path=self.findShortestPathToTarget() if len(self.__listOfChests) != 0: # select and remove element from list randomChest = random.choice(self.__listOfChests) self.__listOfChests.remove(randomChest) self.hasgoalchest = True currentState = AgentState(self.pos[0], self.pos[1], self.direction) goalState = AgentState(randomChest[1][0], randomChest[1][1], self.direction) # find way to goal state self.__actionsCollection = self.graphsearch([], [], currentState, self.successor, goalState) if self.__actionsCollection is None: raise Exception("CRITICAL ERROR - Algorithm error - Path doesn't exist!!! ://") else: #build list from dictionary by last element goalActionsList = [] #keysList = list(self.__actionsCollection.keys()) #valuesList = list(self.__actionsCollection.values()) stateWithChest = self.__actionsCollection[-1] # fetch last item #stateWithChest: # [ # [0] key - parent ActionState: object, # [1] value - node successor: # { # [0] action: string - action to get state # [1] AgentState: object - current state # } # ] goalActionsList.append(stateWithChest[1][0]) # save action tmpState = stateWithChest[0] while tmpState is not None: # iterate while key (parent state) != None index = 0 for valeState in self.__actionsCollection: # find new key(parent status) index in array data if valeState[1][1].get_x() == tmpState.get_x() and valeState[1][1].get_y() == tmpState.get_y() and valeState[1][1].get_direction() == tmpState.get_direction(): break index += 1 goalActionsList.append(self.__actionsCollection[index][1][0]) # get action tmpState = self.__actionsCollection[index][0] # get state - and next we will find key equal it's value self.__actionsCollection = list(reversed(goalActionsList)) self.__actionsCollection = [action for action in self.__actionsCollection if action is not None] # remove first None action else: raise Exception("WIN!!! :D") elif len(self.__actionsCollection) == 0: # jeśli jest wyznaczona skrzynka - cel & nie ma akcji do wykonania - cel osiągnięty self.hasgoalchest = False elif len(self.__actionsCollection) != 0: # jeśli jest wyznaczona skrzynka - cel & są akcje do wykoannia to je realizuje actionIndex = self.__actionsCollection[0] # ignore -1 because it's None self.__actionsCollection.remove(actionIndex) newState = actionsInterpreter(actionIndex, AgentState(self.pos[0], self.pos[1], self.direction), self.directions) self.model.grid.move_agent(self, (newState.get_x(), newState.get_y())) self.direction = newState.get_direction() print("moved to - ", [newState.get_x(), newState.get_y()]) cellmates = self.model.grid.get_cell_list_contents([self.pos]) if len(cellmates) > 1: if isinstance(cellmates[0], Box): self.openChest(cellmates[0]) else: opponent = cellmates[0] print("Fighting") self.fightOrFlight(opponent) # print("HP: " + str(self.health) + " / " + str(self.maxHealth)) print("Gold: " + str(self.gold)) else: print("HP: 0 / " + str(self.maxHealth))