Merge branch 'joarad'
This commit is contained in:
commit
1494a717f6
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/.idea
|
69
actions.py
69
actions.py
@ -1,69 +0,0 @@
|
||||
#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,pole):
|
||||
x0 = self.pos[0]
|
||||
y0 = self.pos[1]
|
||||
x = pole[0]
|
||||
y = pole[1]
|
||||
if (x > x0):
|
||||
if (self.direction == 1):
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 0):
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 2):
|
||||
self.queue.insert("tl")
|
||||
self.queue.insert("fwd")
|
||||
else:
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
elif (x < x0):
|
||||
if (self.direction == 3):
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 0):
|
||||
self.queue.insert("tl")
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 2):
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
else:
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
else:
|
||||
if (y > y0):
|
||||
if (self.direction == 0):
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 1):
|
||||
self.queue.insert("tl")
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 3):
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
else:
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
else:
|
||||
if (self.direction == 2):
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 3):
|
||||
self.queue.insert("tl")
|
||||
self.queue.insert("fwd")
|
||||
elif (self.direction == 1):
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
else:
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("tr")
|
||||
self.queue.insert("fwd")
|
||||
if (self.path.empty()):
|
||||
self.queue.insert("op")
|
319
hero.py
319
hero.py
@ -1,319 +0,0 @@
|
||||
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))
|
59
model.py
59
model.py
@ -1,59 +0,0 @@
|
||||
from mesa import Model
|
||||
from hero import Player
|
||||
from othercharacters import Creature, Box, Wall, dice
|
||||
from armory import WM1, A1, WR1, S1, WM2, A2
|
||||
from mesa.time import RandomActivation
|
||||
from mesa.space import MultiGrid
|
||||
# from mesa.datacollection import DataCollector
|
||||
import random
|
||||
|
||||
x = 10
|
||||
y = 10
|
||||
step_counter = 0
|
||||
boxes_number = 4
|
||||
creatures_number = 5
|
||||
|
||||
|
||||
class GameMap(Model):
|
||||
def __init__(self, x, y):
|
||||
self.grid = MultiGrid(x, y, False)
|
||||
self.schedule = RandomActivation(self) # agenci losowo po kolei wykonują swoje akcje
|
||||
# to jest potrzebne przy założeniu, że potwory chodzą?
|
||||
self.boxes_number = boxes_number
|
||||
self.creatures_number = creatures_number
|
||||
self.running = True
|
||||
# player = Player(1000, self)
|
||||
player = Player(1000, self, "Janusz", 3, 3, 3, 20, 20, WM1, A1, 0, WR1, S1)
|
||||
self.schedule.add(player)
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
self.grid.place_agent(player, (x, y))
|
||||
|
||||
for i in range(self.boxes_number):
|
||||
box = Box(i, self)
|
||||
# self.schedule.add(box)
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
if self.grid.is_cell_empty((x, y)):
|
||||
self.grid.place_agent(box, (x, y))
|
||||
self.schedule.add(box)
|
||||
else:
|
||||
pass
|
||||
|
||||
for i in range(self.boxes_number,
|
||||
self.boxes_number + self.creatures_number): # taki range, żeby każdy agent miał poprawne unique_id
|
||||
# creature = Creature(i, self)
|
||||
creature = Creature(i, self, "Goblin", 1, 1, 1, 1, 1, WM2, A2, dice(6))
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
if self.grid.is_cell_empty((x, y)):
|
||||
self.grid.place_agent(creature, (x, y))
|
||||
self.schedule.add(creature)
|
||||
else:
|
||||
pass
|
||||
|
||||
# self.datacollector=DataCollector #informacje o stanie planszy, pozycja agenta
|
||||
|
||||
def step(self):
|
||||
self.schedule.step()
|
||||
# self.datacollector.collect(self) #na razie niepotrzebne
|
BIN
nn_model.h5
Normal file
BIN
nn_model.h5
Normal file
Binary file not shown.
@ -1,86 +0,0 @@
|
||||
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)
|
||||
|
Before Width: | Height: | Size: 208 B After Width: | Height: | Size: 208 B |
BIN
sprites/heroN.png
Normal file
BIN
sprites/heroN.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 292 B |
BIN
sprites/heroS.png
Normal file
BIN
sprites/heroS.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 286 B |
BIN
sprites/heroW.png
Normal file
BIN
sprites/heroW.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 293 B |
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
BIN
src/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
src/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/direction.cpython-39.pyc
Normal file
BIN
src/__pycache__/direction.cpython-39.pyc
Normal file
Binary file not shown.
4
src/agent/__init__.py
Normal file
4
src/agent/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from .hero import Player
|
||||
from .map.gameMap import GameMap
|
||||
from .model import *
|
||||
from .state import AgentState
|
BIN
src/agent/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
src/agent/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
src/agent/__pycache__/hero.cpython-39.pyc
Normal file
BIN
src/agent/__pycache__/hero.cpython-39.pyc
Normal file
Binary file not shown.
215
src/agent/ga_chromosome.py
Normal file
215
src/agent/ga_chromosome.py
Normal file
@ -0,0 +1,215 @@
|
||||
import numpy.random
|
||||
import random
|
||||
import pandas as pd
|
||||
import os
|
||||
import rpy2.robjects as robjects
|
||||
from rpy2.robjects.packages import importr
|
||||
from rpy2.robjects import pandas2ri
|
||||
from rpy2.robjects.conversion import localconverter
|
||||
from rpy2.robjects.packages import importr
|
||||
from src.nominalize import nominalize
|
||||
from src.decisiontree import create_model
|
||||
MAX_COMBAT_TIME = 20
|
||||
attack_types=["MELEE", "RANGED","MAGIC"]
|
||||
class EnemyStats:
|
||||
def __init__(self):
|
||||
self.strength = random.randint(1, 7)
|
||||
self.agility = random.randint(1, 7)
|
||||
self.wisdom = random.randint(1, 7)
|
||||
self.max_health = random.randint(5, 30)
|
||||
self.health=self.max_health
|
||||
self.melee_wep_damage = 1
|
||||
self.ranged_wep_damage = 1
|
||||
self.magic_wep_damage = 2
|
||||
self.armor_defence = 0
|
||||
self.armor_magic_protection = 1
|
||||
self.attack_type=random.choice(attack_types)
|
||||
|
||||
def meleeAttack(self, opponent):
|
||||
attackValue = self.strength + random.randint(1, 6)
|
||||
defenseValue = opponent.strength + opponent.armor_defence
|
||||
damage = attackValue - defenseValue
|
||||
if damage > 0:
|
||||
opponent.health -= (damage + self.melee_wep_damage)
|
||||
|
||||
def rangeAttack(self, opponent):
|
||||
attackValue = self.agility + random.randint(1, 6)
|
||||
defenseValue = opponent.agility
|
||||
damage = attackValue - defenseValue
|
||||
if (damage > 0) and (damage + self.ranged_wep_damage - opponent.armor_defence > 0):
|
||||
opponent.health -= (damage + self.ranged_wep_damage - opponent.armor_defence)
|
||||
|
||||
def magicAttack(self, opponent):
|
||||
attackValue = self.wisdom + random.randint(1, 6)
|
||||
defenseValue = opponent.wisdom
|
||||
damage = attackValue - defenseValue
|
||||
if (damage > 0) and (damage + self.magic_wep_damage - opponent.armor_magic_protection > 0):
|
||||
opponent.health -= (damage + self.magic_wep_damage - opponent.armor_magic_protection)
|
||||
|
||||
def reset(self):
|
||||
self.health = self.max_health
|
||||
|
||||
def try_combat(my_seed, p, e, player_att_type, enemy_att_type):
|
||||
random.seed(my_seed)
|
||||
current_iteration = 0
|
||||
while True:
|
||||
if player_att_type == 0:
|
||||
p.meleeAttack(e)
|
||||
elif player_att_type == 1:
|
||||
p.rangeAttack(e)
|
||||
else:
|
||||
p.magicAttack(e)
|
||||
|
||||
if e.health<=0:
|
||||
return p.health
|
||||
|
||||
if enemy_att_type == 0:
|
||||
e.meleeAttack(p)
|
||||
elif enemy_att_type == 1:
|
||||
e.rangeAttack(p)
|
||||
else:
|
||||
e.magicAttack(p)
|
||||
|
||||
if p.health<=0:
|
||||
return 0
|
||||
|
||||
current_iteration += 1
|
||||
if current_iteration >= MAX_COMBAT_TIME:
|
||||
return 0
|
||||
p.reset()
|
||||
e.reset()
|
||||
|
||||
class PlayerStats(EnemyStats):
|
||||
def __init__(self, s, a, w):
|
||||
self.strength = 1+s
|
||||
self.agility = 1+a
|
||||
self.wisdom = 1+w
|
||||
self.max_health = 50
|
||||
self.health = 50
|
||||
self.melee_wep_damage = 1
|
||||
self.ranged_wep_damage = 1
|
||||
self.magic_wep_damage = 2
|
||||
self.armor_defence = 0
|
||||
self.armor_magic_protection = 0
|
||||
|
||||
def predict_strategy(self, opponent):
|
||||
testcase = pd.DataFrame({'p_strength': nominalize(self.strength,7),
|
||||
'p_agility':nominalize(self.agility, 7),
|
||||
'p_wisdom':nominalize(self.wisdom,7),
|
||||
'p_health':nominalize(self.health,50),
|
||||
'p_melee_damage':nominalize(self.melee_wep_damage, 10),
|
||||
'p_ranged_damage':nominalize(self.ranged_wep_damage,10),
|
||||
'p_magic_damage':nominalize(self.magic_wep_damage,10),
|
||||
'p_armor_defence':nominalize(self.armor_defence,5),
|
||||
'p_armor_magic_protection':nominalize(self.armor_magic_protection,5),
|
||||
'e_strength':nominalize(opponent.strength, 10),
|
||||
'e_agility':nominalize(opponent.agility, 10),
|
||||
'e_wisdom':nominalize(opponent.wisdom,10),
|
||||
'e_health':nominalize(opponent.health, 50),
|
||||
'e_damage':nominalize(opponent.melee_wep_damage,10),
|
||||
'e_armor_defence':nominalize(opponent.armor_defence, 5),
|
||||
'e_armor_magic_protection':nominalize(opponent.armor_magic_protection, 5),
|
||||
'e_attack_type':opponent.attack_type.upper(),
|
||||
'strategy':"PASS"}, index=[1])
|
||||
with localconverter(robjects.default_converter + pandas2ri.converter):
|
||||
r_dataframe = robjects.conversion.py2rpy(testcase)
|
||||
robjects.globalenv['r_dataframe']=r_dataframe
|
||||
result=robjects.r('predict(fights.id3, r_dataframe)')
|
||||
return result[0]
|
||||
|
||||
def fitness_function(chromosome):
|
||||
s=chromosome.count(1)
|
||||
a=chromosome.count(2)
|
||||
w=chromosome.count(3)
|
||||
p=PlayerStats(s, a, w)
|
||||
# wins=[0,0,0]
|
||||
# current_seed=os.urandom(16)
|
||||
# for i in range(3):
|
||||
# random.seed(current_seed)
|
||||
# while p.health>0:
|
||||
# e=EnemyStats()
|
||||
# try_combat(current_seed, p, e, i, e.attack_type) #walka iles razy
|
||||
# if p.health>0:
|
||||
# wins[i]+=1
|
||||
# p.reset()
|
||||
# return max(wins)
|
||||
wins=0
|
||||
while p.health > 0:
|
||||
e=EnemyStats()
|
||||
player_attack=p.predict_strategy(e)
|
||||
try_combat(os.urandom(16), p, e, attack_types.index(player_attack), attack_types.index(e.attack_type)) #walka iles razy
|
||||
if p.health>0:
|
||||
wins+=1
|
||||
return wins
|
||||
|
||||
# tournament selection
|
||||
def selection(pop, scores, k=3):
|
||||
# first random selection
|
||||
selection_ix = numpy.random.randint(len(pop))
|
||||
for ix in numpy.random.randint(0, len(pop), k-1):
|
||||
# check if better (e.g. perform a tournament)
|
||||
if scores[ix] > scores[selection_ix]:
|
||||
selection_ix = ix
|
||||
return pop[selection_ix]
|
||||
|
||||
# crossover two parents to create two children
|
||||
def crossover(p1, p2, r_cross):
|
||||
# children are copies of parents by default
|
||||
c1, c2 = p1.copy(), p2.copy()
|
||||
# check for recombination
|
||||
if numpy.random.rand() < r_cross:
|
||||
# select crossover point that is not on the end of the string
|
||||
pt = numpy.random.randint(1, len(p1)-2)
|
||||
# perform crossover
|
||||
c1 = p1[:pt] + p2[pt:]
|
||||
c2 = p2[:pt] + p1[pt:]
|
||||
return [c1, c2]
|
||||
# mutation operator
|
||||
def mutation(bitstring, r_mut):
|
||||
for i in range(len(bitstring)):
|
||||
# check for a mutation
|
||||
if numpy.random.rand() < r_mut:
|
||||
# flip the bit
|
||||
bitstring[i] = random.randint(1,4)
|
||||
# genetic algorithm
|
||||
|
||||
def genetic_algorithm(objective, n_bits, n_iter, n_pop, r_cross, r_mut):
|
||||
# initial population of random bitstring
|
||||
pop = [numpy.random.randint(1, 3, n_bits).tolist() for _ in range(n_pop)] # tworzy sie lista n_pop list szesciocyfrowych
|
||||
# keep track of best solution
|
||||
best, best_eval = 0, objective(pop[0])
|
||||
# enumerate generations
|
||||
for gen in range(n_iter):
|
||||
# evaluate all candidates in the population
|
||||
scores = [objective(c) for c in pop]
|
||||
# check for new best solution
|
||||
for i in range(n_pop):
|
||||
if scores[i] > best_eval:
|
||||
best, best_eval = pop[i], scores[i]
|
||||
print(">%d, new best f(%s) = %d" % (gen, pop[i], scores[i]))
|
||||
# select parents
|
||||
selected = [selection(pop, scores) for _ in range(n_pop)]
|
||||
# create the next generation
|
||||
children = list()
|
||||
for i in range(0, n_pop, 2):
|
||||
# get selected parents in pairs
|
||||
p1, p2 = selected[i], selected[i+1]
|
||||
# crossover and mutation
|
||||
for c in crossover(p1, p2, r_cross):
|
||||
# mutation
|
||||
mutation(c, r_mut)
|
||||
# store for next generation
|
||||
children.append(c)
|
||||
# replace population
|
||||
pop = children
|
||||
return [best, best_eval]
|
||||
# define the total iterations
|
||||
n_iter = 10
|
||||
# bits
|
||||
n_bits = 6
|
||||
# define the population size
|
||||
n_pop = 20
|
||||
# crossover rate
|
||||
r_cross = 0.9
|
||||
# mutation rate
|
||||
r_mut = 0.05
|
350
src/agent/hero.py
Normal file
350
src/agent/hero.py
Normal file
@ -0,0 +1,350 @@
|
||||
import random
|
||||
import pandas as pd
|
||||
import rpy2.robjects as robjects
|
||||
from rpy2.robjects.packages import importr
|
||||
from rpy2.robjects import pandas2ri
|
||||
from rpy2.robjects.conversion import localconverter
|
||||
from rpy2.robjects.packages import importr
|
||||
from src.agent.model import *
|
||||
from src.agent.state import AgentState
|
||||
from src.direction import Direction
|
||||
from src.items.armory import WM9
|
||||
from src.treesearch.actionsInterpreter import ActionInterpreter
|
||||
from src.agent.model.dice.dice import roll_the_dice
|
||||
from src.treesearch.bfs import BFS
|
||||
from src.nominalize import nominalize
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import os
|
||||
import PIL
|
||||
import tensorflow as tf
|
||||
|
||||
from tensorflow import keras
|
||||
from tensorflow.keras import layers
|
||||
from tensorflow.keras.models import Sequential
|
||||
|
||||
import pathlib
|
||||
|
||||
class Player(Creature):
|
||||
def __init__(self, unique_id, model, n, s, a, w, max_hp, hp, weapon, arm, g, w2, w3, list_of_chests):
|
||||
super().__init__(unique_id, model, n, s, a, w, max_hp, hp, weapon, arm, g)
|
||||
self.name = n
|
||||
self.strength = s
|
||||
self.agility = a
|
||||
self.wisdom = w
|
||||
self.maxHealth = max_hp
|
||||
self.health = hp
|
||||
self.gold = g
|
||||
self.weapon1 = weapon
|
||||
self.weapon2 = w2
|
||||
self.weapon3 = w3
|
||||
self.armor = arm
|
||||
self.isBox = False
|
||||
self.isCreature = False
|
||||
self.isPlayer=True
|
||||
self.direction = Direction.N
|
||||
self.queue = []
|
||||
self.has_goal_chest = False
|
||||
self.opened_chests = 0
|
||||
self.__listOfChests = list_of_chests
|
||||
self.__actionsCollection = []
|
||||
self.combat=False
|
||||
self.opponent=None
|
||||
self.strategy="PASS"
|
||||
|
||||
def identify_content(self, chest):
|
||||
dataset_url = "https://drive.google.com/uc?export=download&id=1b6w1FbupRmgVC-q9Lpdlg5OBK_gRKEUy"
|
||||
data_dir = tf.keras.utils.get_file(fname='loot', origin=dataset_url, untar=True)
|
||||
data_dir = pathlib.Path(data_dir)
|
||||
|
||||
#image_count = len(list(data_dir.glob('*/*.jpg')))
|
||||
#print(image_count)
|
||||
|
||||
batch_size = 32
|
||||
img_height = 180
|
||||
img_width = 180
|
||||
|
||||
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
|
||||
data_dir,
|
||||
validation_split=0.2,
|
||||
subset="training",
|
||||
seed=123,
|
||||
image_size=(img_height, img_width),
|
||||
batch_size=batch_size)
|
||||
|
||||
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
|
||||
data_dir,
|
||||
validation_split=0.2,
|
||||
subset="validation",
|
||||
seed=123,
|
||||
image_size=(img_height, img_width),
|
||||
batch_size=batch_size)
|
||||
|
||||
class_names = train_ds.class_names
|
||||
#print(class_names)
|
||||
|
||||
normalization_layer = layers.experimental.preprocessing.Rescaling(1. / 255)
|
||||
|
||||
normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
|
||||
image_batch, labels_batch = next(iter(normalized_ds))
|
||||
first_image = image_batch[0]
|
||||
# Notice the pixels values are now in `[0,1]`.
|
||||
#print(np.min(first_image), np.max(first_image))
|
||||
|
||||
#num_classes = 3
|
||||
|
||||
# Recreate the exact same model, including its weights and the optimizer
|
||||
new_model = tf.keras.models.load_model('nn_model.h5')
|
||||
|
||||
# Show the model architecture
|
||||
#new_model.summary()
|
||||
|
||||
# loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
|
||||
# print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))
|
||||
|
||||
object_url = chest.type
|
||||
object_path = tf.keras.utils.get_file(chest.file_name, origin=object_url)
|
||||
|
||||
img = keras.preprocessing.image.load_img(
|
||||
object_path, target_size=(img_height, img_width)
|
||||
)
|
||||
img_array = keras.preprocessing.image.img_to_array(img)
|
||||
img_array = tf.expand_dims(img_array, 0) # Create a batch
|
||||
|
||||
predictions = new_model.predict(img_array)
|
||||
score = tf.nn.softmax(predictions[0])
|
||||
|
||||
print(
|
||||
"This image most likely belongs to {} with a {:.2f} percent confidence."
|
||||
.format(class_names[np.argmax(score)], 100 * np.max(score))
|
||||
)
|
||||
|
||||
return class_names[np.argmax(score)]
|
||||
|
||||
def predict_strategy(self, opponent):
|
||||
testcase = pd.DataFrame({'p_strength': nominalize(self.get_strength(),10),
|
||||
'p_agility':nominalize(self.get_agility(), 10),
|
||||
'p_wisdom':nominalize(self.get_wisdom(),10),
|
||||
'p_health':nominalize(self.get_health(),50),
|
||||
'p_melee_damage':nominalize(self.get_melee_damage(), 10),
|
||||
'p_ranged_damage':nominalize(self.get_ranged_damage(),10),
|
||||
'p_magic_damage':nominalize(self.get_magic_damage(),10),
|
||||
'p_armor_defence':nominalize(self.get_armor_defence(),5),
|
||||
'p_armor_magic_protection':nominalize(self.get_armor_magic_protection(),5),
|
||||
'e_strength':nominalize(opponent.get_strength(), 10),
|
||||
'e_agility':nominalize(opponent.get_agility(), 10),
|
||||
'e_wisdom':nominalize(opponent.get_wisdom(),10),
|
||||
'e_health':nominalize(opponent.get_health(), 50),
|
||||
'e_damage':nominalize(opponent.get_damage(),10),
|
||||
'e_armor_defence':nominalize(opponent.get_armor_defence(), 5),
|
||||
'e_armor_magic_protection':nominalize(opponent.get_armor_magic_protection(), 5),
|
||||
'e_attack_type':opponent.get_attack_type().upper(),
|
||||
'strategy':"PASS"}, index=[1])
|
||||
with localconverter(robjects.default_converter + pandas2ri.converter):
|
||||
r_dataframe = robjects.conversion.py2rpy(testcase)
|
||||
robjects.globalenv['r_dataframe']=r_dataframe
|
||||
print(r_dataframe)
|
||||
result=robjects.r('predict(fights.id3, r_dataframe)')
|
||||
print(result)
|
||||
return result[0]
|
||||
def describe_situation(self, opponent):
|
||||
situation = {# 'p_strength': self.get_strength(),
|
||||
# 'p_agility': self.get_agility(),
|
||||
# 'p_wisdom': self.get_wisdom(),
|
||||
# 'p_health': self.get_health(),
|
||||
# 'p_melee_damage': self.get_melee_damage(),
|
||||
# 'p_ranged_damage': self.get_ranged_damage(),
|
||||
# 'p_magic_damage': self.get_magic_damage(),
|
||||
# 'p_armor_defence': self.get_armor_defence(),
|
||||
# 'p_armor_magic_protection': self.get_armor_magic_protection(),
|
||||
'e_strength': opponent.get_strength(),
|
||||
'e_agility': opponent.get_agility(),
|
||||
'e_wisdom': opponent.get_wisdom(),
|
||||
'e_health': opponent.get_health(),
|
||||
'e_damage': opponent.get_damage(),
|
||||
'e_armor_defence': opponent.get_armor_defence(),
|
||||
'e_armor_magic_protection': opponent.get_armor_magic_protection(),
|
||||
'e_attack_type': opponent.get_attack_type().upper()}
|
||||
return situation
|
||||
|
||||
def melee_attack(self, opponent):
|
||||
attack_value = self.strength + roll_the_dice(6)
|
||||
defense_value = opponent.strength + opponent.armor.get_defence()
|
||||
damage = attack_value - defense_value
|
||||
if damage > 0:
|
||||
opponent.health = opponent.health - (damage + self.weapon1.get_damage())
|
||||
print("damage done by the player: ", damage)
|
||||
|
||||
def range_attack(self, opponent):
|
||||
attack_value = self.agility + roll_the_dice(6)
|
||||
defense_value = opponent.agility
|
||||
damage = attack_value - defense_value
|
||||
if (damage > 0) and (damage + self.weapon2.get_damage() - opponent.armor.get_defence() > 0):
|
||||
opponent.health = opponent.health - (damage + self.weapon2.get_damage() - opponent.armor.get_defence())
|
||||
print("damage done by the player: ", damage)
|
||||
|
||||
def magic_attack(self, opponent):
|
||||
attack_value = self.wisdom + roll_the_dice(6)
|
||||
defense_value = opponent.wisdom
|
||||
damage = attack_value - defense_value
|
||||
if (damage > 0) and (damage + self.weapon3.get_damage() - opponent.armor.get_mag_protection() > 0):
|
||||
opponent.health = opponent.health - (damage + self.weapon3.get_damage() - opponent.armor.get_mag_protection())
|
||||
print("damage done by the player: ", damage)
|
||||
|
||||
def fight_or_flight(self, opponent, strategy):
|
||||
self.combat = True
|
||||
while self.combat:
|
||||
if strategy=="MELEE":
|
||||
self.melee_attack(opponent)
|
||||
if opponent.health > 0:
|
||||
opponent.default_attack(self)
|
||||
if self.health <= 0:
|
||||
self.combat = False
|
||||
print("Player died :/")
|
||||
else:
|
||||
self.combat = False
|
||||
self.gold = self.gold + opponent.gold
|
||||
opponent.gold = 0
|
||||
opponent.model.grid.remove_agent(opponent)
|
||||
print("Fight won")
|
||||
elif strategy=="RANGED":
|
||||
self.range_attack(opponent)
|
||||
if opponent.health > 0:
|
||||
opponent.default_attack(self)
|
||||
if self.health <= 0:
|
||||
self.combat = False
|
||||
print("Player died :/")
|
||||
else:
|
||||
self.combat = False
|
||||
self.gold = self.gold + opponent.gold
|
||||
opponent.gold = 0
|
||||
opponent.model.grid.remove_agent(opponent)
|
||||
print("Fight won")
|
||||
elif strategy=='MAGIC':
|
||||
self.magic_attack(opponent)
|
||||
if opponent.health > 0:
|
||||
opponent.default_attack(self)
|
||||
if self.health <= 0:
|
||||
self.combat = False
|
||||
print("Player died :/")
|
||||
else:
|
||||
self.combat = False
|
||||
self.gold = self.gold + opponent.gold
|
||||
opponent.gold = 0
|
||||
opponent.model.grid.remove_agent(opponent)
|
||||
print("Fight won")
|
||||
else:
|
||||
running_speed = self.agility + roll_the_dice(6)
|
||||
opponent_speed = opponent.agility + roll_the_dice(6)
|
||||
if running_speed > opponent_speed:
|
||||
self.combat = False
|
||||
print("Player ran away")
|
||||
self.step()
|
||||
else:
|
||||
print("Player was too slow to run away")
|
||||
opponent.default_attack(self)
|
||||
if self.health <= 0:
|
||||
self.combat = False
|
||||
print("Player died :/")
|
||||
|
||||
def open_chest(self, chest):
|
||||
if chest.type == 1:
|
||||
ch_gold = 3 * roll_the_dice(6)
|
||||
self.gold = self.gold + ch_gold
|
||||
print("------Chest opened. Gold inside:", ch_gold, "-----")
|
||||
elif chest.type == 2:
|
||||
self.weapon1 = WM9
|
||||
else:
|
||||
self.health = 0
|
||||
# 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.weapon_type == "Melee":
|
||||
# buffer = self.weapon1
|
||||
# self.weapon1 = chest.loot
|
||||
# chest.loot = buffer
|
||||
# elif chest.loot.weapon_type == "Range":
|
||||
# buffer = self.weapon2
|
||||
# self.weapon2 = chest.loot
|
||||
# chest.loot = buffer
|
||||
# elif chest.loot.weapon_type == "Magic":
|
||||
# buffer = self.weapon3
|
||||
# self.weapon3 = chest.loot
|
||||
# chest.loot = buffer
|
||||
|
||||
def step(self):
|
||||
if self.health > 0:
|
||||
print("position: ", self.pos)
|
||||
# print("direction: ", self.direction)
|
||||
if not self.has_goal_chest: # 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
|
||||
random_chest = random.choice(self.__listOfChests)
|
||||
self.__listOfChests.remove(random_chest)
|
||||
self.has_goal_chest = True
|
||||
|
||||
current_state = AgentState(self.pos[0], self.pos[1], self.direction)
|
||||
|
||||
goal_state = AgentState(random_chest[1][0], random_chest[1][1], self.direction)
|
||||
# find way to goal state
|
||||
treesearch_module = BFS(self)
|
||||
self.__actionsCollection = treesearch_module.graphsearch([],
|
||||
[],
|
||||
current_state,
|
||||
BFS.successor,
|
||||
goal_state)
|
||||
|
||||
if self.__actionsCollection is None:
|
||||
raise Exception("CRITICAL ERROR - Algorithm error - Path doesn't exist!!! ://")
|
||||
|
||||
else:
|
||||
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.has_goal_chest = False
|
||||
|
||||
elif len(
|
||||
self.__actionsCollection) != 0: # jeśli jest wyznaczona skrzynka - cel & są akcje do wykoannia to je realizuje
|
||||
|
||||
action_index = self.__actionsCollection[0] # ignore -1 because it's None
|
||||
self.__actionsCollection.remove(action_index)
|
||||
|
||||
new_state = ActionInterpreter.interpret(action_index,
|
||||
AgentState(self.pos[0], self.pos[1], self.direction))
|
||||
|
||||
self.model.grid.move_agent(self, (new_state.get_x(), new_state.get_y()))
|
||||
self.direction = new_state.get_direction()
|
||||
|
||||
#print("moved to - ", [new_state.get_x(), new_state.get_y()])
|
||||
|
||||
cellmates = self.model.grid.get_cell_list_contents([self.pos])
|
||||
if len(cellmates) > 1:
|
||||
if isinstance(cellmates[0], Box):
|
||||
decision = self.identify_content(cellmates[0])
|
||||
print("Content of chest: "+cellmates[0].address)
|
||||
if (decision == 'coins') or (decision == 'weapons'):
|
||||
print("I will open this chest!")
|
||||
self.open_chest(cellmates[0])
|
||||
print("Type of opened chest: ", cellmates[0].type)
|
||||
else:
|
||||
print("Probably a trap - chest skipped!")
|
||||
print("Type of skipped chest: ", cellmates[0].type)
|
||||
self.opened_chests += 1
|
||||
self.has_goal_chest = False
|
||||
cellmates[0].model.grid.remove_agent(cellmates[0])
|
||||
else:
|
||||
self.opponent = cellmates[0]
|
||||
self.strategy=self.predict_strategy(self.opponent)
|
||||
print("Current enemy stats:\n", self.describe_situation(self.opponent))
|
||||
print("Strategy returned from the tree: ", self.strategy)
|
||||
self.fight_or_flight(self.opponent, self.strategy)
|
||||
else:
|
||||
print("HP: 0 / " + str(self.maxHealth))
|
BIN
src/agent/map/__pycache__/gameMap.cpython-39.pyc
Normal file
BIN
src/agent/map/__pycache__/gameMap.cpython-39.pyc
Normal file
Binary file not shown.
97
src/agent/map/gameMap.py
Normal file
97
src/agent/map/gameMap.py
Normal file
@ -0,0 +1,97 @@
|
||||
from mesa import Model
|
||||
from mesa.datacollection import DataCollector
|
||||
import src.agent.ga_chromosome as ga
|
||||
from src.agent.hero import Player
|
||||
|
||||
from src.agent.model.dice.dice import roll_the_dice
|
||||
from src.agent.model.creature import Creature
|
||||
|
||||
from src.agent.model.box import Box
|
||||
|
||||
from src.items.armory import *#WM1, A1, WR1, S1, WM2, A2
|
||||
from mesa.time import RandomActivation
|
||||
from mesa.space import MultiGrid
|
||||
|
||||
import random
|
||||
|
||||
# from mesa.datacollection import DataCollector
|
||||
|
||||
x = 10
|
||||
y = 10
|
||||
step_counter = 0
|
||||
boxes_number = 6
|
||||
creatures_number = 35
|
||||
|
||||
class GameMap(Model):
|
||||
def __init__(self, x, y):
|
||||
self.listOfChests = []
|
||||
self.grid = MultiGrid(x, y, False)
|
||||
self.schedule = RandomActivation(self) # agenci losowo po kolei wykonują swoje akcje
|
||||
self.boxes_number = boxes_number
|
||||
self.creatures_number = creatures_number
|
||||
self.running = True
|
||||
best, score = ga.genetic_algorithm(ga.fitness_function, ga.n_bits, ga.n_iter, ga.n_pop, ga.r_cross, ga.r_mut)
|
||||
s=1+best.count(1)
|
||||
a=1+best.count(2)
|
||||
w=1+best.count(3)
|
||||
print("player optimised stats:", s, a, w)
|
||||
self.player = Player(1000, self, "Janusz", s, a, w, 50, 50, WM1, A1, 0, WR1, S1, self.listOfChests)
|
||||
print('Player stats:',self.player.strength, self.player.agility, self.player.wisdom)
|
||||
self.schedule.add(self.player)
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
self.grid.place_agent(self.player, (x, y))
|
||||
for i in range(self.boxes_number):
|
||||
r_type = random.randrange(1, 4)
|
||||
box = Box(i, self, r_type)
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
if self.grid.is_cell_empty((x, y)):
|
||||
self.grid.place_agent(box, (x, y))
|
||||
self.schedule.add(box)
|
||||
self.listOfChests.append([i, [x, y]]) # fetching chest position - [index, [OX, OY]]
|
||||
else:
|
||||
pass
|
||||
|
||||
for i in range(self.boxes_number,
|
||||
self.boxes_number + self.creatures_number-20): # taki range, żeby każdy agent miał poprawne unique_id
|
||||
# creature = Creature(i, self)
|
||||
creature = Creature(i, self, "Goblin",
|
||||
roll_the_dice(3), roll_the_dice(3), roll_the_dice(3), 15, roll_the_dice(3),
|
||||
WM2, A2, roll_the_dice(5))
|
||||
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
if self.grid.is_cell_empty((x, y)):
|
||||
self.grid.place_agent(creature, (x, y))
|
||||
self.schedule.add(creature)
|
||||
else:
|
||||
pass
|
||||
for i in range(self.boxes_number + self.creatures_number-20, self.creatures_number): # taki range, żeby każdy agent miał poprawne unique_id
|
||||
creature = Creature(i, self, "Skeleton",
|
||||
roll_the_dice(7), roll_the_dice(7), roll_the_dice(7), 15, roll_the_dice(7),
|
||||
WR4, A8, roll_the_dice(10))
|
||||
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
if self.grid.is_cell_empty((x, y)):
|
||||
self.grid.place_agent(creature, (x, y))
|
||||
self.schedule.add(creature)
|
||||
else:
|
||||
pass
|
||||
#self.datacollector=DataCollector(model_reporters={"HP":self.player.health, "Gold":self.player.gold, "Position (x, y)":self.player.pos}) #informacje o stanie planszy, pozycja agenta
|
||||
#other data: position, strength & other parameters
|
||||
def get_list_of_chests(self):
|
||||
return self.listOfChests
|
||||
|
||||
def get_hp(self):
|
||||
return self.player.health
|
||||
def get_gold(self):
|
||||
return self.player.gold
|
||||
def get_position(self):
|
||||
return str(self.player.pos)+str(self.player.direction.name)
|
||||
|
||||
def step(self):
|
||||
self.schedule.step()
|
||||
#self.datacollector.collect(self)
|
||||
#print(str(self.datacollector.model_reporters))
|
6
src/agent/model/__init__.py
Normal file
6
src/agent/model/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from .dice import *
|
||||
from .armor import Armor
|
||||
from .box import Box
|
||||
from .creature import Creature
|
||||
from .wall import Wall
|
||||
from .weapon import Weapon
|
BIN
src/agent/model/__pycache__/armor.cpython-39.pyc
Normal file
BIN
src/agent/model/__pycache__/armor.cpython-39.pyc
Normal file
Binary file not shown.
BIN
src/agent/model/__pycache__/box.cpython-39.pyc
Normal file
BIN
src/agent/model/__pycache__/box.cpython-39.pyc
Normal file
Binary file not shown.
BIN
src/agent/model/__pycache__/creature.cpython-39.pyc
Normal file
BIN
src/agent/model/__pycache__/creature.cpython-39.pyc
Normal file
Binary file not shown.
BIN
src/agent/model/__pycache__/wall.cpython-39.pyc
Normal file
BIN
src/agent/model/__pycache__/wall.cpython-39.pyc
Normal file
Binary file not shown.
BIN
src/agent/model/__pycache__/weapon.cpython-39.pyc
Normal file
BIN
src/agent/model/__pycache__/weapon.cpython-39.pyc
Normal file
Binary file not shown.
21
src/agent/model/armor.py
Normal file
21
src/agent/model/armor.py
Normal file
@ -0,0 +1,21 @@
|
||||
class Armor:
|
||||
def __init__(self, name, defence, mp):
|
||||
self.__name = name
|
||||
self.__defence = defence
|
||||
self.__mag_protection = mp
|
||||
|
||||
def get_name(self):
|
||||
return self.__name
|
||||
|
||||
def get_defence(self):
|
||||
return self.__defence
|
||||
|
||||
def set_defence(self, new_defence):
|
||||
self.__defence = new_defence
|
||||
|
||||
def get_mag_protection(self):
|
||||
return self.__mag_protection
|
||||
|
||||
def set_mag_protection(self, new_mag_protection):
|
||||
self.__mag_protection = new_mag_protection
|
||||
|
42
src/agent/model/box.py
Normal file
42
src/agent/model/box.py
Normal file
@ -0,0 +1,42 @@
|
||||
from mesa import Agent
|
||||
import random
|
||||
#from .dice.dice import roll_the_dice
|
||||
|
||||
golds = [("https://drive.google.com/uc?export=download&id=1fWeew0jXZ1lZBmv6CG5viLGloJAex6ao",'moneta'),
|
||||
("https://drive.google.com/uc?export=download&id=1UrXbbfJhfCuDZSnxund7sVk40QMS3R2Q", 'moneta2'),
|
||||
("https://drive.google.com/uc?export=download&id=1qH0OP4X1NQqpHtUkwD8SryJtKCKcZzVe", 'moneta3'),
|
||||
("https://drive.google.com/uc?export=download&id=1b9tZf639mEWgiWq_EYyqjeKYPEMi7dX9", 'moneta4'),
|
||||
("https://drive.google.com/uc?export=download&id=1z9jt-j3aS1fRUgVA_t1zR7TS5QzuXW5b", 'moneta5')]
|
||||
weapons = [("https://drive.google.com/uc?export=download&id=1TA-ObC33FaiHmgQ6i71Kcb32VrHsKUd1", 'miecz'),
|
||||
("https://drive.google.com/uc?export=download&id=1oyv15FSPJ84xx1tQLJW8Wlbb1JUx2xCy", 'miecz2'),
|
||||
("https://drive.google.com/uc?export=download&id=1Ha0eeLRLcidrMAN1P59V9zB8uSQq3GM5", 'miecz3'),
|
||||
("https://drive.google.com/uc?export=download&id=1GetUWnglUtqWqcK4sd5HsdVuaUpU5Ec_", 'miecz4'),
|
||||
("https://drive.google.com/uc?export=download&id=1RImo84OykYICvwfLycDEb5tr4tPbGVy1", 'miecz5')]
|
||||
traps = [("https://drive.google.com/uc?export=download&id=1G-AxY712V-eT2ylW0VXn4o2V_4pvy7lz", 'kwiat'),
|
||||
("https://drive.google.com/uc?export=download&id=1i7MwzJRPBZ-KrCDqhT5RCXLstLlWCsx9", 'kwiat2'),
|
||||
("https://drive.google.com/uc?export=download&id=1zF7wQuG1gtQ796m6TM08FOUOVK8s_qhT", 'kwiat3'),
|
||||
("https://drive.google.com/uc?export=download&id=1qwrIThsoKg44b57JXvbXe--TIplacd-i", 'kwiat4'),
|
||||
("https://drive.google.com/uc?export=download&id=1YsqdQaLyD8Es4w09p4Zdw2CufNkl_avN", 'kwiat5')]
|
||||
|
||||
class Box(Agent):
|
||||
def __init__(self, unique_id, model, type):
|
||||
super().__init__(unique_id, model)
|
||||
#self.gold = 3 * roll_the_dice(6)
|
||||
self.isBox = True
|
||||
self.isCreature = False
|
||||
self.isPlayer = False
|
||||
self.type = type
|
||||
r_img = random.randrange(0,4)
|
||||
if type == 1:
|
||||
self.address = golds[r_img][0]
|
||||
self.file_name = golds[r_img][1]
|
||||
elif type == 2:
|
||||
self.address = weapons[r_img][0]
|
||||
self.file_name = weapons[r_img][1]
|
||||
else:
|
||||
self.address = traps[r_img][0]
|
||||
self.file_name = traps[r_img][1]
|
||||
|
||||
def step(self):
|
||||
pass
|
||||
|
80
src/agent/model/creature.py
Normal file
80
src/agent/model/creature.py
Normal file
@ -0,0 +1,80 @@
|
||||
from mesa import Agent
|
||||
from .dice.dice import roll_the_dice
|
||||
|
||||
|
||||
class Creature(Agent):
|
||||
def __init__(self, unique_id, model, name, strength, agility, wisdom, max_hp, hp, weapon, armor, gold):
|
||||
super().__init__(unique_id, model)
|
||||
self.name = name
|
||||
self.strength = strength
|
||||
self.agility = agility
|
||||
self.wisdom = wisdom
|
||||
self.maxHealth = max_hp
|
||||
self.health = hp
|
||||
self.gold = gold
|
||||
self.weapon1 = weapon
|
||||
self.armor = armor
|
||||
self.isBox = False
|
||||
self.isCreature = True
|
||||
self.isPlayer = False
|
||||
|
||||
def get_strength(self):
|
||||
return self.strength
|
||||
|
||||
def get_agility(self):
|
||||
return self.agility
|
||||
|
||||
def get_wisdom(self):
|
||||
return self.wisdom
|
||||
|
||||
def get_health(self):
|
||||
return self.health
|
||||
|
||||
def get_damage(self):
|
||||
return self.weapon1.get_damage()
|
||||
|
||||
def get_melee_damage(self):
|
||||
return self.weapon1.get_damage()
|
||||
|
||||
def get_ranged_damage(self):
|
||||
return self.weapon2.get_damage()
|
||||
|
||||
def get_magic_damage(self):
|
||||
return self.weapon3.get_damage()
|
||||
|
||||
def get_armor_defence(self):
|
||||
return self.armor.get_defence()
|
||||
|
||||
def get_armor_magic_protection(self):
|
||||
return self.armor.get_mag_protection()
|
||||
|
||||
def get_attack_type(self):
|
||||
return self.weapon1.get_type()
|
||||
def melee_attack(self, opponent):
|
||||
attack_value = self.strength + roll_the_dice(6)
|
||||
defense_value = opponent.strength + opponent.armor.get_defence()
|
||||
damage = attack_value - defense_value
|
||||
if damage > 0:
|
||||
opponent.health = opponent.health - (damage + self.weapon1.get_damage())
|
||||
print("damage done by the monster: ", damage)
|
||||
def range_attack(self, opponent):
|
||||
attack_value = self.agility + roll_the_dice(6)
|
||||
defense_value = opponent.agility
|
||||
damage = attack_value - defense_value
|
||||
if (damage > 0) and (damage + self.weapon1.get_damage() - opponent.armor.get_defence() > 0):
|
||||
opponent.health = opponent.health - (damage + self.weapon1.get_damage() - opponent.armor.get_defence())
|
||||
print("damage done by the monster: ", damage)
|
||||
def magic_attack(self, opponent):
|
||||
attack_value = self.wisdom + roll_the_dice(6)
|
||||
defense_value = opponent.wisdom
|
||||
damage = attack_value - defense_value
|
||||
if (damage > 0) and (damage + self.weapon1.get_damage() - opponent.armor.get_mag_protection() > 0):
|
||||
opponent.health = opponent.health - (damage + self.weapon1.get_damage() - opponent.armor.get_mag_protection())
|
||||
print("damage done by the monster: ", damage)
|
||||
def default_attack(self, opponent):
|
||||
if self.weapon1.get_type() == "Meele":
|
||||
self.melee_attack(opponent)
|
||||
elif self.weapon1.get_type() == "Ranged":
|
||||
self.range_attack(opponent)
|
||||
else:
|
||||
self.magic_attack(opponent)
|
0
src/agent/model/dice/__init__.py
Normal file
0
src/agent/model/dice/__init__.py
Normal file
BIN
src/agent/model/dice/__pycache__/dice.cpython-39.pyc
Normal file
BIN
src/agent/model/dice/__pycache__/dice.cpython-39.pyc
Normal file
Binary file not shown.
4
src/agent/model/dice/dice.py
Normal file
4
src/agent/model/dice/dice.py
Normal file
@ -0,0 +1,4 @@
|
||||
import random
|
||||
|
||||
def roll_the_dice(number):
|
||||
return random.randint(1, number)
|
9
src/agent/model/wall.py
Normal file
9
src/agent/model/wall.py
Normal file
@ -0,0 +1,9 @@
|
||||
from mesa import Agent
|
||||
|
||||
|
||||
class Wall(Agent):
|
||||
def __init__(self, unique_id, model):
|
||||
super().__init__(unique_id, model)
|
||||
|
||||
def step(self):
|
||||
pass
|
14
src/agent/model/weapon.py
Normal file
14
src/agent/model/weapon.py
Normal file
@ -0,0 +1,14 @@
|
||||
class Weapon:
|
||||
def __init__(self, name, weapon_type, weapon_damage):
|
||||
self.__name = name
|
||||
self.__type = weapon_type
|
||||
self.__damage = weapon_damage
|
||||
|
||||
def get_name(self):
|
||||
return self.__name
|
||||
|
||||
def get_type(self):
|
||||
return self.__type
|
||||
|
||||
def get_damage(self):
|
||||
return self.__damage
|
29
src/agent/state.py
Normal file
29
src/agent/state.py
Normal file
@ -0,0 +1,29 @@
|
||||
class AgentState:
|
||||
def __init__(self, x, y, direction):
|
||||
self.__x = x
|
||||
self.__y = y
|
||||
self.__direction = direction
|
||||
|
||||
def get_x(self):
|
||||
return self.__x
|
||||
|
||||
def increment_x(self, value):
|
||||
self.__x += value
|
||||
|
||||
def set_x(self, x):
|
||||
self.__x = x
|
||||
|
||||
def get_y(self):
|
||||
return self.__y
|
||||
|
||||
def increment_y(self, value):
|
||||
self.__y += value
|
||||
|
||||
def set_y(self, y):
|
||||
self.__y = y
|
||||
|
||||
def get_direction(self):
|
||||
return self.__direction
|
||||
|
||||
def set_direction(self, direction):
|
||||
self.__direction = direction
|
20
src/decisiontree.py
Normal file
20
src/decisiontree.py
Normal file
@ -0,0 +1,20 @@
|
||||
import rpy2.robjects as robjects
|
||||
from rpy2.robjects.packages import importr
|
||||
import pickle
|
||||
|
||||
def create_model():
|
||||
RWeka = importr('RWeka')
|
||||
robjects.r('WPM("refresh-cache")')
|
||||
robjects.r('WPM("install-package", "simpleEducationalLearningSchemes")')
|
||||
robjects.r('WPM("load-package", "simpleEducationalLearningSchemes")')
|
||||
robjects.r('ID3<-make_Weka_classifier("weka/classifiers/trees/Id3")')
|
||||
robjects.r('fights<-read.arff("C:/Users/X260/Downloads/currentdata.arff")')
|
||||
robjects.r('fights.id3 <- ID3(strategy ~ p_strength + p_agility + p_wisdom+ p_health + '
|
||||
'p_melee_damage + p_ranged_damage + p_magic_damage + p_armor_defence + p_armor_magic_protection + '
|
||||
'e_strength+ e_agility + e_wisdom + e_health + e_damage + e_armor_defence + e_armor_magic_protection + '
|
||||
'e_attack_type, data = fights)')
|
||||
# robjects.r('.jcache(fights.id3)')
|
||||
#robjects.r('save(fights.id3, file="tree.rda)')
|
||||
# with open('tree.rda','wb') as f:
|
||||
# pickle.dump(robjects.r('fights.id3'), f)
|
||||
#todo: zapisać w rpythonie do pliku, raz zrobić i nie odpalać za każdym razem w serverze
|
BIN
src/dictionary/__pycache__/actions.cpython-39.pyc
Normal file
BIN
src/dictionary/__pycache__/actions.cpython-39.pyc
Normal file
Binary file not shown.
5
src/dictionary/actions.py
Normal file
5
src/dictionary/actions.py
Normal file
@ -0,0 +1,5 @@
|
||||
actions = {
|
||||
"rotate_left": -1,
|
||||
"move_forward": 0,
|
||||
"rotate_right": 1
|
||||
}
|
8
src/dictionary/directions.py
Normal file
8
src/dictionary/directions.py
Normal file
@ -0,0 +1,8 @@
|
||||
from src.direction import Direction
|
||||
|
||||
directions = {
|
||||
Direction.N: [0, 1],
|
||||
Direction.E: [1, 0],
|
||||
Direction.S: [0, -1],
|
||||
Direction.W: [-1, 0]
|
||||
}
|
16
src/direction.py
Normal file
16
src/direction.py
Normal file
@ -0,0 +1,16 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Direction(Enum):
|
||||
N = 0
|
||||
E = 1
|
||||
S = 2
|
||||
W = 3
|
||||
|
||||
def clockwise(self):
|
||||
v = (self.value + 1) % 4
|
||||
return Direction(v)
|
||||
|
||||
def counter_clockwise(self):
|
||||
v = (self.value - 1) % 4
|
||||
return Direction(v)
|
BIN
src/items/__pycache__/armory.cpython-39.pyc
Normal file
BIN
src/items/__pycache__/armory.cpython-39.pyc
Normal file
Binary file not shown.
@ -1,6 +1,5 @@
|
||||
from mesa import Agent, Model
|
||||
import random
|
||||
from hero import Weapon, Armor
|
||||
from src.agent.model.weapon import Weapon
|
||||
from src.agent.model.armor import Armor
|
||||
|
||||
WM1 = Weapon("Log", "Melee", 1)
|
||||
WM2 = Weapon("Log", "Melee", 1)
|
||||
@ -15,16 +14,16 @@ WM10 = Weapon("Axe", "Melee", 3)
|
||||
WM11 = Weapon("Axe", "Melee", 3)
|
||||
WM12 = Weapon("Battle axe", "Melee", 4)
|
||||
|
||||
WR1 = Weapon("Sling", "Range", 1)
|
||||
WR2 = Weapon("Sling", "Range", 1)
|
||||
WR3 = Weapon("Sling", "Range", 1)
|
||||
WR4 = Weapon("Bow", "Range", 2)
|
||||
WR5 = Weapon("Bow", "Range", 2)
|
||||
WR6 = Weapon("Bow", "Range", 2)
|
||||
WR7 = Weapon("Bow", "Range", 2)
|
||||
WR8 = Weapon("Longbow", "Range", 3)
|
||||
WR9 = Weapon("Longbow", "Range", 3)
|
||||
WR10 = Weapon("Crossbow", "Range", 4)
|
||||
WR1 = Weapon("Sling", "Ranged", 1)
|
||||
WR2 = Weapon("Sling", "Ranged", 1)
|
||||
WR3 = Weapon("Sling", "Ranged", 1)
|
||||
WR4 = Weapon("Bow", "Ranged", 2)
|
||||
WR5 = Weapon("Bow", "Ranged", 2)
|
||||
WR6 = Weapon("Bow", "Ranged", 2)
|
||||
WR7 = Weapon("Bow", "Ranged", 2)
|
||||
WR8 = Weapon("Longbow", "Ranged", 3)
|
||||
WR9 = Weapon("Longbow", "Ranged", 3)
|
||||
WR10 = Weapon("Crossbow", "Ranged", 4)
|
||||
|
||||
S1 = Weapon("Push", "Magic", 2)
|
||||
S2 = Weapon("Push", "Magic", 2)
|
||||
@ -62,9 +61,9 @@ A16 = Armor("Magical Plate Armor", 3, 2)
|
||||
# C10 = Box(A8)
|
||||
# C11 = Box(A12)
|
||||
# C12 = Box(A14)
|
||||
|
||||
#
|
||||
# Gracz = Player(1000, self, "Janusz",3,3,3,20,20,WM1,A1,0,WR1,S1)
|
||||
# def __init__(self, unique_id, model, n, s, a, w, maxhp, hp, weap, arm, g):
|
||||
# def __init__(self, unique_id, model, n, s, a, w, max_hp, hp, weapon, arm, g):
|
||||
# M1 = Creature("Goblin",2,2,1,10,10,WM2,A2,dice(6))
|
||||
# M2 = Creature("Goblin",2,2,1,10,10,WM3,A3,dice(6))
|
||||
# M3 = Creature("Goblin",2,2,1,10,10,WR2,A4,dice(6))
|
9
src/nominalize.py
Normal file
9
src/nominalize.py
Normal file
@ -0,0 +1,9 @@
|
||||
def nominalize(val, max_val):
|
||||
return_value = "NONE"
|
||||
if val > 0.66 * max_val:
|
||||
return_value = "HIGH"
|
||||
elif val > 0.33 * max_val:
|
||||
return_value = "MEDIUM"
|
||||
elif val > 0:
|
||||
return_value = "LOW"
|
||||
return return_value
|
BIN
src/tree/__pycache__/node.cpython-39.pyc
Normal file
BIN
src/tree/__pycache__/node.cpython-39.pyc
Normal file
Binary file not shown.
24
src/tree/node.py
Normal file
24
src/tree/node.py
Normal file
@ -0,0 +1,24 @@
|
||||
class Node:
|
||||
def __init__(self, parent, state_tuple, cost):
|
||||
self._cost = cost
|
||||
self._action = state_tuple[0]
|
||||
self._state = state_tuple[1]
|
||||
self._parent = parent
|
||||
|
||||
def get_cost(self):
|
||||
return self._cost
|
||||
|
||||
def get_action(self):
|
||||
return self._action
|
||||
|
||||
def get_state(self):
|
||||
return self._state
|
||||
|
||||
def get_predecessor(self):
|
||||
return self._parent
|
||||
|
||||
def set_predecessor(self, predecessor):
|
||||
self._parent = predecessor
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._cost < other.get_cost()
|
3
src/treesearch/__init__.py
Normal file
3
src/treesearch/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from .bfs import BFS
|
||||
from .actionsInterpreter import ActionInterpreter
|
||||
from .heuristic import *
|
BIN
src/treesearch/__pycache__/actionsInterpreter.cpython-39.pyc
Normal file
BIN
src/treesearch/__pycache__/actionsInterpreter.cpython-39.pyc
Normal file
Binary file not shown.
BIN
src/treesearch/__pycache__/bfs.cpython-39.pyc
Normal file
BIN
src/treesearch/__pycache__/bfs.cpython-39.pyc
Normal file
Binary file not shown.
40
src/treesearch/actionsInterpreter.py
Normal file
40
src/treesearch/actionsInterpreter.py
Normal file
@ -0,0 +1,40 @@
|
||||
from src.agent.state import AgentState
|
||||
from src.direction import Direction
|
||||
|
||||
|
||||
class ActionInterpreter:
|
||||
|
||||
@staticmethod
|
||||
def interpret(action_index, default_state):
|
||||
if action_index == -1:
|
||||
return AgentState(
|
||||
default_state.get_x(),
|
||||
default_state.get_y(),
|
||||
default_state.get_direction().counter_clockwise()
|
||||
)
|
||||
elif action_index == 0:
|
||||
move_x = 0
|
||||
move_y = 0
|
||||
|
||||
if default_state.get_direction() == Direction.N:
|
||||
move_y = 1
|
||||
elif default_state.get_direction() == Direction.E:
|
||||
move_x = 1
|
||||
elif default_state.get_direction() == Direction.S:
|
||||
move_y = -1
|
||||
elif default_state.get_direction() == Direction.W:
|
||||
move_x = -1
|
||||
|
||||
return AgentState(
|
||||
default_state.get_x() + move_x,
|
||||
default_state.get_y() + move_y,
|
||||
default_state.get_direction()
|
||||
)
|
||||
elif action_index == 1:
|
||||
return AgentState(
|
||||
default_state.get_x(),
|
||||
default_state.get_y(),
|
||||
default_state.get_direction().clockwise()
|
||||
)
|
||||
else:
|
||||
return default_state
|
140
src/treesearch/bfs.py
Normal file
140
src/treesearch/bfs.py
Normal file
@ -0,0 +1,140 @@
|
||||
import heapq
|
||||
|
||||
from src.dictionary.actions import actions
|
||||
from src.agent.state import AgentState
|
||||
from src.direction import Direction
|
||||
from src.tree.node import Node
|
||||
from src.treesearch.heuristic.manhattan import manhattan
|
||||
|
||||
|
||||
class BFS:
|
||||
|
||||
def __init__(self, agent):
|
||||
self.__agent = agent
|
||||
|
||||
@staticmethod
|
||||
def successor(append):
|
||||
|
||||
rotate_left = AgentState(
|
||||
append.get_x(),
|
||||
append.get_y(),
|
||||
append.get_direction().counter_clockwise()
|
||||
)
|
||||
|
||||
rotate_right = 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:
|
||||
move_forward = AgentState(
|
||||
append.get_x() + move_x,
|
||||
append.get_y() + move_y,
|
||||
append.get_direction()
|
||||
)
|
||||
else:
|
||||
move_forward = None
|
||||
|
||||
return [
|
||||
[actions["rotate_left"], rotate_left],
|
||||
[actions["move_forward"], move_forward],
|
||||
[actions["rotate_right"], rotate_right]
|
||||
]
|
||||
|
||||
def graphsearch(self, fringe, explored, istate, succesor_function, goal_state):
|
||||
final_action_list = []
|
||||
|
||||
init_state = [None, istate]
|
||||
root = Node(None, init_state, 0)
|
||||
|
||||
heapq.heappush(fringe, (0, root)) # at beginning do nothing
|
||||
|
||||
while len(fringe) != 0:
|
||||
_flag = True
|
||||
|
||||
if len(fringe) == 0:
|
||||
return False
|
||||
|
||||
tmp_node = (heapq.heappop(fringe))[1] # node
|
||||
|
||||
# build dictionary
|
||||
# parent = tmp_node.get_predecessor() # fetch parent state
|
||||
# tmp_node.set_predecessor(None) # clear predecessor - don't build a tree chain
|
||||
# if parent is None:
|
||||
# final_action_list.append([parent, tmp_node])
|
||||
# else:
|
||||
# final_action_list.append(
|
||||
# [parent[1], tmp_node]) # pair(key, value) - key: parent state, value: current state + action
|
||||
|
||||
if tmp_node.get_state().get_x() == goal_state.get_x() and tmp_node.get_state().get_y() == goal_state.get_y():
|
||||
while tmp_node.get_predecessor() is not None:
|
||||
final_action_list.append(tmp_node.get_action())
|
||||
tmp_node = tmp_node.get_predecessor()
|
||||
final_action_list = list(reversed(final_action_list))
|
||||
return final_action_list # TODO change step!
|
||||
|
||||
explored.append(tmp_node)
|
||||
|
||||
tmp_list = succesor_function(tmp_node.get_state())
|
||||
for new_state in tmp_list:
|
||||
_flag = True
|
||||
_flagFringe = True
|
||||
_flagExplored = True
|
||||
|
||||
if new_state[1] is None:
|
||||
continue
|
||||
|
||||
# calculating priority
|
||||
monster = 0
|
||||
if any([thing.isCreature for thing in
|
||||
self.__agent.model.grid.get_cell_list_contents(
|
||||
[(new_state[1].get_x(), new_state[1].get_y())])]):
|
||||
if new_state[0] == 0:
|
||||
monster = 0
|
||||
p = manhattan(new_state[1], goal_state) + tmp_node.get_cost() + monster + 1
|
||||
|
||||
r = 0
|
||||
counter = 0
|
||||
pos = 0
|
||||
for fringeNode in fringe:
|
||||
if fringeNode[1].get_state().get_x() == new_state[1].get_x() and fringeNode[
|
||||
1].get_state().get_y() == new_state[1].get_y() and fringeNode[1].get_state().get_direction() == \
|
||||
new_state[1].get_direction():
|
||||
_flagFringe = False
|
||||
_flag = False
|
||||
r = fringeNode[0]
|
||||
pos = counter
|
||||
counter = counter + 1
|
||||
|
||||
for exploredNode in explored:
|
||||
if exploredNode.get_state().get_x() == new_state[1].get_x() and exploredNode.get_state().get_y() == \
|
||||
new_state[1].get_y() and exploredNode.get_state().get_direction() == new_state[
|
||||
1].get_direction():
|
||||
_flagExplored = False
|
||||
_flag = False
|
||||
|
||||
# if _flag:
|
||||
# new_state[1].set_predecessor(tmp_node)
|
||||
|
||||
if _flagFringe and _flagExplored:
|
||||
new_node = Node(tmp_node, new_state, tmp_node.get_cost() + 1 + monster)
|
||||
heapq.heappush(fringe, (p, new_node))
|
||||
elif not _flagFringe and (p < r):
|
||||
new_node = Node(tmp_node, new_state, tmp_node.get_cost() + 1 + monster)
|
||||
fringe[pos][0] = p
|
||||
fringe[pos][1] = new_node
|
||||
|
||||
return None
|
1
src/treesearch/heuristic/__init__.py
Normal file
1
src/treesearch/heuristic/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .manhattan import manhattan
|
4
src/treesearch/heuristic/manhattan.py
Normal file
4
src/treesearch/heuristic/manhattan.py
Normal file
@ -0,0 +1,4 @@
|
||||
# cost is initially step distance in manhattan metric
|
||||
|
||||
def manhattan(state, target_state):
|
||||
return abs(state.get_x() - target_state.get_x()) + abs(state.get_y() - target_state.get_y())
|
Loading…
Reference in New Issue
Block a user