############################################################################
#
# Note that the rules have been changed slightly since the lecture.
# it was determined that the rules were too simple and therefore
# did not require enough AI.  The changes are to make the problem
# a little more complex. The real difference is that in order to fire
# at somebody, you have to be looking in their direction.  There are
# also a few small changes to encourage aggressiveness.
#
# Your tank can take 20 hits before you die.  Your tank turns red
# as it gets hit.  If you get hit, your cannon tilts askew for one
# turn.  You cannot fire while it is askew.  Of course, if you keep
# getting hit, it will keep tilting askew, so you better try to flee.
# Your turret is normally green or blue depending on which player
# you are.  However, if you can see the opponent, it turns black
# to indicate that it is ready to fire.
#
#
#
# This module defines a class 'TankAI' which must contain the method:
#
#   def chooseAction(self,maze,tank,enemy):
#
#   - self is a pointer to your TankAI object
#   - maze is a pointer to the maze object itself.
#   - tank is a pointer to the tank object.
#   - enemy is a pointer to the enemy object.
#
#   The return value must be one of the following strings:
#
#   "east"
#   "north"
#   "west"
#   "south"
#   "look-east"
#   "look-north"
#   "look-west"
#   "look-south"
#   "fire"
#
#   This method will be called repeatedly - each time it is called,
#   your tank will take a single step.  If you return a direction,
#   your tank will move. If you return the string "fire", you will
#   fire on the enemy.  Note that you cannot fire if you were just
#   hit - your cannon is destabilized.  This means that if you get
#   hit, you better run.
#
#   To help make your decision, you may evaluate the state of the
#   world.  Specifically, you may access these variables:
#
#   tank.x        - your own X coordinate
#   tank.y        - your own Y coordinate
#   tank.health   - the amount of health your tank has left.
#   tank.unstable - number of turns until your cannon restabilizes
#
#   maze.sizeX                - size of the maze (width)
#   maze.sizeY                - size of the maze (height)
#   maze.blockedE[y][x]       - can you go E from the specified cell?
#   maze.blockedW[y][x]       - can you go W from the specified cell?
#   maze.blockedN[y][x]       - can you go N from the specified cell?
#   maze.blockedS[y][x]       - can you go S from the specified cell?
#   maze.blocked[dir][y][x]   - where dir 0=E, 1=N, 2=W, 3=S)
#   maze.movelist             - ["east","north","west","south","fire"]
#   maze.los[y1][x1][y2][x2]  - equal to the string "Y" or "N"
#
#   In addition, you may have some information about the enemy,
#   if you can see him.  The rules are complex, so read carefully.
#
#   Line of sight is determined by an algorithm that connects the
#   centers of two squares using a straight line. In the boundary
#   case, where two tanks are on opposite sides of a corner, they
#   do not have line of sight.  The variable 'maze.los'
#   contains a line-of-sight table.  You can therefore evaluate
#   line of sight in constant time.
#
#   In order to be able to see somebody, you also need to be facing
#   them.  In other words, your turret needs to be pointed in their
#   direction plus or minus 45 degrees.  In the boundary case that
#   they're right on the edge of 45 degrees, they are in your view
#   cone.  You can aim your turret using the "look-east" directives
#   and so forth.  Also, a successful fire will point your turret
#   directly at your opponent - this is the only way to aim at
#   any angle other than along the axes.
#
#   Roughly, you can "see" somebody if and only if they are
#   in your view-cone.  However, there are two exceptions.
#
#   Exception one: if somebody who was in your view-cone moves out
#   of your view cone on their turn, then when it's your turn, you
#   get one last chance at a "parting shot."  Note that in a sense,
#   the parting shot is also a "parting look" - if somebody goes
#   around a corner, you can see which way they went while you take
#   that one last shot.
#
#   Exception two: if two players spot each other simultaneously,
#   then the player who moved into the other one's line of sight
#   gets first shot.  More accurately, if player A moves into
#   player B's view cone, while simultaneously facing toward
#   player B, then even though player B goes next, and even though
#   player A is in player B's view cone, then player B's ability
#   to "see" player A is suppressed for one turn.  This should
#   encourage aggressiveness.
#
#   You can tell if you can see the other player if your
#   parameter (enemy != 0).  If so, you can fire at them.  You
#   can also evaluate these variables:
#
#   enemy.x
#   enemy.y
#   enemy.health
#   enemy.unstable
#
#   Note that it is possible for you to cheat by accessing world
#   state other than the state listed above.  Do not do this, doing
#   so counts as cheating on your homework.
#
#   If you wish, you may store as much information as you like in
#   your own TankAI object.  You may utilize memory as much as you
#   wish, even going so far as to build up data structures that
#   analyze the entire maze if it helps.
#
#   Your grade will depend on your tank's performance. A few days
#   after we release this assignment, we will release five 
#   'benchmark' bots of varying levels of intelligence.  We will
#   run your AI against each of the five bots, five times.  That
#   means it is possible to score from 0 to 25 victories.  Your
#   grade will depend on the number of victories you score:
#
#   0: 0%     5: 55%   10: 80%   15: 90%  20: 95%   25: 100%
#   1: 20%    6: 60%   11: 82%   16: 91%  21: 96%
#   2: 30%    7: 65%   12: 84%   17: 92%  22: 97%
#   3: 40%    8: 70%   13: 86%   18: 93%  23: 98%
#   4: 50%    9: 75%   14: 88%   19: 94%  24: 99%
#
#   During the grading, your bot will have two minutes real time
#   to defeat the benchmark bot.  If it fails to do it in two
#   minutes, then it doesn't count as a victory for you.
#
############################################################################

import math,random

class TankAI:
  def __init__(self):
    self.lastdir = 0
    self.looking = 0

  def chooseAction(self,maze,tank,enemy):
    lastdir = self.lastdir
    if (enemy != 0):
      if (tank.unstable==0):
	return("fire")
    if (random.randint(0,3)==0):
      dir = random.randint(0,3)
      if (dir != self.looking):
	self.looking = dir
	return(maze.looklist[dir])
    dir = -1
    while (dir < 0):
      dir = random.randint(0,3)
      if (maze.blocked[dir][tank.y][tank.x]): dir = -1
    if (((dir+2)&3)==self.lastdir):
      if (maze.blocked[self.lastdir][tank.y][tank.x]==0):
	return(maze.movelist[self.lastdir])
    self.lastdir = dir
    return(maze.movelist[dir])



