high_level_custom_agent.py 5.18 KB
Newer Older
1
#!/usr/bin/env python
drallensmith's avatar
drallensmith committed
2
from __future__ import print_function
3 4 5 6 7
# encoding: utf-8

#MODIFIED#

# First Start the server: $> bin/start.py
8
import argparse
drallensmith's avatar
drallensmith committed
9
import itertools
10
import random
11
try:
12 13
  import hfo
except ImportError:
14 15 16 17 18 19 20
  print('Failed to import hfo. To install hfo, in the HFO directory'\
    ' run: \"pip install .\"')
  exit()
params = {'SHT_DST':0.136664020547, 'SHT_ANG':-0.747394386098,
          'PASS_ANG':0.464086704478, 'DRIB_DST':-0.999052871962}

def can_shoot(goal_dist, goal_angle):
21
  """Returns True if if player may have a good shot at the goal"""
22
  return bool((goal_dist < params['SHT_DST']) and (goal_angle > params['SHT_ANG']))
23 24 25

def has_better_pos(dist_to_op, goal_angle, pass_angle, curr_goal_angle):
  """Returns True if teammate is in a better attacking position"""
26
  if (curr_goal_angle > goal_angle) or (dist_to_op < params['DRIB_DST']):
27 28 29 30 31
    return False
  if pass_angle < params['PASS_ANG']:
    return False
  return True

32 33
def get_action(state,hfo_env,num_teammates,rand_pass):
  """Decides and performs the action to be taken by the agent."""
34 35 36 37
  
  goal_dist = float(state[6])
  goal_op_angle = float(state[8])
  if can_shoot(goal_dist, goal_op_angle):
38
    hfo_env.act(hfo.SHOOT)
39
    return
drallensmith's avatar
drallensmith committed
40
  team_list = list(range(num_teammates))
41
  if rand_pass and (num_teammates > 1):
drallensmith's avatar
drallensmith committed
42
    random.shuffle(team_list)
43
  for i in team_list:
44 45 46 47 48
    teammate_uniform_number=state[10 + 3*num_teammates + 3*i +2]
    if has_better_pos(dist_to_op = float(state[10 + num_teammates + i]),
                      goal_angle = float(state[10 + i]),
                      pass_angle = float(state[10 + 2*num_teammates + i]),
                      curr_goal_angle = goal_op_angle):
49
      hfo_env.act(hfo.PASS, teammate_uniform_number)
50
      return
drallensmith's avatar
drallensmith committed
51 52 53 54
  # no check for can_dribble is needed; doDribble in agent.cpp includes
  # (via doPreprocess) doForceKick, which will cover this situation since
  # existKickableOpponent is based on distance.
  hfo_env.act(hfo.DRIBBLE)
55
  return
56 57 58 59
    

def main():
  parser = argparse.ArgumentParser()
60 61
  parser.add_argument('--port', type=int, default=6000, help="Server port")
  parser.add_argument('--seed', type=int, default=None,
62
                      help="Python randomization seed; uses python default if 0 or not given")
63 64
  parser.add_argument('--rand-pass', action="store_true",
                      help="Randomize order of checking teammates for a possible pass")
65
  parser.add_argument('--epsilon', type=float, default=0,
66
                      help="Probability of a random action if has the ball, to adjust difficulty")
67 68 69 70
  parser.add_argument('--record', action='store_true',
                      help="If doing HFO --record")
  parser.add_argument('--rdir', type=str, default='log/',
                      help="Set directory to use if doing --record")
71
  args=parser.parse_args()
72 73 74
  if args.seed:
    random.seed(args.seed)
  hfo_env = hfo.HFOEnvironment()
75 76 77 78 79 80 81 82 83
  if args.record:
    hfo_env.connectToServer(hfo.HIGH_LEVEL_FEATURE_SET,
                            'bin/teams/base/config/formations-dt', args.port,
                            'localhost', 'base_left', False,
                            record_dir=args.rdir)
  else:
    hfo_env.connectToServer(hfo.HIGH_LEVEL_FEATURE_SET,
                            'bin/teams/base/config/formations-dt', args.port,
                            'localhost', 'base_left', False)
84 85
  num_teammates = hfo_env.getNumTeammates()
  #num_opponents = hfo_env.getNumOpponents()
drallensmith's avatar
drallensmith committed
86
  if args.seed:
87
    if (args.rand_pass and (num_teammates > 1)) or (args.epsilon > 0):
drallensmith's avatar
drallensmith committed
88 89
      print("Python randomization seed: {0:d}".format(args.seed))
    else:
90 91
      print("Python randomization seed useless without --rand-pass w/2+ teammates or --epsilon >0")
  if args.rand_pass and (num_teammates > 1):
drallensmith's avatar
drallensmith committed
92
    print("Randomizing order of checking for a pass")
93 94
  if args.epsilon > 0:
    print("Using epsilon {0:n}".format(args.epsilon))
drallensmith's avatar
drallensmith committed
95 96 97 98 99 100 101 102 103
  for episode in itertools.count():
    num_eps = 0
    num_had_ball = 0
    num_move = 0
    status = hfo.IN_GAME
    while status == hfo.IN_GAME:
      state = hfo_env.getState()
      #print(state)
      if int(state[5]) == 1: # state[5] is 1 when player has the ball
104
        if (args.epsilon > 0) and (random.random() < args.epsilon):
drallensmith's avatar
drallensmith committed
105 106 107 108 109
          if random.random() < 0.5:
            hfo_env.act(hfo.SHOOT)
          else:
            hfo_env.act(hfo.DRIBBLE)
          num_eps += 1
110
        else:
111
          get_action(state,hfo_env,num_teammates,args.rand_pass)
drallensmith's avatar
drallensmith committed
112
        num_had_ball += 1
113
      else:
drallensmith's avatar
drallensmith committed
114 115 116 117
        hfo_env.act(hfo.MOVE)
        num_move += 1
      status=hfo_env.step()
      #print(status)
118

drallensmith's avatar
drallensmith committed
119 120 121 122 123 124 125 126
    # Quit if the server goes down
    if status == hfo.SERVER_DOWN:
      hfo_env.act(hfo.QUIT)
      exit()

    # Check the outcome of the episode
    print("Episode {0:d} ended with {1:s}".format(episode,
                                                  hfo_env.statusToString(status)))
127
    if args.epsilon > 0:
drallensmith's avatar
drallensmith committed
128 129 130 131
      print("\tNum move: {0:d}; Random action: {1:d}; Nonrandom: {2:d}".format(num_move,
                                                                               num_eps,
                                                                               (num_had_ball-
                                                                                num_eps)))
132 133 134

if __name__ == '__main__':
  main()