hfo.py 3.47 KB
Newer Older
1 2
import socket, struct, thread, time

3
class HFO_Actions:
4 5
  ''' An enum of the possible HFO actions

6 7 8 9 10 11 12 13
  [Low-Level] Dash(power, relative_direction)
  [Low-Level] Turn(direction)
  [Low-Level] Tackle(direction)
  [Low-Level] Kick(power, direction)
  [High-Level] Move(): Reposition player according to strategy
  [High-Level] Shoot(): Shoot the ball
  [High-Level] Pass(): Pass to the most open teammate
  [High-Level] Dribble(): Offensive dribble
Matthew Hausknecht's avatar
Matthew Hausknecht committed
14
  QUIT
15 16

  '''
17
  DASH, TURN, TACKLE, KICK, MOVE, SHOOT, PASS, DRIBBLE, QUIT = range(9)
18 19 20 21

class HFO_Status:
  ''' Current status of the HFO game. '''
  IN_GAME, GOAL, CAPTURED_BY_DEFENSE, OUT_OF_BOUNDS, OUT_OF_TIME = range(5)
22 23


24
class HFOEnvironment(object):
25
  ''' The HFOEnvironment is designed to be the main point of contact
26 27 28 29 30 31
  between a learning agent and the Half-Field-Offense domain.

  '''
  def __init__(self):
    self.socket = None # Socket connection to server
    self.numFeatures = None # Given by the server in handshake
32
    self.features = None # The state features
33

34
  def connectToAgentServer(self, server_port=6000):
35 36 37 38 39 40 41 42 43 44 45
    '''Connect to the server that controls the agent on the specified port. '''
    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print '[Agent Client] Connecting to Agent Server on port', server_port
    while True:
      try:
        self.socket.connect(('localhost', server_port))
      except:
        time.sleep(1)
        continue
      else:
        break
46
    print '[Agent Client] Connected'
47
    self.handshakeAgentServer()
48 49 50 51 52 53 54
    # Get the initial state
    state_data = self.socket.recv(struct.calcsize('f')*self.numFeatures)
    if not state_data:
      print '[Agent Client] ERROR Recieved bad data from Server. Perhaps server closed?'
      self.cleanup()
      exit(1)
    self.features = struct.unpack('f'*self.numFeatures, state_data)
55 56

  def handshakeAgentServer(self):
57
    '''Handshake with the agent's server. '''
58 59 60 61 62 63 64 65 66 67 68
    # Recieve float 123.2345
    data = self.socket.recv(struct.calcsize("f"))
    f = struct.unpack("f", data)[0]
    assert abs(f - 123.2345) < 1e-4, "Float handshake failed"
    # Send float 5432.321
    self.socket.send(struct.pack("f", 5432.321))
    # Recieve the number of features
    data = self.socket.recv(struct.calcsize("i"))
    self.numFeatures = struct.unpack("i", data)[0]
    # Send what we recieved
    self.socket.send(struct.pack("i", self.numFeatures))
69 70 71 72
    # Get the current game status
    data = self.socket.recv(struct.calcsize("i"))
    status = struct.unpack("i", data)[0]
    assert status == HFO_Status.IN_GAME, "Status check failed"
73 74 75 76 77
    print '[Agent Client] Handshake complete'

  def getState(self):
    '''Get the current state of the world. Returns a list of floats with
    size numFeatures. '''
78
    return self.features
79

80
  def act(self, action):
81
    ''' Send an action and recieve the game status.'''
82
    self.socket.send(struct.pack("iff", *action))
83 84 85
    # Get the current game status
    data = self.socket.recv(struct.calcsize("i"))
    status = struct.unpack("i", data)[0]
86 87 88 89 90 91 92
    # Get the next state features
    state_data = self.socket.recv(struct.calcsize('f')*self.numFeatures)
    if not state_data:
      print '[Agent Client] ERROR Recieved bad data from Server. Perhaps server closed?'
      self.cleanup()
      exit(1)
    self.features = struct.unpack('f'*self.numFeatures, state_data)
93
    return status
94 95

  def cleanup(self):
96 97
    ''' Send a quit and close the connection to the agent's server. '''
    self.socket.send(struct.pack("i", HFO_Actions.QUIT))
98
    self.socket.close()