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

View file

@ -1,6 +1,8 @@
import os, itertools
import networkx as nx
from skillContests import DefAction
class RinkGraph(object):
"""Base class for a graph of nodes representing a hockey rink. Description of nodes found in design documents."""
G = nx.empty_graph()
@ -129,6 +131,16 @@ class RinkGraph(object):
if nodeDic['adjacent']:
adjacents.append(otherNodeName)
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):
"""Returns an int indicating the danger of a shot from that zone. 0 is no danger, 100 is 26-Offensive Low Slot"""

View file

@ -1,5 +1,7 @@
import attributes
from enum import Enum
from random import sample
from skillContests import AtkAction, DefAction, SkillContestParams
class CreationError(Exception):
pass
@ -49,6 +51,10 @@ class Player(object):
if attr.name.lower().startswith(shortname.lower()):
return attr
return None
def getAttributes(self):
"""Returns a list of all Attributes."""
return self.attributes
def setAttribute(self, shortname:str, value:float):
for attr in self.attributes:
@ -78,16 +84,29 @@ class Player(object):
outString = f"{self.name[:3]}."
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()
def chooseAtkAction(self, actionDic, opposingSkater):
"""Picks an action/target node combo."""
predAction = self.predictOpposingAction(opposingSkater)
raise NotImplementedError()
def chooseAtkAction(self, actionDic, currentNode, graph, opposingSkater):
"""TODO: Make actual AI. Picks an action/target node combo."""
predAction = self.predictOpposingAction(opposingSkater, graph, currentNode)
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):
raise NotImplementedError()
def chooseDefAction(self, currentNode, graph, statsOverride = None):
"""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):
"""A hockey player that is not a goalie."""
@ -96,26 +115,4 @@ class Skater(Player):
class Goalie(Player):
"""A hockey player that *is* a goalie."""
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
pass

View file

@ -1,4 +1,3 @@
from player import AtkAction, DefAction
from enum import Enum
class Situations(Enum):
@ -7,6 +6,27 @@ class Situations(Enum):
PP2 = 2 #5v3 or 6v4
SH1 = -1 #3v4, 4v5, 5v6
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):
"""Basic structure for contests of skill."""
@ -28,9 +48,6 @@ class SkillContestParams(object):
self.atkStats = result[0]
self.defStats = result[1]
#Bool overrides, or [List of (stat,weight) , List of (stat,weight)]
evenTable = [
#Steal #Poke #block lane #Body check #Force off puck #Pin to wall #Body block