Tuesday, February 07, 2006

Mono

My powerbook is still running! Nice. I still haven't found the motivation to try to work on my PC again. Maybe this coming weekend. Maybe. It's been a tiring week, and it's only Monday. Today I got home from work and fell asleep. I slept from 5 to 9pm. Pretty pathetic. I got up, ate 2 bagels with cream cheese, played 2 pathetic games of poker, 1 pathetic game of chess, and finally decided to try to work on my mono problem. What is mono? The quick answer is that it's an open source version of the Microsoft .NET platform. Why am I using it?  Because I decided to start my senior project for school using the c# language, and without a working windows machine where I can actually install the .NET framework, I needed an alternative.

The worst part about doing it on the mac is there really isn't a good development environment available for it (c#). Sure, they have processes that you can go through to get X installed on the mac, then install the GTK libraries, etc... but it's a bit of a hassle. I actually started down that path for another reason - I wanted to see if I could get any of the Windows Forms stuff running. I actually was able to, but not as easily as the article I was reading would lead you to believe. But that's another story. I'm easily distracted. Anyway, I've decided to use eclipse as my editor of choice for the moment, with the improve-technologies c# plug-in. Which at least does some syntax highlighting. It's pretty archaic, and sometimes I feel like I'm actually working with a chisel and stone, but it works. It does require some flipping back and forth between eclipse and a console window, because although it will compile your code through the editor I haven't found a way to run it through the editor. I suppose I could set it up as an external tool, but that just seems a little lame. The other annoying thing is that every time you save your code, it recompiles it.

Having said that, I'm getting by. I even made some progress tonight. I am now able to create a bitboard (64-bit unsigned long integer with each bit representing a square on the chessboard which is either occupied by a piece, 1, or not, 0. For example, a bitboard of all white pawns in the starting position would look like this:

00000000
00000000
00000000
00000000
00000000
00000000
11111111
00000000

It's ok, you can say it. Wow! The problem that I was having wasn't in the theoretical implementation though. I've been studying bit boards off and on for over 10 years now, since I've always wanted to write a chess program. So I have a pretty good understanding of what and how to use them. The problem that I was having was that c# (pronounced c-sharp) through mono wasn't letting me perform bitwise operations on my bitboard. Why would I want to perform bitwise operations? In this case I wanted a simple function to print out a bitboard. Just so that I could "see" what it looked like. I wanted to call a function such as "printBitBoard", passing it the bitboard I wanted to print, and it would print me a diagram such as the one I demonstrated above. So I needed to perform bitwise operations to see if a particular bit was on or off (0 or 1).

If you're not familiar with bitwise operations, what I wanted to do was perform a bitwise AND operation. The bitwise AND operation takes the source and does a bit by bit comparison with the destination. So, if I wanted to see if I had a pawn on A2 (the 1 on the very left, 2nd row from the bottom, in the diagram above), the AND would work as follows (I added in spaces for the sake of visualization):

00000000 00000000 00000000 00000000 00000000 00000000 11111111 00000000 (My WhitePawns bitboard)
BITWISE AND
00000000 00000000 00000000 00000000 00000000 00000000 10000000 00000000 (Bitmask to see if pawn on A2)
=
00000000 00000000 00000000 00000000 00000000 00000000 10000000 00000000 (Result - yes, pawn on A2)

How does it work?
0 AND 0 = 0
0 AND 1 = 0
1 AND 1 = 1

So if I had this instead:

00000000 00000000 00000000 00000000 00000000 00000000 11111111 00000000 (My WhitePawns bitboard)
00000000 00000000 00000000 00000000 00000000 00000001 00000000 00000000 (Bitmask to see if pawn on H3)
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 (Result - no)

Therefore, the calculation is simple. If result > 0, then the square is occupied. Here is the code for printing a bitboard:

public static void printBitBoard(string s, ulong bb) {
Console.Write("----------------------------\n");
Console.Write(s + "\n");
Console.Write("----------------------------\n");

for (int r=0; r<8; r++) {
for (int f=0; f<8; f++) {
ulong bitMask = 1;

if ((bb & (bitMask << (r*8+f))) > 0) {
Console.Write("1");
} else {
Console.Write("0");
}
}

Console.Write("\n");
}
}

This is the cool part: if ((bb & (bitMask << (r*8+f))) > 0)

bb is the bitboard
bitMask is our bitmask set to 1... 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
The << is the shift operator, so we take our bitmask and based upon the square we're checking (1-64), we shift it to the appropriate position in the mask. Since c# is 0 based, we're actually checking 0-63. So the first time through, with r=0 and f=0, the bitmask will be 1 as shown above. The next time through, r=0 and f=1, so we will shift the bit over 1 position and get the following: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010

and so on...

If you wanted to see all pawns, the cool thing is that you wouldn't need to create another bitboard, you'd simply have to OR the WhitePawns and BlackPawns together. A Bitwise or works as follows:

0 OR 0 = 0
1 OR 0 = 1
1 OR 1 = 1

So we have:

00000000 00000000 00000000 00000000 00000000 00000000 11111111 00000000 (My WhitePawns bitboard)
BITWISE OR
00000000 11111111 00000000 00000000 00000000 00000000 00000000 00000000 (My BlackPawns bitboard)
=
00000000 11111111 00000000 00000000 00000000 00000000 11111111 00000000 (Result - all pawns)

And with that, I think I'm going to call it a night! Hopefully I can fall asleep - luckily that's not usually a problem.

Ed.

No comments: