"""
Module myPlayerBrain: the sample Python AI.  Start with this project but write
your own code as this is a very simplistic implementation of the AI.

Created on January 15, 2013

@author: Windward Studios, Inc. (www.windward.net).

No copyright claimed - do anything you want with this code.
"""

import random
import simpleAStar
from framework import sendOrders
from api import units, map
from debug import printrap

from xml.etree import ElementTree as ET

NAME = "Don't Expect Anything"
SCHOOL = "University of Alberta"

class MyPlayerBrain(object):
    """The Python AI class.  This class must have the methods setup and gameStatus."""
    def __init__(self, name=NAME):
        self.name = name #The name of the player.
        
        #The player's avatar (looks in the same directory that this module is in).
        #Must be a 32 x 32 PNG file.
        try:
            avatar = open("MyAvatar.png", "rb")
            avatar_str = b''
            for line in avatar:
                avatar_str += line
            avatar = avatar_str
        except IOError:
            avatar = None # avatar is optional
        self.avatar = avatar
    
    def setup(self, gMap, me, allPlayers, companies, passengers, client):
        """
        Called at the start of the game; initializes instance variables.

        gMap -- The game map.
        me -- Your Player object.
        allPlayers -- List of all Player objects (including you).
        companies -- The companies on the map.
        passengers -- The passengers that need a lift.
        client -- TcpClient to use to send orders to the server.
        
        """
        self.gameMap = gMap
        self.players = allPlayers
        self.me = me
        self.companies = companies
        self.passengers = passengers
        self.client = client

        self.pickup = pickup = self.allPickups(me, passengers)

        # get the path from where we are to the dest.
        path = self.calculatePathPlus1(me, pickup[0].lobby.busStop)
        sendOrders(self, "ready", path, pickup)

    def gameStatus(self, status, playerStatus, players, passengers):
        """
        Called to send an update message to this A.I.  We do NOT have to send a response.

        status -- The status message.
        playerStatus -- The player this status is about. THIS MAY NOT BE YOU.
        players -- The status of all players.
        passengers -- The status of all passengers.

        """

        # bugbug - Framework.cs updates the object's in this object's Players,
        # Passengers, and Companies lists. This works fine as long as this app
        # is single threaded. However, if you create worker thread(s) or
        # respond to multiple status messages simultaneously then you need to
        # split these out and synchronize access to the saved list objects.

        try:
            # bugbug - we return if not us because the below code is only for
            # when we need a new path or our limo hits a bus stop. If you want
            # to act on other players arriving at bus stops, you need to
            # remove this. But make sure you use self.me, not playerStatus for
            # the Player you are updating (particularly to determine what tile
            # to start your path from).
            if playerStatus != self.me:
                return

            ptDest = None
            pickup = []
            if    status == "UPDATE":
                return
            elif (status == "PASSENGER_NO_ACTION" or
                  status == "NO_PATH"):
                if playerStatus.limo.passenger is None:
                    pickup = self.allPickups(playerStatus, passengers)
                    ptDest = pickup[0].lobby.busStop
                else:
                    ptDest = playerStatus.limo.passenger.destination.busStop
            elif (status == "PASSENGER_DELIVERED" or
                  status == "PASSENGER_ABANDONED"):
                pickup = self.allPickups(playerStatus, passengers)
                ptDest = pickup[0].lobby.busStop
            elif  status == "PASSENGER_REFUSED":
                ptDest = random.choice(filter(lambda c: c != playerStatus.limo.passenger.destination,
                    self.companies)).busStop
            elif (status == "PASSENGER_DELIVERED_AND_PICKED_UP" or
                  status == "PASSENGER_PICKED_UP"):
                pickup = self.allPickups(playerStatus, passengers)
                ptDest = playerStatus.limo.passenger.destination.busStop
            else:
                raise TypeError("unknown status %r", status)

            # get the path from where we are to the dest.
            path = self.calculatePathPlus1(playerStatus, ptDest)

            sendOrders(self, "move", path, pickup)
        except Exception as e:
            printrap ("somefin' bad, foo'!")
            raise e

    def calculatePathPlus1 (self, me, ptDest):
        path = simpleAStar.calculatePath(self.gameMap, me.limo.tilePosition, ptDest)
        # add in leaving the bus stop so it has orders while we get the message
        # saying it got there and are deciding what to do next.
        if len(path) > 1:
            path.append(path[-2])
        return path

    def allPickups (self, me, passengers):
            pickup = [p for p in passengers if (not p in me.passengersDelivered and
                                                p != me.limo.passenger and
                                                p.car is None and
                                                p.lobby is not None and p.destination is not None)]
            pickuporder = self.calcPriority(me, pickup)
            #random.shuffle(pickup)
            return pickuporder
    
    
    
    def calcPriority(self, me, pickup):
        pickuporder = []
        priority = {}
        pointmap = {1:5, 2:4, 3:3}
        for p in pickup:
            priority[p] = ((abs(p.lobby.busStop[0]-me.limo.tilePosition[0]))+(abs(p.lobby.busStop[1]-me.limo.tilePosition[1]))     +      (abs(p.lobby.busStop[0]-p.destination.busStop[0]))+(abs(p.lobby.busStop[1]-p.destination.busStop[1])))                    *  pointmap[p.pointsDelivered]
        while len(priority)>0:
            close = min(priority.values())
            for person in priority:
                if priority[person] == close:
                    pickuporder.append(person)
                    priority.pop(person)
                    break
        return pickuporder
@@ -5838,26 +5838,143 @@
 %0D%0A    %0D%0A    
+def distanceCalc(self, from_pos, to_pos):%0D%0A        return ((abs(from_pos%5B0%5D-to_pos%5B0%5D))+(abs(to_pos%5B1%5D-from_pos%5B1%5D)))
 %0D%0A
-
     %0D%0A    de
@@ -6150,62 +6150,25 @@
  = (
-(abs(p.lobby.busStop%5B0%5D-me.limo.tilePosition%5B0%5D))+(abs
+self.distanceCalc
 (p.l
@@ -6179,20 +6179,17 @@
 .busStop
-%5B1%5D-
+,
 me.limo.
@@ -6204,80 +6204,34 @@
 tion
-%5B1%5D))     +      (abs(p.lobby.busStop%5B0%5D-p.destination.busStop%5B0%5D))+(abs
+) +      self.distanceCalc
 (p.l
@@ -6242,20 +6242,17 @@
 .busStop
-%5B1%5D-
+,
 p.destin
@@ -6268,34 +6268,11 @@
 Stop
-%5B1%5D)))                    
+) )
 *  p

Modularized the distance calc