changed externAgent so as to never permit more than MAX_TOTAL_AGENTS to exist
[progcomp10.git] / src / link / externAgent.py
1 '''externAgent.py - a bot shell for talking to external I/O bots.
2 Written by Daniel Axtens <[email protected]> for the UCC Programming Competition in 2010.
3
4 Licensed under an MIT-style license: see the LICENSE file for details.
5 '''
6
7 from uccProgComp import BaseAgent, LearningAgent, RandomAttack
8 from rpsconst import *
9 #from pexpect import pexpect
10
11 import sys, subprocess
12
13 class externAgent (BaseAgent):
14
15     def __init__ (self, externName):
16         BaseAgent.__init__(self)
17         try:
18             self.process = subprocess.Popen(externName, stdin=subprocess.PIPE, 
19                                             stdout=subprocess.PIPE, stderr=subprocess.PIPE,
20                                             universal_newlines=True)
21         except Exception, e:
22             print ("Error spawning \"%s\": " % externName), e
23             
24     def stringToItem( self, str ):
25         if str == "Rock":
26             return Rock
27         elif str == "Paper":
28             return Paper
29         elif str == "Scissors":
30             return Scissors
31         else:
32             # Something has gone wrong!
33             print "Error: tried to convert \"%s\" into an item!" % str
34             raise ValueError( "tried to convert \"%s\" into an item!" % str );
35             return None
36
37     def itemToString( self, item ):
38         return rpsStrings[item]
39         
40         #if item == Rock:
41         #    return "Rock"
42         #elif item == Paper:
43         #    return "Paper"
44         #elif item == Scissors:
45         #    return "Scissors"
46         #else:
47         #    # Something has gone wrong!
48         #    print "Error: tried to convert '%d' to Rock/Paper/Scissors string!" % item
49         #    # raise an exception
50         #    raise ValueError("tried to convert '%d' to Rock/Paper/Scissors string!" % item)
51         
52     def resultToString( self, result ):
53         return adtStrings[result]
54     
55         #if result == Attacker:
56         #    return "Attacker"
57         #elif result == Defender:
58         #    return "Defender"
59         #elif result == Tie:
60         #    return "Tie"
61         #else:
62         #    # Something has gone wrong!
63         #    print "Error: tried to convert '%d' to Attacker/Defender/Tie string!" % result
64         #    # raise an exception
65         #    raise ValueError("tried to convert '%d' to Attacker/Defender/Tie string!" % result)
66         
67     def Attack (self, foe):
68         self.process.stdin.write ( ' '.join( ["ATTACK", repr(foe), "\r\n"] ) )
69         #print >>sys.stderr, self.process.stderr.readlines()
70         result = self.process.stdout.readline().split()
71         try:
72             attack, bluff = self.stringToItem( result[1] ), self.stringToItem( result[2] )
73             return attack, bluff
74         except:
75             #agent is insane
76             print "Agent is insane:", self
77             pass
78         
79     def Defend (self, foe, bluff ):
80         self.process.stdin.write ( ' '.join( ["DEFEND", repr(foe), self.itemToString( bluff ), "\r\n"] ) )
81         #print >>sys.stderr, self.process.stderr.readlines()
82         result = self.process.stdout.readline().split()
83         try:
84             defence = self.stringToItem( result[1] )
85             return defence
86         except:
87             #agent is insane
88             print "Agent is insane:", self
89             pass
90
91     def Results (self, foe, isInstigatedByYou, winner, attItem, defItem, bluffItem, pointDelta):
92         
93         BaseAgent.Results (self, foe, isInstigatedByYou, winner, attItem, 
94                            defItem, bluffItem, pointDelta)
95         
96         string = ' '.join( [ "RESULTS", repr(foe), repr(isInstigatedByYou), 
97                              self.resultToString(winner), 
98                              self.itemToString( attItem ), 
99                              self.itemToString( defItem ),
100                              self.itemToString( bluffItem ), repr(pointDelta),
101                              "\r\n" ] )
102         
103         #string = "RESULTS %s %s %s %s %s %s %d\r\n" % (foe, isInstigatedByYou, 
104         #                     self.resultToString(winner), 
105         #                     self.itemToString( attItem ), 
106         #                     self.itemToString( defItem ),
107         #                     self.itemToString( bluffItem ), pointDelta)
108         #print string
109         
110         self.process.stdin.write ( string )
111         self.process.stdout.readline() # read and discard (should be "OK")
112         
113         # we kill off the process here because otherwise the class doesn't get
114         # destroyed until the end of the iteration. This causes us to hold more
115         # than MAX_TOTAL_AGENTS open for a period of time, which is a bad thing.
116         if self.IsDead():
117             try:
118                 self.process.communicate( "BYE\r\n" )
119             except Exception, e:
120                 print "Error in BYE:", self, ":", e
121             
122             try:
123                 self.process.kill()
124             except:
125                 None
126
127
128     def __del__(self):
129         #unless we're being deleted unexpectedly, this is a no-op.
130         if self.process.poll() == None:
131             try:
132                 self.process.communicate( "BYE\r\n" )
133             except Exception, e:
134                 print "Error in BYE:", self, ":", e
135             
136             try:
137                 self.process.kill()
138             except:
139                 None

UCC git Repository :: git.ucc.asn.au