Skip to content
Snippets Groups Projects
Commit 15240ab3 authored by Daniel Axtens's avatar Daniel Axtens
Browse files

cleanup

parent cd42b53c
Branches
No related merge requests found
'''SampleAgents.py - A collection of sample agents for playing Rock Paper Scissors.
Written by Luke Williams <shmookey@ucc.asn.au> for the UCC Programming Competition in 2008.
Requires Python 2.5.
Licensed under an MIT-style license: see the LICENSE file for details.
'''
from uccProgComp import BaseAgent, LearningAgent, RandomAttack
from rpsconst import *
# Angel is a very simple bot that always tells the truth and expects others to do the same.
class Dummy (BaseAgent):
def Attack (self, foe):
return Paper, Paper
def Defend (self, foe, bluff):
return bluff
class Angel (BaseAgent):
def Attack (self, foe):
attack = RandomAttack () # Chooses randomly from Rock, Paper, Scissors
return attack, attack # Tells the truth for its bluff.
def Defend (self, foe, bluff):
return bluff # Trusts them to be going for a tie.
# Lucifer here is the opposite. He always lies expecting people to be good and always goes for the kill.
class Lucifer (BaseAgent):
def Attack (self, foe):
attack = RandomAttack ()
if attack == Rock: bluff = Scissors # Here we choose the thing
elif attack == Paper: bluff = Rock # that will hurt them
else: bluff = Paper # if they go for a tie.
return attack, bluff
def Defend (self, foe, bluff):
if bluff == Rock: attack = Paper # Here we trust that they
elif bluff == Paper: attack = Scissors # are telling the truth.
else: attack = Rock # And we try to kill them.
return attack
# def Results (self, foeName, wasAttacker, winner, attItem, defItem, bluffItem, pointDelta):
# BaseAgent.Results (self, foeName, wasAttacker, winner, attItem, defItem, bluffItem, pointDelta)
# print "I just scored " + str(pointDelta) + " points!"
# Streetfighter assumes everyone has it in for him.
class Streetfighter (BaseAgent):
def Attack (self, foe):
attack = RandomAttack ()
if attack == Rock: bluff = Paper # Here we choose the thing
elif attack == Paper: bluff = Scissors # that will hurt them
else: bluff = Rock # if they go for a tie.
return attack, bluff
def Defend (self, foe, bluff):
if bluff == Rock: attack = Paper # Here we trust that they
elif bluff == Paper: attack = Scissors # are telling the truth.
else: attack = Rock # And we try to kill them.
return attack
# This is our first bot with any sort of learning capability, based on the LearningAgent base.
# Experienced programmers might opt to write their own learning code based on BaseAgent, but it's up to you.
# Frenchie is a simple bot that is by default nice but will permanently turn against any agent that betrays it.
class Frenchie (LearningAgent):
def Attack (self, foe):
attack = RandomAttack ()
if Loss in LearningAgent.GetWinHistory (self, foe):
if attack == Rock: bluff = Scissors
elif attack == Paper: bluff = Rock
else: bluff = Paper
else:
bluff = attack
return attack, bluff
def Defend (self, foe, bluff):
if Loss in LearningAgent.GetWinHistory (self, foe):
if bluff == Rock: attack = Scissors # They've fucked us in the past,
elif bluff == Paper: attack = Rock # so we assume they're lying and
else: attack = Paper # hoping we go for a kill.
else:
attack = bluff
return attack
# If you want to implement your own Results () callback, you have to call the parent class's first:
class Blank (BaseAgent):
def Attack (self, foe):
return Paper, Paper
def Defend (self, foe, bluff):
return bluff
def Results (self, foeName, wasAttacker, winner, attItem, defItem, bluffItem, pointDelta):
BaseAgent.Results (self, foeName, wasAttacker, winner, attItem, defItem, bluffItem, pointDelta)
# Now you can do your own thing
File deleted
File moved
File moved
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File moved
File moved
'''uccProgComp.py - A supervisor candidate for Rock Paper Scissors.
Written by Luke Williams <shmookey@ucc.asn.au> for the UCC Programming Competition in 2008.
Requires Python 2.5.
Licensed under an MIT-style license: see the LICENSE file for details.
'''
import random, uuid
random.seed ()
from rpsconst import *
DEFAULT_HEALTH = 50
REPRODUCE_HEALTH = 100
DIE_HEALTH = 0
MAX_AGE = 100
DEBUG_MODE = False
# Game dynamics - these are not final:
# WINNER TRUTH WINNER, LOSER
pointsTable [Attacker] [False] = (2, -2)
pointsTable [Attacker] [True] = (2, -2)
pointsTable [Defender] [False] = (-2, 2)
pointsTable [Defender] [True] = (-2, 2)
pointsTable [Tie] [False] = (-1, -1)
pointsTable [Tie] [True] = (1, 1)
def Debug (f):
def g (*args):
if DEBUG_MODE:
print f.__name__, args[1].__class__.__name__, args[1].GetID ()
return f (*args)
return g
class BaseAgent:
def __init__ (self):
self.id = uuid.uuid4().int
self.__points = DEFAULT_HEALTH
# The index will be changing all the time. It can go stale as soon as something dies.
# So use it cautiously.
self.__currentIndex = 0
self.__reproduced = False
self.__age = 0
def GetCurrentIndex (self):
return self.__currentIndex
def SetCurrentIndex (self, index):
self.__currentIndex = index
def GetID (self):
return self.id
def GetPoints (self):
return self.__points
def SetPoints (self, points):
self.__points = points
def Defend (self, foe, bluff):
return Rock
def Attack (self, foe):
return Rock
def IsDead (self):
return self.__points <= DIE_HEALTH
def Reproduced (self):
self.__points = DEFAULT_HEALTH
self.__reproduced = True
def HasReproduced (self):
return self.__reproduced
def SetReproduced (self, repro):
self.__reproduced = repro
def Results (self, foeName, wasAttacker, winner, attItem, defItem, bluffItem, pointDelta):
self.__points += pointDelta
self.__age += 1
if self.__age > MAX_AGE: self.__points = DIE_HEALTH
class LearningAgent (BaseAgent):
def __init__ (self):
BaseAgent.__init__ (self)
self.winHistory = {}
def Results (self, foeName, wasAttacker, winner, attItem, defItem, bluffItem, pointDelta):
BaseAgent.Results (self, foeName, wasAttacker, winner, attItem, defItem, bluffItem, pointDelta)
if wasAttacker:
if winner == Attacker: result = Win
elif winner == Tie: result = Tie
else: result = Loss
else:
if winner == Attacker: result = Loss
elif winner == Tie: result = Tie
else: result = Win
if foeName in self.winHistory: self.winHistory [foeName].append (result)
else: self.winHistory [foeName] = [result]
def GetWinHistory (self, foeName):
if foeName in self.winHistory: return self.winHistory [foeName]
else: return []
class Supervisor:
def __init__ (self):
# The full list of living agents
self.population = []
# A list of classes for each agent type
self.agentTypes = []
# The current iteration
self.iteration = 0
self.agentStats = {}
self.pendingDeaths = []
def RegisterAgent (self, agent):
self.agentTypes.append (agent)
def GeneratePopulation (self, nAgentsPerClass):
for Agent in self.agentTypes:
for i in range (0,nAgentsPerClass): self.population.append (Agent ())
self.agentStats [str(Agent)] = [nAgentsPerClass,0,0]
def Iterate (self):
self.ClearStats ()
self.UpdateIndexes ()
self.iteration += 1
for attacker, defender in self.Select ():
attack, bluff = attacker.Attack (defender.GetID ())
defense = defender.Defend (attacker.GetID (), bluff)
winner = resultTable [attack] [defense]
attPoints, defPoints = pointsTable [winner][attack == bluff]
attacker.Results (defender.GetID (), True, winner, attack, defense, bluff, attPoints)
defender.Results (attacker.GetID (), False, winner, attack, defense, bluff, defPoints)
if attacker.IsDead (): self.KillAgent (attacker)
elif attacker.GetPoints () >= REPRODUCE_HEALTH: self.SpawnAgent (attacker)
if defender.IsDead (): self.KillAgent (defender)
elif defender.GetPoints () >= REPRODUCE_HEALTH: self.SpawnAgent (defender)
def IsGameOver (self):
if self.population == []: return True
liveAgents = [id for id,stats in self.agentStats.iteritems () if stats[0] > 0]
print liveAgents
if len(liveAgents) < 2: return True
return False
# This is needed because when we pick the players we also need a way of identifying them in the
# population list without manually searching each time. O(n) each iteration is better than O(n)
# each death. It also resets the check for if the agent has reproduced this round.
def UpdateIndexes (self):
for agentID in reversed(sorted(self.pendingDeaths)): del self.population [agentID]
for index, agent in enumerate(self.population):
agent.SetCurrentIndex (index)
agent.SetReproduced (False)
self.pendingDeaths = []
@Debug
def KillAgent (self, agent):
self.pendingDeaths.append (agent.GetCurrentIndex ())
stat = self.agentStats [str(agent.__class__)]
stat [0] -= 1
stat [2] += 1
@Debug
def SpawnAgent (self, agent):
child = agent.__class__ ()
self.population.append (child)
agent.Reproduced ()
stat = self.agentStats [str(agent.__class__)]
stat [0] += 1
stat [1] += 1
def Select (self):
# This approach causes agents to keep fighting until they've either died or reproduced.
remaining = self.population[:]
attackerID = defenderID = random.randint (0,len(remaining)-1)
attacker = defender = remaining [attackerID]
while len (remaining) >= 2:
# Check to see if the attacker from last round needs to be dropped.
if attacker.IsDead () or attacker.HasReproduced ():
remaining.pop (attackerID)
if not len(remaining) >= 2: continue
if defenderID > attackerID: defenderID -= 1
# Check to see if the defender from last round is up for some attacking.
if defender.IsDead () or defender.HasReproduced ():
remaining.pop (defenderID)
if not len(remaining) >= 2: continue
attackerID = random.randint (0,len(remaining)-1)
attacker = remaining [attackerID]
else:
attacker = defender
attackerID = defenderID
defender = None
defenderID = random.randint (0,len(remaining)-2)
if defenderID >= attackerID: defenderID += 1
defender = remaining [defenderID]
yield attacker, defender
def GetStats (self):
return self.agentStats
def ClearStats (self):
for agent in self.agentTypes: self.agentStats [str(agent)] = self.agentStats [str(agent)] [:1] + [0,0]
def RandomAttack ():
return random.randint (0,2)
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment