Jon Thysell

Father. Engineer. Retro games. Ukuleles. Nerd.

Creating an AI to play Hive with Mzinga, Part II

In my last post, I introduced Mzinga, my attempt at an open-source AI for the board game Hive. In this post, I want to go through how the Mzinga AI works and what I’m doing to make it better.

Like many chess AIs, the algorithm I used for the Mzinga AI is called Minimax. At a high level, the decision making goes something like this:

  1. Determine how many moves ahead I want to look (let’s say 2).
  2. List out all of the valid moves that I, the current player could play.
  3. Try a move.
  4. After I’ve tried a move, calculate the board’s “score” with an evaluation function. Higher  (positive) numbers mean I’m doing better than my opponent, and positive infinity means that I’ve won the game. Lower (negative) scores mean my opponent is doing better than me, and negative infinity means my opponent has won the game. (We’ll come back to this in Part III).
  5. If the game isn’t over, list out all of the moves that my opponent could play at this point.
  6. Try a move.
  7. Again, calculate the board’s “score” with the evaluation function.
  8. Repeat steps 6-7 for each of my opponent’s possible moves (from that 2nd turn)
  9. Repeats steps 3-8 for each of my original possible moves (from that 1st turn)

The algorithm is called Minimax, because for each player’s turn, the AI assumes that the player will take the move that gets them the best score. I’m called the “maximizing” player because for my turns, I’m going to take the move that maximizes the score. My opponent is called the “minimizing” player, because I assume they’re going to take the move that minimizes the score.

By looking ahead, I can modify the score of an earlier move – ie. a move on my first turn might look great for me, but it may turn out that it opens up a really great move for my opponent. Since I assume they’re always going to take the best move, I replace the score of my move to equal the score of the move they’re most likely going to take. That way I don’t take the move that will screw me later.

After all of the calculations are done, I look at the original set of moves available to me, and I pick the one with the best score and actually play it.

Now, a key part of this working is the part where I “calculate” a board’s score. I’ll get into that next post, because there’s a few more things to note. First, doing that calculation, whatever it is, usually takes some time. So the more moves you look at (whether because a player has lots of moves to choose from, or because you’re searching more moves ahead) the longer it takes to come to a decision. So a lot of science goes into reducing how long it takes to calculate a board’s score, and how to avoid looking at some moves all together.

To reduce how long it takes to calculate a board’s score, I use a Transposition Table. Basically, since I’m playing a game where you take turns moving one piece at a time, there’s a good chance that I’m going to end up in the same layout of pieces, or position, at some point in the future. So, as I’m going along calculating board scores, I save them off. That way, when I see a position that I’ve seen before, I can just reuse value I’ve saved. As the game progresses, that table gets bigger and bigger, and I have more saved off values to reuse.

To reduce how many moves I look at, I use Alpha-Beta Pruning. Essentially, it means that if I’m looking through a player’s moves, there are times when I know that there’s no point in looking anymore. If I do move A and while looking through my opponent’s possible responses I see a move that wins the game for them, I don’t need to look at any more moves that would come after playing move A. I assume that playing move A will lose me the game.

The final thing I do is something called an iterative search. The deeper the depth of your search, the exponentially longer it takes. The game wouldn’t be very fun to play if the AI takes hours to decide what to do. Conversely, if the depth is too low, then the AI will be considerably weaker, since it doesn’t “think ahead”. So instead we do an iterative search.

It turns out that Alpha-Beta Pruning is most effective when you look at the “best” moves for each turn first. Only, if we already knew the best moves, we wouldn’t need to search! To help Alpha-Beta pruning out, what I do is:

  1. Search to a depth of one, ie. just looking at my move and not my opponent’s response.
  2. Sort my moves from best to worst.
  3. Search again but now to a depth of two, looking at both my moves and my opponent’s responses.
  4. Sort my moves again from best to worst.
  5. Search again but now to a depth of three, looking at both my moves, my opponent’s responses, and my next move.
  6. And so on, and so on…

Instead of having a set depth to search, I instead set a time limit on my search, say five seconds. I start searching deeper and deeper, each time resorting the moves better and better, until I run out of time. Combined with the fact that I’m saving off board scores as I go, each search iteration gets faster and faster as I see the same board positions over and over.

Now, a lot of code is spent making these operations go as fast as possible, but at the end of the day, the everything hinges on how good your AI is at evaluating a board’s position. The faster and more accurately you can rate who’s “ahead”, the stronger your AI will be.

Stay tuned for Part III, where I go more into detail about how the AI evaluates board positions and how I’m trying to improve it.

Try out Mzinga today!

/jon

Update (15-JUL-2016): Creating an AI to play Hive with Mzinga, Part III is up.

Creating an AI to play Hive with Mzinga, Part I

I first started playing chess seriously in college, and I learned just enough to realize that I wasn’t going to be able to commit to the kind of study that makes a great chess player. I even built a super weak chess AI in Matlab that just made random moves. More recently I’ve gotten back into playing over at Chess.com (hit me up for a game), and when I was looking for a side project last winter, I peered back into the deep and treacherous waters of chess AI programming.

But I’d already built a chess AI (dumb as it was) and wanted to do something new. Then it occurred to me that I could try to make an AI for another game I love to play, Hive.

What is Hive? Hive is an abstract board game (like chess) where the pieces are different kinds of bugs. Each bug moves in a certain way, and the goal is surround your opponent’s Queen Bee before they surround yours. Like chess in many ways, but simpler and more approachable to many people.

So I started looking around to see if anyone had already created any Hive AIs. While there is some software for playing Hive (play Hive online at Boardspace, with the PC game from BlueLine Games, or via various mobile apps) and that software usually has an AI player to play against, I couldn’t find anyone specifically trying to make a strong Hive AI player.

The chess world on the other hand, is loaded with people trying to make better chess AIs. The amount of available chess AIs (see this list of chess engines for example) and publicly available research material (see the Chess Programming Wiki) is simply astonishing.

One of the coolest aspects of it is the separation of the chess engine (where the AI does its work) and the UI (which just displays the game). There are well established protocols that chess engines can implement (such as the Chess Engine Communication Protocol or the Universal Chess Interface) to specify how you ask a chess engine to evaluate a board and pick the best move. This means that by implementing these protocols, chess programmers don’t have to agree on what programming language to use, or waste time making pretty interfaces. They can focus on the guts of their engine, using whatever tools they want, and they’ll be able to participate in games against both humans and other chess engines.

It’s with that model in mind that I started work on Mzinga.

Mzinga 0.9 ScreenshotMzinga is an open-source AI to play the board game Hive. It is architected similar to various chess-playing AIs, consisting of:

  • A set of standardized commands similar to the Universal Chess Interface
  • An command-line reference engine, which accepts the standardized commands
  • A general board UI which can interface with any engine that implements the standardized commands

The goal is not to simply implement Hive in code, but to establish a standard way for programmers to create their own AI players. The hope is that this will encourage explorations around Hive AI.

It’s written in C# (see the Mzinga source on GitHub) and runs on Windows 7 and above. You can play player vs. player, player vs. cpu, or cpu vs. cpu. It’s very beta – the included AI is not very strong, and the UI is a little bare, but it is very playable. Check it out and let me know what you think!

Stay tuned for Part II, where I go more into detail about how the AI works and what I’m doing to improve it.

Try out Mzinga today!

/jon

Update (14-JUL-2016): Creating an AI to play Hive with Mzinga, Part II is up.

Consolidating the Sega Genesis, Sega CD, and Sega 32x power supplies

As I’ve mentioned before, the Sega Genesis was my first and favorite childhood gaming console, and though over the years I’ve come to rely on emulators, re-releases and clone systems to get my Sega nostalgia, I recently decided to set up some original hardware.

Whether you’re new to the system, or a long-time fan, the holy trinity is to get a Sega Genesis along with its two biggest add-ons, the Sega CD and the Sega 32X. Now, one of the major annoyances is that each has its own wall-wart power supply, which are a pain to use: they’re hard to get situated on power strips due to their size and they generate a lot of heat, even with nothing turned on.

I thought there had to be a way to have a single consolidated power supply that supports all three systems at once. And after a little research, I found two solutions:

  1. The Sega Trio, which is a commercial power supply made specifically to solve this problem at the reasonable cost of $28.99. Only problem seems to be the very limited availability.
  2. Follow what others have done (see this forum post), and build my own custom harness on top of a generic power supply.

So I decided to build my own, and document the build along the way.

The Investigation

The first step was to collect all of the relevant power requirements for each system (thanks to this page for a lot of it). For my own setup, I have a model 2 Genesis, model 2 Sega CD, and a 32X. Here’s what the original power supplies look like:

System Voltage Amperage Plug Type Polarity
Sega Genesis Model 2 10V 0.85A 1.7mm Pos. center
Sega CD Model 2 9V 1.2A 2.1mm Neg. center
Sega 32X 10V 0.85A 1.7mm Pos. center

Now the next step is to find a suitable generic power supply. It is important to note that none of these systems actually needs exactly 9 or 10 volts to operate. In fact, the rating on the label is more like the “average voltage” that adapters of that model produce. So a particular one of these power adapters may actually produce anywhere from 8 to 12V.

This is all fine because the first thing each system does is step down that input power to the steady 5 volts that the chips inside are designed to use.

Since it’s very easy to source 9V power supplies, I’ll go with 9V for my generic.

As for the amperage, I need to add up the ratings of each power supply to get a minimum safe value. Amperage ratings show the maximum amperage that the power supplies can safely provide, not the actual amount the systems will necessarily draw. To be safe, OEM manufacturers typically provide power supplies that can offer slightly more amps than they expect their product to draw at full intensity.

So in the original setup, 2.9A is probably safely above the maximum current I’d expect the three systems to draw at once. Round that up to 3A, and now I’m looking for a 9V, minimum 3A power supply, preferably one that isn’t a wall-wart.

The next consideration is how to get one power supply to have three plugs. So I’m going to need to make or buy some kind of harness to split or daisy-chain three separate plugs. As for the plugs themselves, I have couple of things to consider.

Generic power supplies typically come standard with barrel plugs with a 2.1mm diameter center hole with positive polarity. The Genesis Model 2 and 32X both use the more common positive polarity center. Unfortunately, they use the less common EIAJ-03 barrel plugs with a smaller 1.7mm diameter center hole. The Sega CD Model 2 uses the common 2.1mm center hole, but the less common negative polarity center.

So in both cases I’m going to need some adapters.

At this point I have a spectrum of options. On one end is to buy all raw parts and try to solder up a completely custom harness. More extreme, I could even build my own power supply from scratch. On the other end of the spectrum is to try and get away with buying off-the-shelf cables and adapters.

Building from scratch is fine if you have the time, skills and tools. To save money you’ll need to buy parts in bulk, which is great if you’re going to build a bunch, or might use the parts in other projects.

Anyone can buy off-the-shelf parts and just plug them all together. No special skills required. But you will pay a premium.

For this project, I thought it would be interesting to source off-the-shelf parts, just to prove that I could make it work with no soldering required. Yes it probably wouldn’t look as slick, but anyone could replicate it. Also I was feeling lazy. I can always play cable doctor later and transform the off-the-shelf parts into a slicker, more permanent solution.

Bill of Materials

Item Product Quantity Unit Price
9V 3A DC Power Supply Output 9V 3A AC/DC Power Supply Cord Charger IEC320 C8 Socket Adapter 1 $14.37
AC Power Cord SF Cable, 6ft 18 AWG 2-Slot Non-Polarized Power Cord (IEC320 C7 to NEMA 1-15P) 1 5.75
3-Way DC Power Cable Splitter 1:3 DC Power Splitter Cable Cord 1 Female to 3 Male 5.5×2.1mm Port Pigtals 12V 1 3.99
2.1mm to 1.7mm DC Power Adapter Cable 4.8mm x 1.7mm Male Plug to 5.5mm x 2.1mm female socket DC Power Adapter cable 2 3.59
2.1mm Power Jack Polarity Changer MODE 2.1MM JACK-PLUG POLARITY CHANGER BLACK 68-102-0 1 3.80
Subtotal $35.09
Shipping 4.49
Total $39.58

First off, I’ll say that I didn’t spend a ton of time sourcing the parts. Just a couple days casually browsing Amazon and Ebay. If I found something that looked like it’d work, I bought it. For $40, this is definitely not the cheapest way to do this, but it’s not much worse than buying three new power supplies at $9.99 each.

The nicest thing was finding out that the CCTV security camera market supports an industry of nice DC power cable splitters in a variety of configurations, which was the part I assumed I’d have to make myself.

The Build

Once I had the parts, it was a simply a matter of connecting everything. If it’s not straight-forward for you, it goes like this:

  1. Connect AC cord to the power supply.
  2. Connect the 3-way splitter to the power supply.
  3. Connect each of the two 2.1mm to 1.7mm adapter cables to a cable coming out of the 3-way splitter (one each for the Genesis and 32X).
  4. Connect the 2.1mm polarity changer to the remaining cable coming out of the 3-way splitter (for the Sega CD).

The end result should look something like this:

Since the plugs have different sizes, it shouldn’t be too hard to figure out which plug connects to each system. For the sake of simplicity, I put a bit of colored tape on each: red for Genesis, blue for CD, yellow for 32X, corresponding with the primary colors of the game boxes for each system.

The power supply works like a charm. I’m free from the three-wart tyranny!

Have questions or comments? Sound off below.

/jon

Chordious 2.0 Preview available for download

Just a quick message, I’ve been feverishly working on the next version of Chordious, and today have just announced the first “preview” build of Chordious 2 for Windows. It’s not 100% complete, but I think there’s enough there to start gathering feedback.

Chordious 2.0 Preview

Find out more in the kick-off blog post: Try out the Chordious 2 Preview for Windows.

/jon

Building a custom retro console running RetroPie

Ever since I first heard about Raspberry Pi and the RetroPie project, I’ve wanted to build a retro console. Something with all my favorite old game systems emulated in a compact classy box, with nice controllers and fully customizable.

Back in the day I used to have a soft-modded Xbox original to play retro games, but it was loud, bulky, and the controllers weren’t great. When I got my first Raspberry Pi, I tried to make my custom console, but I ran into several problems:

  1. Power issues: A non-clean shutdown meant corrupting the SD card, which isn’t user-friendly, and no power switch
  2. Weak ports: Connecting straight to the light-weight Pi meant it was often left hovering in the air, which would strain the HDMI and USB connections
  3. Available cases: Raspberry Pi cases all seem to fall into the category of tight as possible, giving no internal room to address 1 and 2 above

My first successful attempt was of course building the Picade, but it has two major limitations:

  1. One player only
  2. Kind of heavy to play on a couch

Since then I’ve been planning a new machine. The goal has been a small, two-player console that connects to modern TVs. Then after I discovered this lovely Polycase ZN-40 electronics enclosure, I new it was time to get to work. Yesterday was Pi Day, and I’d just cloned my Picade SD card, so I decided to finally try putting a console together.

It went together way faster than I anticipated! Now I can’t wait to make a couple more: one for home, one for work, one for the game room… the opportunities are endless.

Okay, enough typing, time to play!

/jon

P.S. Here’s a quick video and some development pics:

 

retroconsole01 retroconsole02 retroconsole03 retroconsole04 retroconsole05 retroconsole06 retroconsole07 retroconsole08 retroconsole09 retroconsole10 retroconsole11