2021-04-25 22:48:55 +02:00
import random
2021-03-30 14:17:54 +02:00
from mesa import Agent
2021-04-25 22:48:55 +02:00
2021-04-13 23:08:57 +02:00
from othercharacters import dice , Box , Creature , Armor , Weapon
2021-04-25 22:48:55 +02:00
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 ) :
2021-04-25 22:48:55 +02:00
def __init__ ( self , unique_id , model , n , s , a , w , maxhp , hp , weap , arm , g , w2 , w3 , listOfChests ) :
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-25 22:48:55 +02:00
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 )
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-25 22:48:55 +02:00
self . openedchests + = 1
self . hasgoalchest = False
2021-04-14 02:48:54 +02:00
chest . model . grid . remove_agent ( chest )
2021-04-25 22:48:55 +02:00
#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!!!
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-25 22:48:55 +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 ] )
2021-04-13 23:08:57 +02:00
else :
2021-04-25 22:48:55 +02:00
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-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-25 22:48:55 +02:00
# 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
2021-04-14 02:48:54 +02:00
else :
2021-04-25 22:48:55 +02:00
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 ) :
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-25 22:48:55 +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 ) )