from mesa import Agent import random def dice(number): return random.randint(1, number) class Wall(Agent): def __init__(self, unique_id, model): super().__init__(unique_id, model) def step(self): pass class Box(Agent): def __init__(self, unique_id, model): super().__init__(unique_id, model) self.gold = 3 * dice(6) self.isBox = True self.isCreature = False def step(self): pass class Weapon(): def __init__(self, name, type, damage): self.name = name self.type = type self.damage = damage class Armor(): def __init__(self, name, defence, mp): self.name = name self.defence = defence self.mag_protection = mp class Creature(Agent): def __init__(self, unique_id, model, n, s, a, w, maxhp, hp, weap, arm, g): super().__init__(unique_id, model) 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.armor = arm self.isBox = False self.isCreature = True 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.weapon1.damage - opponent.armor.defence > 0): opponent.health = opponent.health - (damage + self.weapon1.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.weapon1.damage - opponent.armor.mag_protection > 0): opponent.health = opponent.health - (damage + self.weapon1.damage - opponent.armor.mag_protection) def defaultAttack(self, opponent): if self.weapon1.type == "Meele": self.meleeAttack(opponent) elif self.weapon1.type == "Range": self.rangeAttack(opponent) else: self.magicAttack(opponent) 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 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) 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 # 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 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 False def step(self): if self.health > 0: self.moveFwd() self.rotate(False) print(self.findShortestPathToTarget()) 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))