from mesa import Agent from othercharacters import dice, Box, Creature, Armor, Weapon class Player(Creature): def __init__(self, unique_id, model, n, s, a, w, maxhp, hp, weap, arm, g, w2, w3): 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 = [[0, 1], [1, 0], [0, -1], [-1, 0]] self.direction = 0 self.queue=[] self.hasgoalchest=False self.openedchests=0 def rotate(self, clockwise=True): if clockwise: self.direction = (self.direction + 1) % 4 else: self.direction = (self.direction + 3) % 4 def moveFwd(self): possible_steps = self.model.grid.get_neighborhood( self.pos, moore=False, include_center=False) new_position = (self.pos[0] + self.directions[self.direction][0], self.pos[1] + self.directions[self.direction][1]) if new_position in possible_steps: self.model.grid.move_agent(self, new_position) print("moved to ", new_position) # def move(self): # OLD # possible_steps = self.model.grid.get_neighborhood( # self.pos, # moore=True, # include_center=False) # new_position = self.random.choice(possible_steps) # self.model.grid.move_agent(self, new_position) 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 # 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 def findShortestPathToTarget(self): visited = [] precedessors = {} queue = [self.pos] found_target = False while queue: cur_pos = queue.pop(0) #check for target cell_contents = self.model.grid.get_cell_list_contents([cur_pos]) if cell_contents and any([isinstance(thing, Box) for thing in cell_contents]): found_target = cur_pos self.hasgoalchest=True break #enqueue safe unvisited neighbours neighbours = self.model.grid.get_neighborhood( cur_pos, moore=False, include_center=False) for cell in neighbours: #if cell hasn't been visited and the contents don't include creatures if cell not in visited and not any([isinstance(thing, Creature) for thing in self.model.grid.get_cell_list_contents([cell])]): queue.append(cell) precedessors[cell] = cur_pos visited.append(cur_pos) if found_target: path = [found_target] while True: if path[0] == self.pos: break precedessor = precedessors[path[0]] path.insert(0, precedessor) return path return "no chests left" # Funkcja konwertujaca wspolrzedne nastepnego pola do odwiedzenia # na kolejke akcji do wykonania # tl - turn left, tr - turn right, fwd - forward, op - open # queue - kolejka akcji do zrobienia, pole klasy Player # path - kolejka pol do odwiedzenia, pole klasy Player # pole to element wziety z kolejki path def actionPlanner(self, cell_from, cell_to): x0 = cell_from[0] y0 = cell_from[1] x = cell_to[0] y = cell_to[1] if (x > x0): if (self.direction == 1): self.queue.append("fwd") elif (self.direction == 0): self.queue.append("tr") self.rotate(True) self.queue.append("fwd") elif (self.direction == 2): self.queue.append("tl") self.rotate(False) self.queue.append("fwd") else: self.queue.append("tr") self.rotate(True) self.queue.append("tr") self.rotate(True) self.queue.insert("fwd") elif (x < x0): if (self.direction == 3): self.queue.append("fwd") elif (self.direction == 0): self.queue.append("tl") self.rotate(False) self.queue.append("fwd") elif (self.direction == 2): self.queue.append("tr") self.rotate(True) self.queue.append("fwd") else: self.queue.append("tr") self.rotate(True) self.queue.append("tr") self.rotate(True) self.queue.append("fwd") elif (y > y0): if (self.direction == 0): self.queue.append("fwd") elif (self.direction == 1): self.queue.append("tl") self.rotate(False) self.queue.append("fwd") elif (self.direction == 3): self.queue.append("tr") self.rotate(True) self.queue.append("fwd") else: self.queue.append("tr") self.rotate(True) self.queue.append("tr") self.rotate(True) self.queue.append("fwd") elif (y < y0): if (self.direction == 2): self.queue.append("fwd") elif (self.direction == 3): self.queue.append("tl") self.rotate(False) self.queue.append("fwd") elif (self.direction == 1): self.queue.append("tr") self.rotate(True) self.queue.append("fwd") else: self.queue.append("tr") self.rotate(True) self.queue.append("tr") self.rotate(True) self.queue.append("fwd") elif (len(self.path)==0): self.queue.append("op") 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 self.path=="no chests left": print("no chests left, life has lost meaning") else: print("the player should follow this path:", self.path) for i in range(len(self.path)-1): #iteruje po kolejnych krotkach ze współrzędnymi pól #actionPlanner ma się wykonać i-1 razy, bo dla ostatniego pola już nie self.actionPlanner(self.path[i], self.path[i+1]) #dla każdego pola dodaje do kolejki kilka akcji potrzebnych żeby do niego dojść print(self.queue) self.direction=0 # bo po obrotach w wyznaczaniu ścieżki trzeba wrócić do orientacji takiej, jaka była na starcie wyznaczania #to znaczy, że po otwarciu skrzynki też się zeruje żeby zacząć wyznaczanie i chodzenie od takiej samej while len(self.queue)!=0: self.action=self.queue.pop(0) if self.action=="tr": self.rotate(True) print("tr'd, direction: ", self.direction) break elif self.action=="tl": self.rotate(False) print("tl'd, direction: ", self.direction) break elif self.action=="fwd": self.moveFwd() break 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))