Training Data Deep Learning - Halite II 2017 Artificial Intelligence Competition p.5




Welcome to the next part of the deep learning with Halite II tutorials. In the previous tutorial, we created an example bot that just chooses randomly between mining empty planets, mining our own planets, and attacking the enemy. In this tutorial, we're going to write a script to automatically play games with this bot versus itself, and then we'll take just the moves of the winning player, saving them as training data for an AI.

I didn't see any clear way to log "who" won the game via the typical CLI. I did see that Halite has hosted all of their code on GitHub, including for running a game server, so I probably could have done it with that, but it seemed like more work than just simply parsing the output from console, so that's what I did.

I want to run these games automatically, parse the output, and save the winner, so, to begin, let's import os and run a game:

import os

os.system('halite.exe -d "360 240" "python MyBot-3-choices-1.py" "python MyBot-3-choices-2.py" >> data.gameout')

In my case, I named the script we were working on before as MyBot-3-choices, and then the version number. The only difference between MyBot-3-choices-1.py and MyBot-3-choices-2.py is the VERSION constant. That's all we need to do to run the game and store the output to a file. Instead of outputting to a file, you can also check output with subprocesses. Feel free to do that instead if saving to a temporary file keeps you up at night.

Next, we're going to read this file. We could use regular expressions, or just a series of splits. I'll go with the latter.

with open('data.gameout'.format(num), 'r') as f:
    contents = f.readlines()
    CharlesBot1 = contents[-4]
    CharlesBot2 = contents[-3]
    print(CharlesBot1)
    print(CharlesBot2)

The output, unless there's an error, will always be in this order. The first player's output is 4th from last, and the second player is 3rd from last. We'll output these lines just to be sure.

Aside from the winner, we're also curious about other stats like ships and damage. Some games might just plain not be anything decent. This is random. Maybe both teams do nothing for 300 frames, or maybe they just kill each other. Being aggressive is fine, but, at least initially, we should probably get a solid base of games where the AIs actually mine planets, produce ships, and do some amount of damage, so we don't wind up with an AI that *only* attacks or *only* mines planets.

Now, to parse these lines, which will look something like this:

Player #0, Charles1, came in rank #2 and was last alive on frame #85, producing 7 ships and dealing 1532 damage!

Player #1, Charles2, came in rank #1 and was last alive on frame #86, producing 46 ships and dealing 2172 damage!

We want to get the rank, how many ships, and how much damage:

def get_ships(data):
    return int(data.split("producing ")[1].split(" ships")[0])

def get_damage(data):
    return int(data.split("dealing ")[1].split(" damage")[0])

def get_rank(data):
    return int(data.split("rank #")[1].split(" and")[0])

Then:

with open('data.gameout', 'r') as f:
    contents = f.readlines()
    CharlesBot1 = contents[-4]
    CharlesBot2 = contents[-3]
    print(CharlesBot1)
    print(CharlesBot2)

    CharlesBot1_ships = get_ships(CharlesBot1)
    CharlesBot1_dmg = get_damage(CharlesBot1)
    CharlesBot1_rank = get_rank(CharlesBot1)

    CharlesBot2_ships = get_ships(CharlesBot2)
    CharlesBot2_dmg = get_damage(CharlesBot2)
    CharlesBot2_rank = get_rank(CharlesBot2)

    print("Charles1 rank: {} ships: {} dmg: {}".format(CharlesBot1_rank,CharlesBot1_ships,CharlesBot1_dmg))
    print("Charles2 rank: {} ships: {} dmg: {}".format(CharlesBot2_rank,CharlesBot2_ships,CharlesBot2_dmg))

Then, let's add the winner's moves to the training data:

if CharlesBot1_rank == 1:
    print("c1 won")
    player_1_wins += 1
    if CharlesBot1_ships >= ship_requirement and CharlesBot1_dmg >= damage_requirement:
        with open("c1_input.vec","r") as f:
            input_lines = f.readlines()
        with open("train.in","a") as f:
            for l in input_lines:
                f.write(l)

        with open("c1_out.vec","r") as f:
            output_lines = f.readlines()
        with open("train.out","a") as f:
            for l in output_lines:
                f.write(l)

            
elif CharlesBot2_rank == 1:
    print("c2 won")
    player_2_wins += 1
    if CharlesBot2_ships >= ship_requirement and CharlesBot2_dmg >= damage_requirement:
        with open("c2_input.vec","r") as f:
            input_lines = f.readlines()
        with open("train.in","a") as f:
            for l in input_lines:
                f.write(l)
            
        with open("c2_out.vec","r") as f:
            output_lines = f.readlines()
        with open("train.out","a") as f:
            for l in output_lines:
                f.write(l)

For now, let's set the ship requirement to 10 and damage to 1000:

ship_requirement = 10
damage_requirement = 1000

Finally, we just want to loop this a bunch, so let's do that:

import os
import time

ship_requirement = 10
damage_requirement = 1000


def get_ships(data):
    return int(data.split("producing ")[1].split(" ships")[0])

def get_damage(data):
    return int(data.split("dealing ")[1].split(" damage")[0])

def get_rank(data):
    return int(data.split("rank #")[1].split(" and")[0])

player_1_wins = 0
player_2_wins = 0

for num in range(5000):
    try:
        print("Currently on: {}".format(num))
        if player_1_wins > 0 or player_2_wins > 0:
            p1_pct = round(player_1_wins/(player_1_wins+player_2_wins)*100.0, 2)
            p2_pct = round(player_2_wins/(player_1_wins+player_2_wins)*100.0, 2)
            print("Player 1 win: {}%; Player 2 win: {}%.".format(p1_pct, p2_pct))

        os.system('halite.exe -d "360 240" "python MyBot-3-choices-1.py" "python MyBot-3-choices-2.py" >> data.gameout')

        with open('data.gameout', 'r') as f:
            contents = f.readlines()
            CharlesBot1 = contents[-4]
            CharlesBot2 = contents[-3]
            print(CharlesBot1)
            print(CharlesBot2)

            CharlesBot1_ships = get_ships(CharlesBot1)
            CharlesBot1_dmg = get_damage(CharlesBot1)
            CharlesBot1_rank = get_rank(CharlesBot1)

            CharlesBot2_ships = get_ships(CharlesBot2)
            CharlesBot2_dmg = get_damage(CharlesBot2)
            CharlesBot2_rank = get_rank(CharlesBot2)

            print("Charles1 rank: {} ships: {} dmg: {}".format(CharlesBot1_rank,CharlesBot1_ships,CharlesBot1_dmg))
            print("Charles2 rank: {} ships: {} dmg: {}".format(CharlesBot2_rank,CharlesBot2_ships,CharlesBot2_dmg))

        if CharlesBot1_rank == 1:
            print("c1 won")
            player_1_wins += 1
            if CharlesBot1_ships >= ship_requirement and CharlesBot1_dmg >= damage_requirement:
                with open("c1_input.vec","r") as f:
                    input_lines = f.readlines()
                with open("train.in","a") as f:
                    for l in input_lines:
                        f.write(l)

                with open("c1_out.vec","r") as f:
                    output_lines = f.readlines()
                with open("train.out","a") as f:
                    for l in output_lines:
                        f.write(l)

        elif CharlesBot2_rank == 1:
            print("c2 won")
            player_2_wins += 1
            if CharlesBot2_ships >= ship_requirement and CharlesBot2_dmg >= damage_requirement:
                with open("c2_input.vec","r") as f:
                    input_lines = f.readlines()
                with open("train.in","a") as f:
                    for l in input_lines:
                        f.write(l)
                    
                with open("c2_out.vec","r") as f:
                    output_lines = f.readlines()
                with open("train.out","a") as f:
                    for l in output_lines:
                        f.write(l)

        time.sleep(2)
    except Exception as e:
        print(str(e))
        time.sleep(2)

Notice the sleeps. You need some amount of sleep in here, or strange things happen. The game repeats itself for some reason. It's something with the halite.exe. Feel free to try to find the sweet spot. At some point, the output gets repeated twice, and is quite annoying!

I am also tracking winning and losing percentages with this, just for my curiosity. Alright, run at least a few hundred games. I did 5,000 overnight. Once that's done, I will see you in the next tutorial for training a model!

The next tutorial:





  • Introduction - Halite II 2017 Artificial Intelligence Competition p.1
  • Modifying Starter Bot - Halite II 2017 Artificial Intelligence Competition p.2
  • Custom Bot - Halite II 2017 Artificial Intelligence Competition p.3
  • Deep Learning - Halite II 2017 Artificial Intelligence Competition p.4
  • Training Data Deep Learning - Halite II 2017 Artificial Intelligence Competition p.5
  • Training Model Deep Learning - Halite II 2017 Artificial Intelligence Competition p.6
  • Deploying Model Deep Learning - Halite II 2017 Artificial Intelligence Competition p.7