{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "source": [
    "# Grid\n",
    "\n",
    "The functions here are used often when dealing with 2D grids (like in TicTacToe)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Heading\n",
    "\n",
    "With the `turn_heading`, `turn_left` and `turn_right` functions an agent can turn around in a grid. In a 2D grid the orientations normally are:\n",
    "\n",
    "* North: (0,1)\n",
    "* South: (0,-1)\n",
    "* East: (1,0)\n",
    "* West: (-1,0)\n",
    "\n",
    "In code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "orientations = [(1, 0), (0, 1), (-1, 0), (0, -1)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We signify a left turn with a +1 and a right turn with a -1.\n",
    "\n",
    "The functions `turn_left` and `turn_right` call `turn_heading`, which then turns the agent around according to the input.\n",
    "\n",
    "First the code for `turn_heading`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def turn_heading(heading, inc, headings=orientations):\n",
    "    return headings[(headings.index(heading) + inc) % len(headings)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now use the function to turn left:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(-1, 0)\n"
     ]
    }
   ],
   "source": [
    "print(turn_heading((0, 1), 1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We were facing north and we turned left, so we are now facing west.\n",
    "\n",
    "Let's now take a look at the other two functions, which automate this process:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def turn_right(heading):\n",
    "    return turn_heading(heading, -1)\n",
    "\n",
    "def turn_left(heading):\n",
    "    return turn_heading(heading, +1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The first one turns the agent right, so it passes -1 to `turn_heading`, while the second one turns the agent left, so it passes +1.\n",
    "\n",
    "Let's see what happens when we are facing north and want to turn left and right:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(-1, 0)\n",
      "(1, 0)\n"
     ]
    }
   ],
   "source": [
    "print(turn_left((0, 1)))\n",
    "print(turn_right((0, 1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When we turn left from north we end up facing west, while on the other hand if we turn right we end up facing east."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Distance\n",
    "\n",
    "The function returns the Euclidean Distance between two points in the 2D space."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "import math\n",
    "\n",
    "def distance(a, b):\n",
    "    \"\"\"The distance between two (x, y) points.\"\"\"\n",
    "    return math.hypot((a[0] - b[0]), (a[1] - b[1]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5.0\n"
     ]
    }
   ],
   "source": [
    "print(distance((1, 2), (5, 5)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### Distance Squared\n",
    "\n",
    "This function returns the square of the distance between two points."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "def distance_squared(a, b):\n",
    "    \"\"\"The square of the distance between two (x, y) points.\"\"\"\n",
    "    return (a[0] - b[0])**2 + (a[1] - b[1])**2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "25\n"
     ]
    }
   ],
   "source": [
    "print(distance_squared((1, 2), (5, 5)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### Vector Clip\n",
    "\n",
    "With this function we can make sure the values of a vector are within a given range. It takes as arguments three vectors: the vector to clip (`vector`), a vector containing the lowest values allowed (`lowest`) and a vector for the highest values (`highest`). All these vectors are of the same length. If a value `v1` in `vector` is lower than the corresponding value `v2` in `lowest`, then we set `v1` to `v2`. Similarly we \"clip\" the values exceeding the `highest` values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "from utils import clip\n",
    "\n",
    "def vector_clip(vector, lowest, highest):\n",
    "    \"\"\"Return vector, except if any element is less than the corresponding\n",
    "    value of lowest or more than the corresponding value of highest, clip to\n",
    "    those values.\"\"\"\n",
    "    return type(vector)(map(clip, vector, lowest, highest))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 9)\n"
     ]
    }
   ],
   "source": [
    "print(vector_clip((-1, 10), (0, 0), (9, 9)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "The vector we wanted to clip was the tuple (-1, 10). The lowest allowed values were (0, 0) and the highest (9, 9). So, the result is the tuple (0,9)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
