{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Halite is an online multiplayer game created by Two Sigma.  In the game, four participants command ships to collect an energy source called **halite**.  The player with the most halite at the end of the game wins.\n\nIn this tutorial, as part of the **[Halite competition](https://www.kaggle.com/c/halite/overview)**, you'll write your own intelligent bots to play the game.  \n\n> Note that the Halite competition is now closed, so we are no longer accepting submissions.  That said, you can still use the competition to write your own bots - you just cannot submit bots to the official leaderboard.  To see the current list of open competitions, check out the simulations homepage: https://www.kaggle.com/simulations.\n\n\n# Part 1: Get started\n\nIn this section, you'll learn more about how to play the game. ","metadata":{}},{"cell_type":"markdown","source":"## Game rules \n\nIn this section, we'll look more closely at the game rules and explore the different icons on the game board.\n\nFor context, we'll look at a game played by four random players.  You can use the animation below to view the game in detail: every move is captured and can be replayed. ","metadata":{}},{"cell_type":"code","source":"\nfrom kaggle_environments import make, evaluate\nenv = make(\"halite\", debug=True)\nenv.run([\"random\", \"random\", \"random\", \"random\"])\nenv.render(mode=\"ipython\", width=800, height=600)","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The game is played in a 21 by 21 gridworld and lasts 400 timesteps.  Each player starts the game with 5,000 halite and one ship.  \n\nGrid locations with **halite** are indicated by a light blue icon, where larger icons indicate more available halite.\n\n<center>\n<img src=\"https://storage.googleapis.com/kaggle-media/learn/images/3NENMos.png\" width=65%><br/>\n</center>\n\nPlayers use **ships** to navigate the world and collect halite.  A ship can only collect halite from its current position.  When a ship decides to collect halite, it collects 25% of the halite available in its cell.  This collected halite is added to the ship's \"cargo\".  \n\n<center>\n<img src=\"https://storage.googleapis.com/kaggle-media/learn/images/eKN0kP3.png\" width=65%><br/>\n</center>\n\nHalite in ship cargo is not counted towards final scores.  In order for halite to be counted, ships need to deposit their cargo into a **shipyard** of the same color.  A ship can deposit all of its cargo in a single timestep simply by navigating to a cell containing a shipyard.\n\n<center>\n<img src=\"https://storage.googleapis.com/kaggle-media/learn/images/LAc6fj8.png\" width=65%><br/>\n</center>\n\nPlayers start the game with no shipyards.  To get a shipyard, a player must convert a ship into a shipyard, which costs 500 halite.  Also, shipyards can spawn (or create) new ships, which deducts 500 halite (per ship) from the player.\n\nTwo ships cannot successfully inhabit the same cell.  This event results in a **collision**, where:\n- the ship with more halite in its cargo is destroyed, and \n- the other ship survives and instantly collects the destroyed ship's cargo.\n\n<center>\n<img src=\"https://storage.googleapis.com/kaggle-media/learn/images/BuIUPmK.png\" width=65%><br/>\n</center>\n\nIf you view the full game rules, you'll notice that there are more types of collisions that can occur in the game (for instance, ships can collide with enemy shipyards, which destroys the ship, the ship's cargo, and the enemy shipyard). \n\nIn general, Halite is a complex game, and we have not covered all of the details here.  But even given these simplified rules, you can imagine that a successful player will have to use a relatively complicated strategy.  ","metadata":{}},{"cell_type":"markdown","source":"## Game strategy\n\nAs mentioned above, a ship has two options at its disposal for collecting halite.  It can:\n- collect (or mine) halite from its current position.\n- collide with an enemy ship containing relatively more halite in its cargo.  In this case, the ship destroys the enemy ship and steals its cargo.\n\nBoth are illustrated in the figure below.  The \"cargo\" that is tracked in the player's scoreboard contains the total cargo, summed over all of the player's ships.\n<center>\n<img src=\"https://storage.googleapis.com/kaggle-media/learn/images/2DJX6Vt.png\" width=75%><br/>\n</center>\n\nThis raises some questions that you'll have to answer when commanding ships:\n- Will your ships focus primarily on locating large halite reserves and mining them efficiently, while mostly ignoring and evading the other players?  \n- Or, will you look for opportunities to steal halite from other players?  \n- Alternatively, can you use a combination of those two strategies?  If so, what cues will you look for in the game to decide which option is best?  For instance, if all enemy ships are far away and your ships are located on cells containing a lot of halite, it makes sense to focus on mining halite.  Conversely, if there are many ships nearby with halite to steal (and not too much local halite to collect), it makes sense to attack the enemy ships.\n\nYou'll also have to decide how to control your shipyards, and how your ships interact with shipyards.  There are three primary actions in the game involving shipyards.  You can:\n- convert a ship into a shipyard.  This is the only way to create a shipyard.  \n- use a shipyard to create a ship.\n- deposit a ship's cargo into a shipyard. \n\nThese are illustrated in the image below.\n\n<center>\n<img src=\"https://storage.googleapis.com/kaggle-media/learn/images/fL5atut.png\" width=75%><br/>\n</center>\n\nWith more ships and shipyards, you can collect halite at a faster rate.  But each additional ship and shipyard costs you halite: how will you decide when it might be beneficial to create more?","metadata":{}},{"cell_type":"markdown","source":"# Part 2: Your first bot\n\nIn this section, you'll create your first bot to play the game.\n\n## The notebook\n\nThe first thing to do is to create a Kaggle notebook where you'll store all of your code. \n\nBegin by navigating to [**https://www.kaggle.com/notebooks**](https://www.kaggle.com/notebooks) and clicking on **\"New Notebook\"**.\n\nNext, click on **\"Create\"**. (_Don't change the default settings: so, **\"Python\"** should appear under **\"Select language\"**, and you should have **\"Notebook\"** selected under **\"Select type\"**._)\n\n![](https://storage.googleapis.com/kaggle-media/learn/images/qUVvr8k.png)\n\nYou now have a notebook where you'll develop your first agent!  If you're not sure how to use Kaggle Notebooks, we strongly recommend that you walk through **[this notebook](https://www.kaggle.com/alexisbcook/getting-started-with-titanic)** before proceeding.  It teaches you how to run code in the notebook.\n\n## Your first agent\n\nIt's time to create your first agent!  Copy and paste the code in the cell below into your notebook.  Then, run the code.","metadata":{}},{"cell_type":"code","source":"%%writefile submission.py\n\n# Imports helper functions\nfrom kaggle_environments.envs.halite.helpers import *\n\n# Returns best direction to move from one position (fromPos) to another (toPos)\n# Example: If I'm at pos 0 and want to get to pos 55, which direction should I choose?\ndef getDirTo(fromPos, toPos, size):\n    fromX, fromY = divmod(fromPos[0],size), divmod(fromPos[1],size)\n    toX, toY = divmod(toPos[0],size), divmod(toPos[1],size)\n    if fromY < toY: return ShipAction.NORTH\n    if fromY > toY: return ShipAction.SOUTH\n    if fromX < toX: return ShipAction.EAST\n    if fromX > toX: return ShipAction.WEST\n\n# Directions a ship can move\ndirections = [ShipAction.NORTH, ShipAction.EAST, ShipAction.SOUTH, ShipAction.WEST]\n\n# Will keep track of whether a ship is collecting halite or carrying cargo to a shipyard\nship_states = {}\n\n# Returns the commands we send to our ships and shipyards\ndef agent(obs, config):\n    size = config.size\n    board = Board(obs, config)\n    me = board.current_player\n\n    # If there are no ships, use first shipyard to spawn a ship.\n    if len(me.ships) == 0 and len(me.shipyards) > 0:\n        me.shipyards[0].next_action = ShipyardAction.SPAWN\n\n    # If there are no shipyards, convert first ship into shipyard.\n    if len(me.shipyards) == 0 and len(me.ships) > 0:\n        me.ships[0].next_action = ShipAction.CONVERT\n    \n    for ship in me.ships:\n        if ship.next_action == None:\n            \n            ### Part 1: Set the ship's state \n            if ship.halite < 200: # If cargo is too low, collect halite\n                ship_states[ship.id] = \"COLLECT\"\n            if ship.halite > 500: # If cargo gets very big, deposit halite\n                ship_states[ship.id] = \"DEPOSIT\"\n                \n            ### Part 2: Use the ship's state to select an action\n            if ship_states[ship.id] == \"COLLECT\":\n                # If halite at current location running low, \n                # move to the adjacent square containing the most halite\n                if ship.cell.halite < 100:\n                    neighbors = [ship.cell.north.halite, ship.cell.east.halite, \n                                 ship.cell.south.halite, ship.cell.west.halite]\n                    best = max(range(len(neighbors)), key=neighbors.__getitem__)\n                    ship.next_action = directions[best]\n            if ship_states[ship.id] == \"DEPOSIT\":\n                # Move towards shipyard to deposit cargo\n                direction = getDirTo(ship.position, me.shipyards[0].position, size)\n                if direction: ship.next_action = direction\n                \n    return me.next_actions","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The line `%%writefile submission.py` saves the agent to a Python file.  Note that all of the code above has to be copied and run in a single cell (please do not split the code into multiple cells).\n\nIf the code cell runs successfully, then you'll see a message `Writing submission.py` (or `Overwriting submission.py`, if you run it more than once).\n\nThen, copy and run the next code cell in your notebook to play your agent against three random agents.  Your agent is in the top left corner of the screen.","metadata":{}},{"cell_type":"code","source":"from kaggle_environments import make\nenv = make(\"halite\", debug=True)\nenv.run([\"submission.py\", \"random\", \"random\", \"random\"])\nenv.render(mode=\"ipython\", width=800, height=600)","metadata":{"scrolled":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Your agent should perform much better than the random agents!  Note that if your ship doesn't move at all in the game, then you've likely made an error in the code you used to generate the **submission.py** file.  If this is the case, try copying the code cell and running it again.","metadata":{}},{"cell_type":"markdown","source":"# Part 3: Keep learning!\n\nThis first agent is just the beginning.  Over time and with effort, your score will gradually improve.  Here are some resources to keep learning:\n\n- The first step is to read the **[complete game rules](https://www.kaggle.com/c/halite/overview/environment-rules)**.  For simplicity, we've only covered a subset of the rules here.  But, you'll need a complete understanding of the game dynamics to come up with a winning strategy.\n- The agent you just submitted uses Sam Harris' **[Halite SDK](https://www.kaggle.com/sam/halite-sdk-overview)** to simplify the code we need to write.  Check out the notebook to see what other helper functions are available.\n- Look at the **[Notebooks tab](https://www.kaggle.com/c/halite/notebooks?sortBy=voteCount&group=everyone&pageSize=20&competitionId=18011)** in the Halite competition to learn from agents that other users have created.  \n- Kaggle's **[Intro to Game AI and Reinforcement Learning](https://www.kaggle.com/learn/intro-to-game-ai-and-reinforcement-learning)** course is a great resource to get started with techniques for creating intelligent agents.","metadata":{}},{"cell_type":"markdown","source":"---\n\n\n\n\n*Have questions or comments? Visit the [course discussion forum](https://www.kaggle.com/learn/intro-to-game-ai-and-reinforcement-learning/discussion) to chat with other learners.*","metadata":{}}]}