Tuesday, July 28, 2009

A Checkers Rules Engine in C#

One of the things I've always wanted to program is a game using a Genetic Algorithm to generate the AI. Well at work I was talking about AI coding and my aforementioned desire came up and as we talked about it, the idea of using game of Checkers as the game I could use with a GA surfaced.

When I got home that evening and was relaxing after diner, I booted up the laptop and started cruising around the web. I was started looking around for a rules engine for checkers - hopefully in C#. You see my thought was, if I could find a rules engine that, from a given game board configuration and who's move it was, it would output all valid moves.

Well, no matter how I arranged the words in Google, I could not find a rules engine for checkers. I found a few complete C# checkers games but the rules were too integrated into the rest of the game for me to filter out.

So, I decided to write one.

I started with an enum to define the two players:
public enum PlayerColors { Black, Red }

Then I wrote a class to hold each checker piece:

CheckerPiece has a single constructor:
CheckerPiece(PlayerColors MyPlayerColor, int MyPieceLocation, bool MyIsKing)

Four properties:
public int PieceLocation { get; set; }
public bool IsKing { get; set; }
public PlayerColors PlayerColor { get; set; }
public List PossibleMoveLocations { get; set; }

and Three methods:
public char GetPlayCharacter()
public void FindAllMoves(char[] GameboardArray)
public void FindAllJumps(char[] GameboardArray)

The constructor sets the PlayerColor, PieceLocation, and IsKing.

PlayerColor defines which side the piece belongs to.
PieceLocation is an int from 0 to 63 defining each square of the game board.
IsKing is a bool that determines if the piece is a king or not.

GetPlayCharacter returns a lowercase r for a red piece, a lowercase b for a black piece, an uppercase R for a red king piece and an uppercase B for a black king piece.

a game board array is a char[64] array that can hold on of these chars 'r', 'R', 'b', 'B' or ' ' (a space).

FindAllMoves and FindAlJumps take in a GameboardArray and sets the PossibleMoveLocations list with all the possible Moves or Jumps.

Now with that built, I created the CheckersRulesEngine class.

CheckersRulesEngine has a single constructor:
public CheckersRulesEngine(char[] gameboardarray)

A static char array that holds a starting game board configuration for convenience:
static public readonly char[] StartingGameboardArray =
" b b b bb b b b b b b b r r r r r r r rr r r r ".ToCharArray();

Three properties:
public List MovablePieces { get; set; }
public List Pieces { get; set; }
public char[] GameboardArray { get; set; }

And Three Methods:
public void GetPiecesWithMoves(PlayerColors CurrentPlayer)
public void GetPiecesWithJumps(PlayerColors CurrentPlayer)
public string OutputAsciiBoard()

The constructor the GameboardArray and creates a CheckerPiece entry into Pieces for each piece defined in the GameboardArray.

GetPiecesWithMoves and GetPiecesWithJumps works its way through the Pieces collection and loads MovablePieces with the pieces that qualify.

OutputAsciiBoard is a helper function that outputs an ascii board showing the location of all the pieces.

You can get the c# code for the CheckersRulesEngine here! Or, you can download a Visual Studio 2008 solution that also includes a console program that plays a game of checkers against itself using random moves! The solution can be downloaded Here!

Tuesday, July 21, 2009

Widgets: Drag, drop and reorder. Simply done with JQUERY.

The heart of the Dropthings project, IGoogle or Pageflakes is the client side moving of the widgets. Be it dragging and dropping the widgets in other columns or reordering the widgets in a single column, this client side behaviour it the flashy part of the widget system.

In the Dropthings project the Author originally used the microsoft AJAX client side library along with quite a bit of his own code. No critisim here, he coded a complex cross-browser system that WORKED! I would not even have tried.

But, in the latest addition it says that the code was converted over to JQUERY. Well I looked at that code and while he may have converted to use JQUERY, he is not really USING JQUERY. Most of his system is still in place. No problem with that, unless you are not the Author and want to modify or enhance it.

I went another route: pure JQUERY. With just a few lines of code and a bit of AJAX to update the server I got all that functionality without all the complexity. Here it is:

        $(document).ready(function() {
$(".DropZone").sortable({
opacity: 0.5,
smooth: true,
helper: "clone",
handle: ".WidgetHeader",
connectWith: ".DropZone",
placeholder: "WidgetSortPlaceholderHighlight",
forcePlaceholderSize: true,
stop: function(event, ui) {
callMyService();
}
});
});


Thats it. You now have multi column drag and drop support. Just have your div's associated with the DropZone class and the Header of the WidgetContainer associated with the WidgetHeader class. My OnStop call to callMyService() walks through all the .DropZone controls and gets the ID of the Widget, the ID of the DropZone and the index (the order of the widgets) and calls the Webservice to update the database.

Here is a link to a working minimum example.

Thursday, July 16, 2009

A c# class to convert between bases

Ever needed to work with numbers in base 17, or base 3? I have always wanted to write a Genetic algorithm that used base 3 numbers to represent the board - 0 empty, 1 my piece, 2 opponent piece. Recently at work, we needed to work with base 36 numbers. While doing some searching I also learned that some people needed numbers that were alpha-int (Where the letters preceded the numbers) instead of the standard int-alpha.

Here is a class that I think Microsoft left out. We work different systems and different numbers every day, so why didn't Microsoft include a base converter class? It probably was just too low on their list of priorities.

Well, here is my interpretation. It is a static class that exposes three overloaded functions:
Encode(long Value, sbyte Base)
Encode(long Value, sbyte Base, bool NumeralsFirst)
Decode(string Input, sbyte Base)
Decode(string Input, sbyte Base, bool NumeralsFirst)
BetweenBases(string Value, sbyte FromBase, sbyte ToBase)
BetweenBases(string Value, sbyte FromBase, sbyte ToBase, bool NumeralsFirst)

By using the BetweenBases function, you can convert directly from one base to another without decoding to a long in between.

The complete code for the class can be downloaded here.

Saturday, July 11, 2009

Risk Map in Silverlight 2

As I mentioned in a previous post, I have reworked the USA map project to represent the map in the game of Risk.



The above image shows how the XAML is defined. The XAML is based on the SVG file found here. Once the project is ran, each country (both its inner and outer polygons) are entered into a data graph, similar to the one I used for the USA Map, with just a few improvements.

This demo, when ran, assigns each country to a player and assumes that you are the Green player. If you click on a country that is bordered with bright green, its border will turn black and all enemy held countries' borders will turn white. This shows what nations are available to attack.



If a programmer had a risk game play engine, this silverlight front-end will work quite well for you. The complete project can be downloaded here.

Tuesday, July 7, 2009

Dropthings - The good ideas and the bad

In a previous post I talked about my first impressions of the Dropthings project. Here I will talk about some of the ideas that I really liked in the Dropthings project, what ideas I will take away for my own project and the ideas that I thought were great but did not fit with my exact needs. And, at the very end I may add a few comments on another bad idea contained in the Dropthings project.

First I like the idea of not directly loading the widgets onto the page but instead having a common container where you load the widget, then the common container [lets call it the WidgetContainer :-)], is loaded on to the page. Here is a mockup of my version of the WidgetContainer user control:



The Dropthings project and my project save the widget information in two tables, the Widget table where all the default information about the widget is stored and the WidgetInstance table where the user specific widget information is stored. Since my requirements are that no controls are loaded until the user logs in, the entire generic user system in Dropthings, though cool, is not needed in my application.

So, after login, the process of loading the page is as simple as looping through the returned records and creating an instance of each widget inside its host container.

Lastly I would like to talk about the use of LINQ in the Dropthings project. Now I am not a huge advocate of LINQ, but there are times when it is the only tool that can solve the problem at hand, and I love it for that. What I do not like is that it:
A: Is database specific. Try running LINQ on Oracle or DB2 without purchasing third party plug-in. Sorry, cannot be done.
B: Unless it is watched very closely, the implementers of LINQ cross the data/rules boundary. In Dropthings you find LINQ commands everywhere. If you wanted to roll the Dropthings project out with an Oracle or DB2 back end, you would have a monumental time replacing all the Data access.

So, if the Dropthings project were not so tightly coupled with the data layer and workflow, I think (just my opinion) that the entire system would have benefited.

Thursday, July 2, 2009

Which UpdatePanel caused the Post?

Now that is a question! And the answer tool me nearly a day to discover. (OK, all of you that know the answer, stop snickering. I'm just learning the ASP.NET AJAX model)

After many dead ends, here is the key to finding what UpdatePanel caused the Post:
ScriptManager.GetCurrent(Page).AsyncPostBackSourceElementID

This returns the actual element ID that forced the Post. How does this help? Well, any post that originated in a UpdatePanel would be from a child control. So, if you walk up the control tree and find a UpdatePanel, you will have the UpdatePanel that caused the Post.

private UpdatePanel GetUpdatePanelThatCausedPostback()
{
var c = Page.FindControl(ScriptManager.GetCurrent(Page).AsyncPostBackSourceElementID);

while (c != null && !(c is UpdatePanel)) { c = c.Parent; }

if (c != null) return (c as UpdatePanel);
else return null;
}


Here we get the control that actually fired the Post and then we walk up the control tree, one by one, until we are either past the top (null) or we have found an UpdatePanel.

Then we simply either return the newly found UpdatePaenl or we return null.