Remove duplicate of pickEntity() in GA_With_DT and SurvivalDT classes

This commit is contained in:
Michał Czekański 2020-05-24 15:47:56 +02:00
parent 45345cabd8
commit 02df6e01c6
2 changed files with 42 additions and 97 deletions

View File

@ -1,6 +1,5 @@
import random import random
from datetime import datetime from datetime import datetime
from typing import List
import numpy import numpy
@ -8,15 +7,11 @@ import src.AI.DecisionTrees.InductiveDecisionTreeLearning as DT
import src.AI.DecisionTrees.projectSpecificClasses.Examples as Examples import src.AI.DecisionTrees.projectSpecificClasses.Examples as Examples
from src.AI.Affinities import Affinities from src.AI.Affinities import Affinities
from src.AI.DecisionTrees.DecisionTree import DecisionTree from src.AI.DecisionTrees.DecisionTree import DecisionTree
from src.AI.DecisionTrees.projectSpecificClasses.DTEntities.DTSurvivalInteractable import DTSurvivalInteractable
from src.AI.DecisionTrees.projectSpecificClasses.DTPlayerStats import DTPlayerStats
from src.AI.DecisionTrees.projectSpecificClasses.SurvivalAttributesDefinitions import \ from src.AI.DecisionTrees.projectSpecificClasses.SurvivalAttributesDefinitions import \
SurvivalAttributesDefinitions as AttrDefs SurvivalAttributesDefinitions as AttrDefs
from src.AI.DecisionTrees.projectSpecificClasses.SurvivalClassification import SurvivalClassification from src.AI.DecisionTrees.projectSpecificClasses.SurvivalClassification import SurvivalClassification
from src.AI.DecisionTrees.projectSpecificClasses.SurvivalDTExample import SurvivalDTExample from src.AI.SurvivalDT import SurvivalDT
from src.entities.Enums import Classifiers
from src.entities.Player import Player from src.entities.Player import Player
from src.game.Map import Map
def geneticAlgorithmWithDecisionTree(map, iter, solutions, mutationAmount=0.05): def geneticAlgorithmWithDecisionTree(map, iter, solutions, mutationAmount=0.05):
@ -29,13 +24,13 @@ def geneticAlgorithmWithDecisionTree(map, iter, solutions, mutationAmount=0.05):
:param mutationAmount: Mutation strength :param mutationAmount: Mutation strength
""" """
entityPickingDecisionTree = DT.inductiveDecisionTreeLearning(Examples.examples, survivalDecisionTree = SurvivalDT(DT.inductiveDecisionTreeLearning(Examples.examples,
AttrDefs.allAttributesDefinitions, AttrDefs.allAttributesDefinitions,
SurvivalClassification.FOOD, SurvivalClassification.FOOD,
SurvivalClassification) SurvivalClassification))
print("\nDecision tree: \n") print("\nDecision tree: \n")
DecisionTree.printTree(entityPickingDecisionTree, 0) DecisionTree.printTree(survivalDecisionTree.entityPickingDecisionTree, 0)
print() print()
# Based on 4 weights, that are affinities tied to the player # Based on 4 weights, that are affinities tied to the player
@ -57,7 +52,7 @@ def geneticAlgorithmWithDecisionTree(map, iter, solutions, mutationAmount=0.05):
fitness = [] fitness = []
for player in population: for player in population:
fitness.append(doSimulation(player, map, entityPickingDecisionTree)) fitness.append(doSimulation(player, map, survivalDecisionTree))
parents = selectMatingPool(population, fitness, int(solutions / 2)) parents = selectMatingPool(population, fitness, int(solutions / 2))
@ -137,10 +132,11 @@ def mutation(offspring, mutationAmount):
return offspring return offspring
def doSimulation(weights, map, decisionTree): def doSimulation(weights, map, decisionTree: SurvivalDT):
""" """
Runs the simulation. Returns fitness. Runs the simulation. Returns fitness.
:param decisionTree:
:param weights: A list of weights for players. :param weights: A list of weights for players.
:param map: Map object :param map: Map object
""" """
@ -148,7 +144,7 @@ def doSimulation(weights, map, decisionTree):
player.disableMovementTime() player.disableMovementTime()
while player.alive: while player.alive:
if player.movementTarget is None: if player.movementTarget is None:
target = pickEntity(player, map, decisionTree) target = decisionTree.pickEntity(player, map)
player.gotoToTarget(target, map) player.gotoToTarget(target, map)
player.update() player.update()
fitness = player.movePoints fitness = player.movePoints
@ -158,83 +154,6 @@ def doSimulation(weights, map, decisionTree):
return fitness return fitness
def pickEntity(player, map, entityPickingDecisionTree: DecisionTree):
"""
Select an entity to become the next goal for the player. The goal is specified by decision tree.
:param entityPickingDecisionTree:
:param player: Player object
:param map: Map object
:type map: Map
:type player: Player
"""
foods = map.getInteractablesByClassifier(Classifiers.FOOD)
waters = map.getInteractablesByClassifier(Classifiers.WATER)
rests = map.getInteractablesByClassifier(Classifiers.REST)
playerStats = DTPlayerStats.dtStatsFromPlayerStats(player.statistics)
# Get foods sorted by distance from player
dtFoods: List[DTSurvivalInteractable] = []
for food in foods:
dtFood = DTSurvivalInteractable.dtInteractableFromInteractable(food, player.x, player.y)
dtFoods.append(dtFood)
dtFoods.sort(key=lambda x: x.distanceFromPlayer.value)
# Get waters sorted by distance from player
dtWaters: List[DTSurvivalInteractable] = []
for water in waters:
dtWater = DTSurvivalInteractable.dtInteractableFromInteractable(water, player.x, player.y)
dtWaters.append(dtWater)
dtWaters.sort(key=lambda x: x.distanceFromPlayer.value)
# Get rest places sorted by distance from player
dtRestPlaces: List[DTSurvivalInteractable] = []
for rest in rests:
dtRest = DTSurvivalInteractable.dtInteractableFromInteractable(rest, player.x, player.y)
dtRestPlaces.append(dtRest)
dtRestPlaces.sort(key=lambda x: x.distanceFromPlayer.value)
currentSituation = SurvivalDTExample(None, playerStats.hungerAmount, playerStats.thirstAmount,
playerStats.staminaAmount,
dtFoods[0].distanceFromPlayer, dtWaters[0].distanceFromPlayer,
dtRestPlaces[0].distanceFromPlayer)
treeDecision, choice = pickEntityAfterTreeDecision(currentSituation, entityPickingDecisionTree, dtFoods, dtRestPlaces, dtWaters)
# If the choice happens to be the same as the last one pick something else.
if choice == map.getEntityOnCoord(player.getFacingCoord()):
if treeDecision == SurvivalClassification.FOOD:
dtFoods.remove(dtFoods[0])
elif treeDecision == SurvivalClassification.WATER:
dtWaters.remove(dtWaters[0])
elif treeDecision == SurvivalClassification.REST:
dtRestPlaces.remove(dtRestPlaces[0])
currentSituation = SurvivalDTExample(None, playerStats.hungerAmount, playerStats.thirstAmount,
playerStats.staminaAmount,
dtFoods[0].distanceFromPlayer, dtWaters[0].distanceFromPlayer,
dtRestPlaces[0].distanceFromPlayer)
treeDecision, choice = pickEntityAfterTreeDecision(currentSituation, entityPickingDecisionTree, dtFoods, dtRestPlaces, dtWaters)
return choice
def pickEntityAfterTreeDecision(currentSituation, decisionTree, dtFoods, dtRestPlaces, dtWaters):
treeDecision = decisionTree.giveAnswer(currentSituation)
choice = None
if treeDecision == SurvivalClassification.FOOD:
choice = dtFoods[0].interactable
elif treeDecision == SurvivalClassification.WATER:
choice = dtWaters[0].interactable
elif treeDecision == SurvivalClassification.REST:
choice = dtRestPlaces[0].interactable
return treeDecision, choice
def writeResults(iter, bestFit, bestMember): def writeResults(iter, bestFit, bestMember):
""" """
Logs the results of the iteration to files. Logs the results of the iteration to files.

View File

@ -5,7 +5,6 @@ from src.AI.DecisionTrees.projectSpecificClasses.DTEntities.DTSurvivalInteractab
from src.AI.DecisionTrees.projectSpecificClasses.DTPlayerStats import DTPlayerStats from src.AI.DecisionTrees.projectSpecificClasses.DTPlayerStats import DTPlayerStats
from src.AI.DecisionTrees.projectSpecificClasses.SurvivalClassification import SurvivalClassification from src.AI.DecisionTrees.projectSpecificClasses.SurvivalClassification import SurvivalClassification
from src.AI.DecisionTrees.projectSpecificClasses.SurvivalDTExample import SurvivalDTExample from src.AI.DecisionTrees.projectSpecificClasses.SurvivalDTExample import SurvivalDTExample
from src.AI.GA_With_DT import pickEntityAfterTreeDecision
from src.entities.Enums import Classifiers from src.entities.Enums import Classifiers
@ -57,7 +56,8 @@ class SurvivalDT:
dtFoods[0].distanceFromPlayer, dtWaters[0].distanceFromPlayer, dtFoods[0].distanceFromPlayer, dtWaters[0].distanceFromPlayer,
dtRestPlaces[0].distanceFromPlayer) dtRestPlaces[0].distanceFromPlayer)
treeDecision, choice = pickEntityAfterTreeDecision(currentSituation, self.entityPickingDecisionTree, dtFoods, treeDecision, choice = self.__pickEntityAfterTreeDecision__(currentSituation, self.entityPickingDecisionTree,
dtFoods,
dtRestPlaces, dtWaters) dtRestPlaces, dtWaters)
# If the choice happens to be the same as the last one pick something else. # If the choice happens to be the same as the last one pick something else.
@ -74,7 +74,33 @@ class SurvivalDT:
dtFoods[0].distanceFromPlayer, dtWaters[0].distanceFromPlayer, dtFoods[0].distanceFromPlayer, dtWaters[0].distanceFromPlayer,
dtRestPlaces[0].distanceFromPlayer) dtRestPlaces[0].distanceFromPlayer)
treeDecision, choice = pickEntityAfterTreeDecision(currentSituation, self.entityPickingDecisionTree, dtFoods, treeDecision, choice = self.__pickEntityAfterTreeDecision__(currentSituation, dtFoods,
dtRestPlaces, dtWaters) dtRestPlaces, dtWaters)
return choice print("Tree choice: ")
print(choice.getDescription())
return choice.interactable
def __pickEntityAfterTreeDecision__(self, currentSituation, dtFoods, dtRestPlaces, dtWaters):
"""
This method is usable only in SurvivalDT.pickEntity method.
After decision tree decides for what type of entity player should go this method retrieves a proper object
from list of foods, rest places, waters.
:param currentSituation:
:param dtFoods:
:param dtRestPlaces:
:param dtWaters:
:return:
"""
treeDecision = self.entityPickingDecisionTree.giveAnswer(currentSituation)
choice = None
if treeDecision == SurvivalClassification.FOOD:
choice = dtFoods[0]
elif treeDecision == SurvivalClassification.WATER:
choice = dtWaters[0]
elif treeDecision == SurvivalClassification.REST:
choice = dtRestPlaces[0]
return treeDecision, choice