2021-03-30 14:17:54 +02:00
|
|
|
from mesa import Agent
|
2021-04-13 23:08:57 +02:00
|
|
|
from othercharacters import dice, Box, Creature, Armor, Weapon
|
2021-04-12 23:42:09 +02:00
|
|
|
|
2021-03-29 14:46:05 +02:00
|
|
|
class Player(Creature):
|
|
|
|
def __init__(self, unique_id, model, n, s, a, w, maxhp, hp, weap, arm, g, w2, w3):
|
2021-03-30 14:17:54 +02:00
|
|
|
super().__init__(unique_id, model, n, s, a, w, maxhp, hp, weap, arm, g)
|
2021-03-29 14:46:05 +02:00
|
|
|
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
|
2021-03-30 14:17:54 +02:00
|
|
|
self.isBox = False
|
|
|
|
self.isCreature = False
|
2021-04-12 23:42:09 +02:00
|
|
|
self.directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
|
|
|
|
self.direction = 0
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue=[]
|
2021-04-14 02:48:54 +02:00
|
|
|
self.hasgoalchest=False
|
|
|
|
self.openedchests=0
|
2021-04-12 23:42:09 +02:00
|
|
|
|
|
|
|
def rotate(self, clockwise=True):
|
|
|
|
if clockwise:
|
|
|
|
self.direction = (self.direction + 1) % 4
|
|
|
|
else:
|
|
|
|
self.direction = (self.direction + 3) % 4
|
2021-03-29 14:46:05 +02:00
|
|
|
|
2021-04-12 23:42:09 +02:00
|
|
|
def moveFwd(self):
|
|
|
|
possible_steps = self.model.grid.get_neighborhood(
|
|
|
|
self.pos,
|
|
|
|
moore=False,
|
|
|
|
include_center=False)
|
2021-04-13 15:41:09 +02:00
|
|
|
new_position = (self.pos[0] + self.directions[self.direction][0],
|
|
|
|
self.pos[1] + self.directions[self.direction][1])
|
2021-04-12 23:42:09 +02:00
|
|
|
if new_position in possible_steps:
|
|
|
|
self.model.grid.move_agent(self, new_position)
|
2021-04-14 01:30:57 +02:00
|
|
|
print("moved to ", new_position)
|
2021-04-13 23:08:57 +02:00
|
|
|
# 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)
|
2021-03-29 14:46:05 +02:00
|
|
|
|
2021-04-12 23:42:09 +02:00
|
|
|
def meleeAttack(self, opponent):
|
2021-03-29 14:46:05 +02:00
|
|
|
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)
|
|
|
|
|
2021-04-12 23:42:09 +02:00
|
|
|
def rangeAttack(self, opponent):
|
2021-03-29 14:46:05 +02:00
|
|
|
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)
|
2021-04-12 23:42:09 +02:00
|
|
|
|
|
|
|
def magicAttack(self, opponent):
|
2021-03-29 14:46:05 +02:00
|
|
|
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)
|
2021-04-12 23:42:09 +02:00
|
|
|
|
2021-03-29 14:46:05 +02:00
|
|
|
def fightOrFlight(self, opponent):
|
|
|
|
combat = True
|
|
|
|
while combat:
|
|
|
|
choice = dice(4)
|
2021-03-30 14:17:54 +02:00
|
|
|
print("dice rolled:", choice)
|
2021-03-29 14:46:05 +02:00
|
|
|
if choice == 1:
|
|
|
|
running_speed = self.agility + dice(6)
|
|
|
|
opponent_speed = opponent.agility + dice(6)
|
|
|
|
if running_speed > opponent_speed:
|
|
|
|
combat = False
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Player ran away")
|
2021-03-29 14:46:05 +02:00
|
|
|
self.step()
|
|
|
|
else:
|
|
|
|
opponent.defaultAttack(self)
|
|
|
|
if self.health <= 0:
|
|
|
|
combat = False
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Player died :/")
|
2021-03-29 14:46:05 +02:00
|
|
|
elif choice == 2:
|
|
|
|
self.meleeAttack(opponent)
|
|
|
|
if opponent.health > 0:
|
|
|
|
opponent.defaultAttack(self)
|
|
|
|
if self.health <= 0:
|
|
|
|
combat = False
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Player died :/")
|
2021-03-29 14:46:05 +02:00
|
|
|
else:
|
|
|
|
combat = False
|
|
|
|
self.gold = self.gold + opponent.gold
|
|
|
|
opponent.gold = 0
|
|
|
|
opponent.model.grid.remove_agent(opponent)
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Fight won")
|
2021-03-29 14:46:05 +02:00
|
|
|
elif choice == 3:
|
|
|
|
self.rangeAttack(opponent)
|
|
|
|
if opponent.health > 0:
|
|
|
|
opponent.defaultAttack(self)
|
|
|
|
if self.health <= 0:
|
|
|
|
combat = False
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Player died :/")
|
2021-03-29 14:46:05 +02:00
|
|
|
else:
|
|
|
|
combat = False
|
|
|
|
self.gold = self.gold + opponent.gold
|
|
|
|
opponent.gold = 0
|
|
|
|
opponent.model.grid.remove_agent(opponent)
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Fight won")
|
2021-03-29 14:46:05 +02:00
|
|
|
else:
|
2021-03-30 14:17:54 +02:00
|
|
|
self.magicAttack(opponent)
|
2021-03-29 14:46:05 +02:00
|
|
|
if opponent.health > 0:
|
|
|
|
opponent.defaultAttack(self)
|
|
|
|
if self.health <= 0:
|
|
|
|
combat = False
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Player died :/")
|
2021-03-29 14:46:05 +02:00
|
|
|
else:
|
|
|
|
combat = False
|
|
|
|
self.gold = self.gold + opponent.gold
|
|
|
|
opponent.gold = 0
|
|
|
|
opponent.model.grid.remove_agent(opponent)
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Fight won")
|
2021-04-12 23:42:09 +02:00
|
|
|
|
|
|
|
def openChest(self, chest):
|
2021-03-29 14:46:05 +02:00
|
|
|
self.gold = self.gold + chest.gold
|
2021-03-30 14:17:54 +02:00
|
|
|
print("Chest opened. Gold inside:", chest.gold)
|
2021-03-29 14:46:05 +02:00
|
|
|
chest.gold = 0
|
2021-04-14 02:48:54 +02:00
|
|
|
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
|
2021-03-30 14:17:54 +02:00
|
|
|
# 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
|
2021-04-12 23:42:09 +02:00
|
|
|
|
2021-04-13 15:41:09 +02:00
|
|
|
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
|
2021-04-14 02:48:54 +02:00
|
|
|
self.hasgoalchest=True
|
2021-04-13 15:41:09 +02:00
|
|
|
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
|
|
|
|
|
2021-04-14 02:48:54 +02:00
|
|
|
return "no chests left"
|
2021-04-13 15:41:09 +02:00
|
|
|
|
2021-04-13 23:08:57 +02:00
|
|
|
# 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
|
|
|
|
|
2021-04-14 01:30:57 +02:00
|
|
|
def actionPlanner(self, cell_from, cell_to):
|
|
|
|
x0 = cell_from[0]
|
|
|
|
y0 = cell_from[1]
|
|
|
|
x = cell_to[0]
|
|
|
|
y = cell_to[1]
|
2021-04-13 23:08:57 +02:00
|
|
|
if (x > x0):
|
|
|
|
if (self.direction == 1):
|
|
|
|
self.queue.append("fwd")
|
|
|
|
elif (self.direction == 0):
|
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
|
|
|
elif (self.direction == 2):
|
|
|
|
self.queue.append("tl")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(False)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
|
|
|
else:
|
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.insert("fwd")
|
|
|
|
elif (x < x0):
|
|
|
|
if (self.direction == 3):
|
|
|
|
self.queue.append("fwd")
|
|
|
|
elif (self.direction == 0):
|
|
|
|
self.queue.append("tl")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(False)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
|
|
|
elif (self.direction == 2):
|
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
|
|
|
else:
|
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
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)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
|
|
|
else:
|
2021-04-14 01:30:57 +02:00
|
|
|
self.queue.append("tr")
|
|
|
|
self.rotate(True)
|
|
|
|
self.queue.append("tr")
|
|
|
|
self.rotate(True)
|
|
|
|
self.queue.append("fwd")
|
|
|
|
elif (y < y0):
|
2021-04-13 23:08:57 +02:00
|
|
|
if (self.direction == 2):
|
|
|
|
self.queue.append("fwd")
|
|
|
|
elif (self.direction == 3):
|
|
|
|
self.queue.append("tl")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(False)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
|
|
|
elif (self.direction == 1):
|
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
|
|
|
else:
|
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("tr")
|
2021-04-14 01:30:57 +02:00
|
|
|
self.rotate(True)
|
2021-04-13 23:08:57 +02:00
|
|
|
self.queue.append("fwd")
|
2021-04-14 01:30:57 +02:00
|
|
|
elif (len(self.path)==0):
|
|
|
|
self.queue.append("op")
|
2021-04-13 15:41:09 +02:00
|
|
|
|
2021-03-29 14:46:05 +02:00
|
|
|
def step(self):
|
|
|
|
if self.health > 0:
|
2021-04-14 01:30:57 +02:00
|
|
|
print("position: ", self.pos)
|
2021-04-14 01:54:52 +02:00
|
|
|
#print("direction: ", self.direction)
|
2021-04-14 02:48:54 +02:00
|
|
|
if not self.hasgoalchest: #jeśli nie ma wyznaczonej skrzynki do której idzie to robi bfs żeby ją wyznaczyć
|
2021-04-13 23:08:57 +02:00
|
|
|
self.path=self.findShortestPathToTarget()
|
2021-04-14 02:48:54 +02:00
|
|
|
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
|
2021-04-14 01:30:57 +02:00
|
|
|
while len(self.queue)!=0:
|
2021-04-13 23:08:57 +02:00
|
|
|
self.action=self.queue.pop(0)
|
|
|
|
if self.action=="tr":
|
|
|
|
self.rotate(True)
|
2021-04-14 01:30:57 +02:00
|
|
|
print("tr'd, direction: ", self.direction)
|
|
|
|
break
|
2021-04-13 23:08:57 +02:00
|
|
|
elif self.action=="tl":
|
|
|
|
self.rotate(False)
|
2021-04-14 01:30:57 +02:00
|
|
|
print("tl'd, direction: ", self.direction)
|
|
|
|
break
|
2021-04-13 23:08:57 +02:00
|
|
|
elif self.action=="fwd":
|
|
|
|
self.moveFwd()
|
2021-04-14 01:30:57 +02:00
|
|
|
break
|
2021-03-29 14:46:05 +02:00
|
|
|
cellmates = self.model.grid.get_cell_list_contents([self.pos])
|
|
|
|
if len(cellmates) > 1:
|
2021-04-12 23:42:09 +02:00
|
|
|
if isinstance(cellmates[0], Box):
|
2021-03-30 14:17:54 +02:00
|
|
|
self.openChest(cellmates[0])
|
2021-03-29 14:46:05 +02:00
|
|
|
else:
|
2021-03-30 14:17:54 +02:00
|
|
|
opponent = cellmates[0]
|
|
|
|
print("Fighting")
|
|
|
|
self.fightOrFlight(opponent)
|
2021-04-14 01:54:52 +02:00
|
|
|
# print("HP: " + str(self.health) + " / " + str(self.maxHealth))
|
2021-04-12 23:42:09 +02:00
|
|
|
print("Gold: " + str(self.gold))
|
2021-03-29 14:46:05 +02:00
|
|
|
else:
|
2021-04-12 23:42:09 +02:00
|
|
|
print("HP: 0 / " + str(self.maxHealth))
|