implemented random action selection

This commit is contained in:
Sakimori 2024-08-15 14:20:08 -04:00
parent f54572b913
commit ce3fda2638
4 changed files with 64 additions and 38 deletions

View file

@ -1,7 +1,7 @@
import random, team, player, os, math import random, team, player, os, math
from team import Team from team import Team
from player import Player, AtkAction, DefAction, Skater, Goalie from player import Player, Skater, Goalie
from skillContests import SkillContestParams, Situations from skillContests import SkillContestParams, Situations, AtkAction, DefAction
from attributes import normalDis from attributes import normalDis
from hocUtils import RinkGraph from hocUtils import RinkGraph
from enum import Enum from enum import Enum
@ -219,8 +219,8 @@ class Game(object):
defender = self.defendingSkater() #reroll until eligible defender found defender = self.defendingSkater() #reroll until eligible defender found
self.ineligibleDefenders = [] #clear ineligible defs self.ineligibleDefenders = [] #clear ineligible defs
atkAction, nodeTarget = attacker.chooseAtkAction(validActions, defender) atkAction, nodeTarget = attacker.chooseAtkAction(validActions, self.currentZone, self.activeGraph(), defender)
defAction = defender.chooseDefAction() defAction = defender.chooseDefAction(self.currentZone, self.activeGraph())
scParams = SkillContestParams().actionCheck(atkAction, defAction, self.currentSituation()) scParams = SkillContestParams().actionCheck(atkAction, defAction, self.currentSituation())
result = self.skillContest(attacker, defender, scParams) result = self.skillContest(attacker, defender, scParams)

View file

@ -1,6 +1,8 @@
import os, itertools import os, itertools
import networkx as nx import networkx as nx
from skillContests import DefAction
class RinkGraph(object): class RinkGraph(object):
"""Base class for a graph of nodes representing a hockey rink. Description of nodes found in design documents.""" """Base class for a graph of nodes representing a hockey rink. Description of nodes found in design documents."""
G = nx.empty_graph() G = nx.empty_graph()
@ -130,6 +132,16 @@ class RinkGraph(object):
adjacents.append(otherNodeName) adjacents.append(otherNodeName)
return adjacents return adjacents
def getPossibleDefensiveActions(self, nodeName):
if isinstance(nodeName, int):
nodeName = str(nodeName)
actions = [DefAction.Steal, DefAction.Poke, DefAction.BlockLn, DefAction.Body, DefAction.Force]
if int(nodeName) < 10 or int(nodeName) > 40 or int(nodeName[1]) == 0 or int(nodeName[1]) == 7: #on wall
actions.append(DefAction.Pin)
if int(nodeName[1]) >= 5: #in defensive end
actions.append(DefAction.BlockSlot)
return actions
def shotDanger(self, nodeName): def shotDanger(self, nodeName):
"""Returns an int indicating the danger of a shot from that zone. 0 is no danger, 100 is 26-Offensive Low Slot""" """Returns an int indicating the danger of a shot from that zone. 0 is no danger, 100 is 26-Offensive Low Slot"""
if isinstance(nodeName, int): if isinstance(nodeName, int):

View file

@ -1,5 +1,7 @@
import attributes import attributes
from enum import Enum from enum import Enum
from random import sample
from skillContests import AtkAction, DefAction, SkillContestParams
class CreationError(Exception): class CreationError(Exception):
pass pass
@ -50,6 +52,10 @@ class Player(object):
return attr return attr
return None return None
def getAttributes(self):
"""Returns a list of all Attributes."""
return self.attributes
def setAttribute(self, shortname:str, value:float): def setAttribute(self, shortname:str, value:float):
for attr in self.attributes: for attr in self.attributes:
if attr.name.lower().startswith(shortname.lower()): if attr.name.lower().startswith(shortname.lower()):
@ -78,16 +84,29 @@ class Player(object):
outString = f"{self.name[:3]}." outString = f"{self.name[:3]}."
return outString return outString
def predictOpposingAction(self, opposingSkater): def predictOpposingAction(self, opposingSkater, graph, currentNode):
oppAttributes = opposingSkater.getAttributes()
#TODO: Fuzzy opponent attributes based on wisdom
return self.chooseDefAction(statsOverride=oppAttributes)
raise NotImplementedError() raise NotImplementedError()
def chooseAtkAction(self, actionDic, opposingSkater): def chooseAtkAction(self, actionDic, currentNode, graph, opposingSkater):
"""Picks an action/target node combo.""" """TODO: Make actual AI. Picks an action/target node combo."""
predAction = self.predictOpposingAction(opposingSkater) predAction = self.predictOpposingAction(opposingSkater, graph, currentNode)
raise NotImplementedError() targetNode = sample(actionDic.keys(),1)[0] #random target node
action = AtkAction[sample(actionDic[targetNode],1)[0]]
ovr = SkillContestParams().actionCheck(action,predAction).override
while ovr is not None and ovr is False: #don't pick an autofail
targetNode = sample(actionDic.keys(),1)[0] #random target node
action = sample(actionDic[targetNode],1)[0]
ovr = SkillContestParams().actionCheck(action,predAction).override
return (action, targetNode)
def chooseDefAction(self): def chooseDefAction(self, currentNode, graph, statsOverride = None):
raise NotImplementedError() """TODO: Make actual AI. Returns random possible defensive action."""
attrs = self.attributes if statsOverride is None else statsOverride
possibleActions = graph.getPossibleDefensiveActions(currentNode)
return sample(possibleActions,1)[0]
class Skater(Player): class Skater(Player):
"""A hockey player that is not a goalie.""" """A hockey player that is not a goalie."""
@ -97,25 +116,3 @@ class Skater(Player):
class Goalie(Player): class Goalie(Player):
"""A hockey player that *is* a goalie.""" """A hockey player that *is* a goalie."""
pass pass
class AtkAction(Enum):
SkateB = 0
SkateF = 1
SkateT = 2
SkateA = 3
PassS = 4
PassF = 5
PassB = 6
Dump = 7
ShotS = 8
ShotW = 9
class DefAction(Enum):
Steal = 0
Poke = 1
BlockLn = 2
Body = 3
Force = 4
Pin = 5
BlockSlot = 6

View file

@ -1,4 +1,3 @@
from player import AtkAction, DefAction
from enum import Enum from enum import Enum
class Situations(Enum): class Situations(Enum):
@ -8,6 +7,27 @@ class Situations(Enum):
SH1 = -1 #3v4, 4v5, 5v6 SH1 = -1 #3v4, 4v5, 5v6
SH2 = -2 #3v5 or 4v6 SH2 = -2 #3v5 or 4v6
class AtkAction(Enum):
SkateB = 0
SkateF = 1
SkateT = 2
SkateA = 3
PassS = 4
PassF = 5
PassB = 6
Dump = 7
ShotS = 8
ShotW = 9
class DefAction(Enum):
Steal = 0
Poke = 1
BlockLn = 2
Body = 3
Force = 4
Pin = 5
BlockSlot = 6
class SkillContestParams(object): class SkillContestParams(object):
"""Basic structure for contests of skill.""" """Basic structure for contests of skill."""
atkStats = [] atkStats = []
@ -28,9 +48,6 @@ class SkillContestParams(object):
self.atkStats = result[0] self.atkStats = result[0]
self.defStats = result[1] self.defStats = result[1]
#Bool overrides, or [List of (stat,weight) , List of (stat,weight)] #Bool overrides, or [List of (stat,weight) , List of (stat,weight)]
evenTable = [ evenTable = [
#Steal #Poke #block lane #Body check #Force off puck #Pin to wall #Body block #Steal #Poke #block lane #Body check #Force off puck #Pin to wall #Body block