Sunday, November 25, 2012

Developing a Developer: Weekly Report 3

I'm on chapter 17. The Pygame part has started. This week has been interesting.


Cartesian Coordinates

If you know some basic maths, programming Cartesian coordinates changes a little bit your mindset. Usually, you put the X axis horizontally and the Y axis vertically. Going to the right means a greater value for the X coordinate and going to the left means a lower value; while going up means a higher value for the Y coordinate and going down means a lower value on that coordinate. When we program, it isn't always like that. Usually, the origin (0, 0) is at the top left corner on the screen, and while going to the right still means a greater value for X, going down now means a greater value for Y. It might sound confusing at first, but you get used to it very quickly.

However, this isn't a problem I struggle with when working with a Cartesian coordinate system. I do have experienced a little bit of confusion while I was reverse engineering the Reversi game. The board uses a Cartesian coordinate system, being the top left corner the origin. The problem comes when you have to assign values to the coordinates and then display them.

Let's imagine we want to assign different values to each place on the board. The code could look something like this:

for x in range(row_size):
    for y in range(column_size):
        matrix[x][y] = value


Imagine that row_size = 2 and column_size = 2. The result would be something like:

matrix[0][0] = value for 0, 0
matrix[0][1] = value for 0, 1
matrix[1][0] = value for 1, 0
matrix[1][1] = value for 1, 1


It makes perfect sense. The first coordinate (x) comes first and then the second one (y). Nevertheless, if we tried to print the board following the same fashion:

for x in range(row_size):
    for y in range(column_size):
        print_on_board(matrix[x][y])


We end up getting something like this:


Value for 0,0
Value for 0, 1
Value for 1, 0
Value for 1, 1


If we use the previous algorithm, the computer will swap the X and Y axis. We don't want that happening. In order to avoid that we must use the following code:

for y in range(column_size): # Print each row
    for x in range(column_size): # Print each value on the same row
        print_on_board(matrix[x][y])


This way, we would get the desired result.


AI and Minimax

Chapter 16 of “Invent Your Own Computer Games with Python” by Al Sweigart deals with AI simulations. I've done many simulations in the past, in fact, in this very blog you can look at some I made about the Risk tabletop game. At university I had a few subjects about Artificial Intelligence and I thought it was a good idea to apply something about Game Theory in a game like Reversi. So, I decided to implement my own AI for Reversi. I've implemented the Minimax algorithm.

In very rough terms, Minimax is about choosing the option that gives us more profit taking into account that our adversary will choose the option that will give us the least. Let's imagine that in a certain game I could choose between two options: A and B. If I choose A, my opponent can choose between giving me 3 points or 2 points. If I choose B, the opponent can choose between giving me 20 points or 0. In this example, we minimize damage by choosing option A. Minimax considers that the opponent will choose 0, so it's better to take at 2 (in the worst scenario after going for A) than 0 (even if we know that by choosing B we have a chance of getting 20!). A human being might attempt to choose B hoping that his opponent will choose to give him 20 points by mistake, but that's not the way machines think.

In Reversi, we usually have more than 2 options (legal moves) and the game involves more than just one decision for the player to take (it easily lasts 40 moves). In other words, the depth of the search for the solution is greater. In the previous example, the depth is one. We analyze only one move forward for the player and one for the opponent. My AI implementation will analyze 4 moves forward. The benefit for a move will be the number of tiles turned by that move unless we're talking about a corner. My Minimax implementation will assign an infinite benefit to corner moves (in all simulations that I've made before it's clear that getting the corners is always in our benefit). Being this, implemented in Minimax means that the AI will also avoid the opponent claiming them!

You can download the source code for the simulation here, and if you just want to play against the computer (which will use Minimax) you can download the source code here. Remember that these codes are a variation of the ones in the book.

These are the result for the simulations (X is the book's AI and O is mine):

Welcome to Reversi!
Enter number of games to run: 350
Game #0: X scored 31 points. O scored 33 points.
Game #1: X scored 25 points. O scored 37 points.
Game #2: X scored 37 points. O scored 27 points.
Game #3: X scored 32 points. O scored 31 points.
Game #4: X scored 47 points. O scored 17 points.
Game #5: X scored 34 points. O scored 29 points.
Game #6: X scored 27 points. O scored 37 points.
Game #7: X scored 30 points. O scored 34 points.
Game #8: X scored 21 points. O scored 43 points.
Game #9: X scored 21 points. O scored 41 points.
[skipped for brevity]
Game #340: X scored 26 points. O scored 22 points.
Game #341: X scored 32 points. O scored 32 points.
Game #342: X scored 30 points. O scored 34 points.
Game #343: X scored 32 points. O scored 32 points.
Game #344: X scored 38 points. O scored 26 points.
Game #345: X scored 39 points. O scored 22 points.
Game #346: X scored 20 points. O scored 44 points.
Game #347: X scored 18 points. O scored 46 points.
Game #348: X scored 18 points. O scored 46 points.
Game #349: X scored 21 points. O scored 43 points.
X wins 94 games (26.86%), O wins 243 games (69.43%), ties for 13 games (3.71%) of 350.0 games total.


You can download the whole log here. I didn't run more than 350 games because I don't have that much computation time available and it's a fairly big number anyway. In any case, it seems unquestionable that my AI beats the one shown in the book (it wins almost 70% of the games!).


From ASCII Art to Pygame Art

This is my way of saying "Hello World!" with Pygame (see picture below).



Download the source code here.

Monday, November 19, 2012

Developing a Developer: Weekly Report 2


I'm finishing chapter 15 in “Invent Your Own Computer Games with Python” by Al Sweigart. Haven't I said it's a wonderful book yet? At the moment, I'm reversed engineering the Reversi game (it's ironic, isn't it?).

I haven't done anything out of the project programme (except my last post about calculating primes faster). I'm concerned about two things regarding to the project:
  • As far as I know Pygame doesn't work with Python 3 on Linux. This means that I have to continue the training offered in the book (which uses Python 3) in Windows. Perhaps I'll use pgreloaded in my games in the future.
  • How to make single EXE files. I've used tools like py2exe and cx_freeze in the past. It helped me to work my games in computers that didn't have Python installed, but I wasn't able to make a single EXE file nor an installer. I'll have to investigate about this.

That's been my week 2 working on this training project. By next week, I'll have finished the part of the book that deals with text games – mostly using ASCII art – and probably started programming with graphics using Pygame.

Sunday, November 11, 2012

Faster Primes

Do you remember my post about prime numbers? If you don't, you can catch up clicking on the link:
Prime Numbers: A Computational Approach

I've improved the function that checks if a number is a prime number. Here's the new code:

/*
 * Check if "number" is a prime number. If it is, the function will return 1.
 * If it isn't, it will return 0.
 *
 */
int isPrime(long long unsigned number)
{
    if(number == 2)
    {
        return 1;
    }
    else if(number % 2 == 0)
    {
        return 0;
    }
    long long unsigned aux;
    for(aux = 3; aux*aux <= number; aux+=2)
    {
        if(number % aux == 0)
        {
            return 0;
        }
    }
    return 1;
}


The key is the double increment in the for-loop (aux+=2). Apart from 2, all prime numbers are odd numbers. The first thing I do, is check if a prime number is 2. Secondly, I discard the possibility that the number is divisible by 2. Finally, I proceed with the algorithm the same way I did in the first program, but this time I start checking if the number can be divided by 3. And then, I can safely increment the number two units on each iteration (if 2 cannot divide a number, a number that can be divided by 2 won't be able to divide that number either).

This screencaptures (it's about the Unix time command again) show this improvement. I calculate primes up to 10000000 this time.

Old version
New version

You can download the source code with the improved function here.

Saturday, November 10, 2012

Developing a Developer: Weekly Report 1

First week. I've read the first 10 chapters of the first book (Invent Your Own Computer Games with Python). The process I've employed looks something like this:

1 - Copy the source code of the chapter's game.
2 - Read the chapter.
3 - Reverse Engineering (in this step I write a program that does the same, but I do not look into the book nor in it's source code).

This last step is my favourite. I've implemented the games "Guess", "Jokes", "Dragon Realm" and "Hangman". In my version of hangman I've made a few changes. For example, in my version the program reads the words from a file (instead of having them in the source code). You can download my version of the game here (remember that this game is heavily inspired in Al Sweigart's hangman).

I also set up Eclipse (the development environment) and installed the PyDev plugin that makes Eclipse able to work with Python. Setting up PyDev is a piece of cake. The only difficulty I found was configuring the Python interpreter in the environment. I used this tutorial for that purpose:
http://www.vogella.com/articles/Python/article.html

 Finally, I used this program for the diagrams:
https://live.gnome.org/Dia/

Actually, I didn't need to do diagrams, but the book spends a whole chapter on it. I thought it was interesting to get used to flowcharts. In the future, I'll surely need to do them.

Monday, November 5, 2012

Developing a Developer


Hello readers.

In this post I'm going to announce something special. I want to make a little game. It's going to be a small thing, but it's because I promised a friend to make one, and I have to fulfil my promises. It's also the perfect excuse to catch up with this beautiful hobby.

This is mainly a training project. I'll write posts in a journal entry style. That way you can track my progress.

I've divided this project in four phases:
1) The Basis
2) The Tools
3) The Experiments
4) The Games

PHASE 1: The Basis

I'll try to restore the knowledge about game programming I had in the past. It's basically reading this book:




“Invent Your Own Computer Games with Python ” is a free ebook. It's oriented to children that want to make computer games but don't know how to program. When I finished my first programming course (it lasted a year) I realized that I knew many algorithmic things. I knew how to search items in lists, storing integer in arrays, import libraries... It was a very good improvement taking into account that I started without knowing anything about programming. Nevertheless, I didn't know how to do something actually useful. And games... well, it's sort of what we all think of, don't we? So that summer, I found this book and read it. After that I made two simple games, but they were lost one sad day when I accidentally erased all the information in my hard-drive.

PHASE 2: The Tool

It's learning more about game programming but it will be mainly using the Pygame library. Actually, this phase is yet another excuse to read the sequel of the previous book: 


 

I have no idea what it's going to contribute to my knowledge, but I had so much fun reading the first one that I have to read it now.

PHASE 3: The Experiments

This phase it's probably going to be a little bit more chaotic. I'll make a kickoff game that doesn't take a lot of time. Let's see how it goes. I'll also read a few open source programs to take knew ideas. I also may do this kind of things after reading the first book.

PHASE 4: The Game

I'll program the game. I have no idea how long this phase is going to take me. Maybe two weeks? Three? A month and a half? I have an idea about how it's going to be, but I have no idea how I'm going to be posting about it without spoiling the argument. We'll see.