genetic algorithm with decision tree in progress
This commit is contained in:
parent
fe3f9bf4fe
commit
5b89648f69
@ -5,7 +5,7 @@ from mesa.visualization.ModularVisualization import ModularServer
|
||||
#from src.decisiontree import create_model
|
||||
from src.direction import Direction
|
||||
from collections import defaultdict
|
||||
|
||||
import src.agent.ga_chromosome as ga
|
||||
|
||||
def player_representation(agent):
|
||||
portrayal = {"Shape": "sprites/heroE.png",
|
||||
@ -55,10 +55,10 @@ class PlayerStats(TextElement):
|
||||
# return model.player.describe_situation(model.player.opponent, model.player.strategy)
|
||||
# else:
|
||||
# return "Not fighting"
|
||||
ga.create_model()
|
||||
server = ModularServer(GameMap,
|
||||
[grid,PlayerStats()],
|
||||
"Map",
|
||||
{"x": 10, "y": 10})
|
||||
#create_model()
|
||||
server.port = 8081
|
||||
server.launch()
|
||||
|
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, 4, 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
|
@ -1,6 +1,6 @@
|
||||
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
|
||||
@ -30,7 +30,11 @@ class GameMap(Model):
|
||||
self.boxes_number = boxes_number
|
||||
self.creatures_number = creatures_number
|
||||
self.running = True
|
||||
self.player = Player(1000, self, "Janusz", 5, 5, 5, 50, 50, WM1, A1, 0, WR1, S1, self.listOfChests)
|
||||
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)
|
||||
self.player = Player(1000, self, "Janusz", s, a, w, 50, 50, WM1, A1, 0, WR1, S1, self.listOfChests)
|
||||
self.schedule.add(self.player)
|
||||
x = self.random.randrange(self.grid.width)
|
||||
y = self.random.randrange(self.grid.height)
|
||||
@ -51,7 +55,7 @@ class GameMap(Model):
|
||||
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), roll_the_dice(3), roll_the_dice(3),
|
||||
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)
|
||||
@ -63,7 +67,7 @@ class GameMap(Model):
|
||||
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), roll_the_dice(7), roll_the_dice(7),
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user