#!/usr/bin/python2

# python imports
import sys, random, string, profile
# our imports
import Bot, defs, proc, AStar

__version__ = "$Revision: 1.5 $"

rand_seed = random.Random() # global random
def rand(max):
  foo = int(max * rand_seed.random())
  return foo


def good_package(w):
  packs = w.board.extra_here(w.bot.x_pos, w.bot.y_pos)
  if (not packs):
    return None

  # sort the packs so we can get five optimally, this is a guess
  can_carry = w.bot.capacity
  pickups = []
  packs = filter(lambda x: not w.py_bots.has_key(id(x)) and x.weight < w.bot.capacity, packs)
  packs.sort(lambda y,x :cmp(abs(w.bot.capacity - 6 * x.weight) , abs(w.bot.capacity - 6 * y.weight)))
  while (packs and can_carry > packs[0].weight):
    pickups.append(packs[0].id)
    can_carry -= packs[0].weight
    packs.pop(0)

  if (pickups):
    pickups = map ( lambda x: str(x), pickups )
    return (1, 'Pick ' + string.join(pickups, ' '))

  return None

def deliver_package(w):
  b = w.bot
  c_loc = (b.x_pos, b.y_pos)
  if (b.deliverme):
    if (b.deliverme.x_des == b.x_pos and b.deliverme.y_des == b.y_pos):
#      print "Dropping"
      return (1, 'Drop %d' % (b.deliverme.id))
    else:
      neighbor_func = lambda x:w.board.neighbors(x[0],x[1])
      null_heuristic = lambda x, y: abs(x[0]-y[0]) + abs(x[1]-y[1])
      null_distance = lambda x, y: 1

      mystar = AStar.AStar(c_loc, (b.deliverme.x_des, b.deliverme.y_des), neighbor_func, null_distance, null_heuristic)
      gen = mystar.do_a_little()
      for (dummy) in gen:
        dummy = 1
      newpos = mystar.solution[1]
      dir = b.rev_move(c_loc, newpos)
      return (1, 'Move %s' % (dir))
    
  return None

def close_home(w):
  bases = w.board.bases.keys()
  if (not bases):
    if (w.board.maybe_bases):
      w.board.bases = w.board.maybe_bases
      w.board.maybe_bases = {}
      return close_home(w)
    else:
      if (w.board.doubtful_bases):
        w.board.bases = w.board.doubtful_bases
        w.board.doubtful_bases = {}
        return close_home(w)
      else:
        print 'DONE!' # server connection killed before this
      
  b = w.bot
  c_loc = (b.x_pos, b.y_pos)
  
  neighbor_func = lambda x:w.board.neighbors(x[0],x[1])
  null_heuristic = lambda x, y: abs(x[0]-y[0]) + abs(x[1]-y[1])
  null_distance = lambda x, y: 1

  mystar = AStar.AStar(c_loc, bases[0], neighbor_func, null_distance, null_heuristic)
  gen = mystar.do_a_little()
  for (dummy) in gen:
    dummy = 1
  newpos = mystar.solution[1]
  dir = b.rev_move(c_loc, newpos)
  return (1, 'Move %s' % (dir))

def find_move(w):
  p = None
  p = good_package(w) # is there a good package to pickup here?
  if (p):
    return p

  d = deliver_package(w) # are we delivering a package?
  if (d):
    return d

  # lets find a package
  h = close_home(w) # find the closest home
  return h

def foo(host, port): # do the stuff
  jif = proc.Jiffies()
  w = Bot.World((host, port))
  while (1):
    (bid, cmd) = find_move(w)
    w.io.write(w.bot.make_move(bid, cmd))
    #    print "Waiting for server response"
    if (not w.read_server_response()):
      return None
    #    print "Waiting for package list"
    if (not w.read_packages()):
      return None

#    print "You are at %d, %d ($ %d) carry %d- Enter to continue" % (w.bot.x_pos, w.bot.y_pos, w.bot.money, w.bot.capacity)
#    jif.test()
#    jif.bump_turn()
  return

def bar(host, port): # wrapper to foo()
  print host, port, 'FOO'
  foo(host, port)
  print "FINISHED"
  return

if (len(sys.argv) > 1): # don't run during make check
  foo(sys.argv[1], int(sys.argv[2]))
