rpg-szi/hero.py

322 lines
13 KiB
Python
Raw Normal View History

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
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, listOfChests):
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
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 = []
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)
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
print("Player ran away")
2021-03-29 14:46:05 +02:00
self.step()
else:
opponent.defaultAttack(self)
if self.health <= 0:
combat = False
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
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)
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
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)
print("Fight won")
2021-03-29 14:46:05 +02:00
else:
self.magicAttack(opponent)
2021-03-29 14:46:05 +02:00
if opponent.health > 0:
opponent.defaultAttack(self)
if self.health <= 0:
combat = False
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)
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
print("Chest opened. Gold inside:", chest.gold)
2021-03-29 14:46:05 +02:00
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
2021-04-12 23:42:09 +02:00
#- - - - 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
2021-03-29 14:46:05 +02:00
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()])
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):
self.openChest(cellmates[0])
2021-03-29 14:46:05 +02:00
else:
opponent = cellmates[0]
print("Fighting")
self.fightOrFlight(opponent)
# 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))