A simple AI experiment using React and Redux
By Chris Uehlinger
When I got started at my first job, my mom bought me a desk toy called "Aristotle's Puzzle". The rules of the game are fairly simple:
- You have 19 wooden hexagons, numbered 1-19
- You must arrange them in the hexagonal tray, using all 19 numbers
- All of the rows, left diagonals and right diagonals must add up to 38
Here's a version you can play right now. Each hexagon is an HTML
<input> element. If you fill in a row or diagonal, but the sum is not 38, it will be highlighted in red. If it does sum to 38, it will be heighlighted in green. Give it a try:
I find this game interesting because of the different responses it gets from different people. Some people tinker with it for a little bit before giving up. Some people start thinking about the number theory ideas at work here, and how this puzzle could be solved with pencil and paper. I immediately started thinking about how to make an AI that could brute force the problem.
But not just any AI. I wanted to build an AI I could watch. I wanted to build an HTML5 version of the game, and then have an AI play it, but using the same interface humans would use. A while back, I threw together a 2048 AI that essentially hooked itself into the game and "played" by issuing moves into the same functions that were called when players interacted with the game.
Here's what I came up with:
I'd done some work with React before, and took this as an opportunity to brush up on some of the newest technologies in the React ecosystem. To that end, this project made use of pure-function React components, Radium-inspired CSS-in-JS styling, Redux for state management and Webpack/react-hot-loader for my build process.
React's new purely functional components are truly fantastic, they really boil down the essence of what a React component is meant to be, and I think they will make it much easier to teach about React in the future. The CSS-in-JS styles were interesting, and definitely had some big upsides, but I'm not entirely sold on the approach. Frameworks like Radium need to truly tackle media queries, pseudo selectors and pseudo-elements before I can start looking at this as a serious idea for production apps. React-hot-loader knocked my socks off. If you haven't tried it, try it. Pull down this repo, fire it up in the browser with the AI running, and make a couple changes to one of the smaller components. It's the kind of thing you need to see to believe.
But in the end, it was Redux that made this whole thing possible. Redux provided hooks so that my React components and AI could feed actions into the same shared piece of state. Interactions with the UI and decisions made by the AI would be processed through the same "channel". If things were acting weird, I could replay the AI's steps myself and see where things went wrong. Having worked with React+Flux before, Redux is an all-around improvement, taking an interesting architecture and making it streamlined and more flexible. Redux has me really excited for the future of the React ecosystem.
Click the button below to fire up 5 AIs at once. Redux stores are so powerful and flexible, the app and the AI can be decomposed and spun up in parallel: