Wednesday, January 30, 2013

Qt

Yesterday I settled on using Qt to build the gui version of my Tic-Tac-Toe app. There's still some weirdness because all the documentation is written in c++, but that's not really an issue. The problem I'm starting to see is that my app is not really built with a gui in mind. It works just fine as a console application. The game runs and asks for input or prints output whenever it needs to. With the gui, I need a way to "drive" the game. I think I need to be able to say, "Ok, the gui's ready. Now take a turn game. Oh and here's some input because it's a human player's turn." This is conjecture right now because I'm still trying to design the gui and figure out how to make Qt do what I want.

I had intended to spend today working on that, but plans changed. This morning I got pulled into helping prepare for the apprentice class. At first I wasn't sure what I was getting myself into, but it was actually really interesting. The project is an extension of the last homework in that it still deals with the stock market. Instead of posting prices to a stock exchange, the stocks put their prices into a tuplespace server. The server holds on to these lists of data and hands them out to whoever requests them. The idea is that an arbitrary number of things can all operate in different processes using the data and not get in anyone's way. The really fun part about this is that the project is a sort of competition for which pair can make the most money once the project is due. It's going to be interesting to see all the different strategies.

Monday, January 28, 2013

Oh, GUIs

I managed to add in a menu system to my Tic-Tac-Toe program on Friday. It was rudimentary. There was a prompt for each player and the user could select Human, Dumb Ai, or Smart AI. Simple, but it got the job done.

This morning, I turned my io class into a wrapper for something that will actually do the input/output. This allows me to pass in an object like StringIO for a test when I want output to essentially go nowhere and Kernel when I want it to go to the command line.

My hope was that this would allow me to easily pass in some sort of gui object and I'd be off and running. That would imply that I easily selected a gui library. I didn't. There seemed to be roadblock after roadblock. This one was poorly maintained or that one wasn't documented or another didn't work on macs right now. Maybe tomorrow I'll have better luck.

Thursday, January 24, 2013

Refactoring

I spent a lot of today refactoring my Tic Tac Toe program. There's something very satisfying about optimization. Most of what I did was to make it easier to implement the controls that will select what kinds of players are added to the game. The player and ai are now the same class. The difference is in what strategy they use to make their moves. A human will use an input strategy. An ai player uses a dumb strategy or negamax. There could be other strategies in the future. Things were going smoothly until I got to adding the new code. Then I stalled. I know what I need to do, but I'm having trouble taking the first steps. With everything that I've learned so far, this means that I'm trying to take too big of a step. Hopefully I can work this out tomorrow.

Wednesday, January 23, 2013

Now Do This

So, this phase of my Tic-Tac-Toe project is complete. I can't say how long I'm going to have to continue with this game but it's going to be long time. The image I got was that I will never want to play this game again by the end. Oh well, at least I'm learning.

I was given my next two assignments. Add support for choosing players and easy/hard ai and add a gui while still supporting the command line. I started on the first part by doing some necessary refactoring. My program is improving, but until I work out some issues it isn't working as expected yet. Hopefully the first assignment doesn't take me too long. In the meantime, I need to investigate some graphical frameworks.

Tuesday, January 22, 2013

Relative Depth

There isn't much to say about today. I fixed a few problems with my code. One of them was to prioritize winning moves that take fewer steps over ones that take more. This required a surprisingly trivial modification to my negamax algorithm. That's great when you don't make any typos. It cost me at least half an hour of frantic searching this evening to figure out how I could have improperly done negamax. In the end, it was because of an equals sign in a function call.

I also completed a test to run all possible player moves and make sure my ai is unbeatable. I'm pretty confident that it works. It worries me that it only executes about 1400 moves. I guess that's right though because the ai should never lose and that cuts out a ton of possible outcomes. As I said, I'm confident but not too confident.

Monday, January 21, 2013

A New Day

Today was mostly spent refining. I made a few modifications to my ai's get_move function to cut down on the time spent computing moves. For an empty board it could take ten to fifteen seconds to calculate a move. After adding a few shortcuts, it doesn't take more than two or three seconds to get any single move. I also added some much needed gui messages. Now it prints whose turn it is and a winner at the end. Before the game was a little confusing to play if you weren't used to it. One thing I want to work on next is seeing if I can't get the AI to play for a larger board. I tried running negamax for a 4x4 board but after twenty minutes it hadn't returned any results. This isn't a requirement, just something I'm curious about.

There was also a new apprentice event today. We met for a talk and afterwards were given a small pair homework assignment. The topic today was the observer pattern. The homework is to implement a stock that is held by a stock exchange and is reported on by a stock ticker. Whenever the stock updates its price, it sends a message to anything watching it and then goes about its business. The idea is that what is watching never has to ask for an update. These events seem like they'll be fun and a good way to work on stuff with the other apprentices.

Sunday, January 20, 2013

Catching Up

So far I haven't been good about daily updates. This is my attempt to catch up on the last week-ish of progress. The timeline for events might be a little off because I'm doing this late. I guess it's more incentive to keep on top of this.

Tuesday - I'd been having trouble figuring out how to implement my main game loop "run". I couldn't think of how to test it. I thought about it for a while but rather than end up wasting too much time I asked Brian. He explained that I shouldn't be testing the implementation of the code. Instead I should be testing the behavior. With that in mind, I wrote tests for and implemented a game_over? function. My test for the main game loop then became "is game_over? true when run is finished?".

Wednesday - At this point I could check that the game was over but not who won. To fix this, I extracted the winner checking code and put in a function called winner. This simplified things a little. My next task was to implement a simple AI player. This required changing my Player class to implement a method called get_move. This allowed me to have the game ask the current player for their move regardless of whether it is a human or the computer.

Thursday - I finished the AI player and was told to make it smarter. There was a specific way I was supposed to make it smarter. I needed to implement the Minimax algorithm. To do that, I first needed to understand it. This required most of my time on Thursday. Looking back, I honestly didn't get it. I couldn't understand how to test it and still hadn't figured out how it worked on a low level by the end of the day. Now it seems so simple. Essentially it checks every possible move combination on the current board and scores it. The goal is to find the move or moves that give the AI the best move that is the worst for the opponent. In Tic-Tac-Toe this translates into if two AI players use this and play against each other then they will always draw.

Friday - I was still having trouble with the Minimax. My mentor recommended looking at the Negamax implementation of Minimax because it is simpler and only involves one function call. I asked a few other apprentices how they had tested it and didn't really make any real progress. This was frustrating because Wikipedia outlines the algorithm in easy to implement pseudo-code but has not advice for implementing it with TDD.

Weekend - I finally started to make some progress. I wrote some sample boards and checked the score that came back from Negamax. It took a while to get this right because I was still having some trouble with understanding how to implement it. I'd given up trying to test it and implement it piece by piece though. Without help, I just couldn't do it. After some web searching though, I came across the vital clue to what I was doing wrong. I needed to take the negative of the result I got out of Negamax. After that, I could no longer beat the AI on my command line interface. This was good, but I still needed tests. In the end, I tested that the function returned the correct move/moves in a number of specific situations. Hopefully that's what I was supposed to do and that I won't get in trouble for doing my TDD a bit backwards this time.

Anyway, two things to take away from this post for me.

  1. Write these on time so that I don't have so much work to do.
  2. I keep trying to enter Vim shortcuts into this web interface, so they must be sinking in.

Monday, January 14, 2013

Being Professional

Friday I received my first reading assignment. It was The Clean Coder. It wasn't a very long book, but I feel like it had a lot to say. Honestly, it was intimidating. The requirements laid out in the book for being a professional are very strict. Things like always taking responsibility for mistakes and time management don't seem too bad at first. When you add in how to say yes or no, how to estimate a project's time, and communicating clearly with other people it was all pretty heavy. I found myself agreeing with most of the requirements but I don't know how I could live up to all of them right now. I think that the book is best taken as a goal that you will never achieve. At least there's something to work towards.

On the Tic-Tac-Toe front, I've still been trying to get the game into a playable state. This means handling input, drawing the board, handling win/draw conditions, and then tying them all together. I've gotten the first two working and have already figured out how to check for a win/draw. I need to write the tests and then the code. I was a little stuck today because I was focusing on how to test the main game loop. The problem was that what terminates the game loop is a game over condition and I didn't have anything that would generate that. So after some trial and error, I changed course and began checking win/draw. I am happy because I figured out a way to check all the necessary combinations for a win with a formula. That way it works if I want to play on a 4x4 board. No such luck in 3d, but that's ok. I'd be worried if it somehow worked.

Thursday, January 10, 2013

Slow Progress

Today marked day two of my apprenticeship. My goal was the same, continue working on my Tic-Tac-Toe program. I had made some progress the previous day but moving forward felt sluggish. Trying to write code using TDD feels like a barrier has been erected between my brain and the computer. It's probably bad practice, but my normal approach to coding has been to put down some code, play with it, tweak it, and ultimately keep it or reject it. The necessity of writing a test first causes me to try to think of a test for code that hasn't been conceived yet. This leads to blockage.

During my morning meeting with my mentor, I explained some of this and he reminded me that I can still design the software first. I had somehow forgotten about this in my focus on writing a test first. Tests are important but they have to come from somewhere. A design is a logical origin. It's funny though, as much as I enjoy using computers for tasks, it's so much more enjoyable to draw a design on paper.

Perhaps another reason work felt slow was because I am still getting comfortable working in vim. Most of my previous programming work has been in GUI-based text editors and IDEs. I've used vim before but mostly for editing a Linux config file or two. Right now it's taking some getting used to. I keep hitting the wrong keys or have to think for a moment about what I want to do. Today was easier than yesterday, so here's hoping that feeling continues. I still don't have a strong opinion on the benefits of vim, but after seeing how many people in the office use a console editor, I feel it might make working with them easier.

As for progress on my program, the game creates a board and two players. The players can make moves on the board, but only the first player. I haven't added rotating turns yet or win/lose conditions or a whole bunch of things. I'm not sure I like where I've put getting the input. Right now console input is read in the Player class. Thinking about it though, the game doesn't care which player is typing the input or where the input is coming from. It just wants input. I should probably write a more generic get_input function for the game class that takes a prompt and returns the input. Still have to deal with invalid selections and quitting the game, but I'm not going to worry about that at this hour. At least I have an idea of where to start tomorrow.

Wednesday, January 9, 2013

Day 1

My first day at 8th Light was pleasant. After some initial setup, I was given my first task. Write a Tic-Tac-Toe game from scratch using TDD. Not earth-shattering, but still challenging. Thinking in terms of TDD doesn't come naturally right now. Thus progress was slow. I started by building the board and working from the bottom up. After some trouble, my mentor advised me that it might be easier to start from the top and work on making a move. Perhaps a different perspective on the problem will help.

The day ended the same as it began, with a handshake. I learned that everyone is expected to shake hands when they arrive in the morning and leave in the evening. I wasn't sure what to think of this. It seems like a small gesture. Thinking about it now, it marked a distinct beginning and end to the day and set a friendly tone in the office. It will also force me to learn everyone's name, something I should be better at.