Archive

Posts Tagged ‘Programming’

DeScramble – Game Logic

May 8th, 2009

This is the 4th installment about my Scramble solver, DeScramble.  You can check out the first 3 parts here, here, and here.  In this post I am going to write a little about the game logic and how the program is setup to play the game.

The rules of the game are pretty simple; find words on the game board using a chain of adjacent letters and use each letter only once per word.  The brunt of the logic, which isn’t much, is knowing which letters are adjacent to which.  Since the game board is a square and the adjacent letters are above and below one another, we have to create a map in the code to tell us which letters are next to which.

board

Valid Moves

0 => 1, 5, 6
1 => 0, 2, 5, 6, 7
….
12 => 6, 7, 8, 11, 13, 16, 17, 18
….
24 => 18, 19, 23

We could of course create a static map of which squares are adjacent to which, but this doesn’t allow us the flexibility to solve for different sized boards (Scramble has both 4×4 and 5×5 games).  So how do we go about creating this map in a flexible way?  Before I show the code to setup the valid character chains I think it will be helpful to go over a few of the basic constructs of the solver.

A game board is made up a many board letters:

Collection<BoardLetter> gameBoard = new Collection<BoardLetter>();
internal class BoardLetter
{
  public char Letter;
  public sbyte Position;

  public BoardLetter(char letter, sbyte position)
  {
    Letter = letter;
    Position = position;
  }
}

The dictionary of words is partitioned by first letter so searching goes a little faster:

Dictionary<char, List<string>> dictionary = new Dictionary<char, List<string>>();

 
The valid character chains are keyed off position and contain a list of BoardLetters adjacent:

Dictionary<sbyte, Collection<BoardLetter>> validCharacterChains =
  new Dictionary<sbyte, Collection<BoardLetter>>();

 
Creating the character chains is pretty straight forward.  The general formula for finding adjacent positions would be position ± 1 and position ± row ± 1.  This formula works for all positions except those on the edge of the game board (top/bottom row and right/left column).  Since we know the game boards are always square finding the edge positions to handle the exceptions is simplified.  The finished method:

private void LoadCharChains()
{
  validCharacterChains.Clear();
  for (sbyte i = 0; i < puzzleLength; i++)
  {
    validCharacterChains.Add(i, new Collection<BoardLetter>());
    double col = (i + 1) % square;
    if (col != 1) // not left col so there is a char to the left
    {
      validCharacterChains[i].Add(gameBoard[i - 1]);
    }
    if (col != 0) // not right col so there is a char to the right
    {
      validCharacterChains[i].Add(gameBoard[i + 1]);
    }
    if (i >= square) // not first row so there is a char above
    {
      validCharacterChains[i].Add(gameBoard[i - square]);
      if (col != 1) // not first row not left col so there is a char above left
      {
        validCharacterChains[i].Add(gameBoard[i - square - 1]);
      }
      if (col != 0) // not first row not right col so there is a char above right
      {
        validCharacterChains[i].Add(gameBoard[i - square + 1]);
      }
    }
    if (i < (puzzleLength - square)) // not last row so there is a char below
    {
      validCharacterChains[i].Add(gameBoard[i + square]);
      if (col != 1) // not last row not left col so there is a char below left
      {
        validCharacterChains[i].Add(gameBoard[i + square - 1]);
      }
      if (col != 0) // not last row not right col so there is a char below right
      {
        validCharacterChains[i].Add(gameBoard[i + square + 1]);
      }
    }
  }
}

 
Now that we have the valid moves mapped out we can just loop though the dictionary of words to see if they can be found on the game board.  We use recursion for this keeping track of where we have traversed on the board so we don’t use the same position twice.  Not the cleanest code but it works:

private void SolvePuzzle()
{
  foreach BoardLetter boardLetter in gameBoard)
  {
    foreach (string possibleAnswer in dictionary[boardLetter.Letter])
    {
      if (!answers.Contains(possibleAnswer))
      {
        foundAnswer = false;
        List<sbyte> testedPositions = new List<sbyte>();
        testedPositions.Add(boardLetter.Position);
        string startWord = boardLetter.Letter.ToString();
        if (startWord.Equals("q"))
        {
          startWord = "qu";
        }
        CheckBoardForAnswer(boardLetter, startWord, possibleAnswer, testedPositions);
      }
    }
  }
}

private void CheckBoardForAnswer(BoardLetter boardLetter, string workingWord, string possibleAnswer,
        List<sbyte> testedPositions)
{
  for (sbyte i = 0; i < validCharacterChains[boardLetter.Position].Count; i++)
  {
    if (!foundAnswer)
    {
      BoardLetter workingLetter = validCharacterChains[boardLetter.Position][i];
      if (!testedPositions.Contains(workingLetter.Position))
      {
        string testWord = String.Concat(workingWord, workingLetter.Letter);
        // if we've added a q then go ahead and add a u
        if (testWord.EndsWith("q"))
        {
          testWord += "u";
        }
        if (testWord.Equals(possibleAnswer))
        {
          answers.Add(possibleAnswer);
          foundAnswer = true;
        }
        else if (possibleAnswer.StartsWith(testWord))
        {
          testedPositions.Add(workingLetter.Position);
          CheckBoardForAnswer(workingLetter, testWord, possibleAnswer, testedPositions);
          testedPositions.Remove(workingLetter.Position);
        }
      }
    }
  }
}

 
In my next (and most likely last) post I will go over how the screen processing works.

.NET, DeScramble , , , , ,

Parallel Computing Videos

November 15th, 2008

In my PDC Day 3 post I mentioned how impressed I was with the Parallel Computing session.  Ryan, Richard, and I are still talking about some of the stuff we saw and learned in that session.  Daniel was kind enough to mention in the comments that the video from his PDC talk is now online.  If you weren’t able to attend PDC or you didn’t make it to the session this is a must see video!

I also noticed on Daniel’s blog that he posted links to a video of an interview he did about parallelism at Tech Ed EMEA .  This interview is a nice compliment to the PDC session as it reiterates some of the important points of parallel computing such as what parallelism is (as opposed to just multi-threading) and why it’s so critical to understand how to leverage the power of multiple cores today given the prospect that 32+ core machines will be standard in the not too distant future.

It’s inevitable that parallelism will become a critical aspect of software development in the future and it’s nice to see Microsoft doing some great work in this area bringing such a vital (and complex) technology to the mainstream.

.NET, Programming , , , ,

DeScramble – Video Demo

November 13th, 2008

In my previous DeScramble post I did an overview of the program’s UI.  Now it’s time to see a video of the program in action!

However, I want to make a few things clear before you watch the video below.

  • I have never used this program in any Scramble Live game with the exception of Cheater’s Ball. All the regulars in Cheater’s Ball know I have this program and have seen it in action.
  • I have never used this program in any Scramble match.  Just look at my record and that becomes obvious.  Plus, all the people I play matches with know I have the program so it wouldn’t really fool anyone.  Besides, actually playing the game with people is more fun.
  • I wrote the program because it was an interesting challenge to me – My goal was not to make people think I am a better Scramble player than I am.
  • After writing this program and watching it run against some of the better players in the game I have a whole new respect for how good those people really are.  The speed at which they are able to find words on the board and enter them in is amazing!

So with that said, here is a short demo of DeScramble in action:

DeScramble, Programming , , , , , ,

Anders C# 4.0 Followup

November 11th, 2008

Since C# 4.0 was introduced by Anders at PDC 2008 there has been a lot of buzz about the features that have been added to the language and why. Many people have questions about why something like dynamic static types needed to be added and what was the thinking behind such decisions. I have wondered along with everyone else about many of these questions. Thankfully channel9 has managed to get an interview with Anders and asked him to clarify some of the reasoning behind the decisions they hade with the language. Video is below:


C# 4.0 – Questions and reasons behind the answers

.NET, Programming , , , , , ,

DeScramble – UI Overview

November 3rd, 2008

About a month ago I wrote an introduction to DeScramble an application I wrote this summer to cheat at the Facebook game Scramble.  In this installment I will introduce the UI and the basic functionality of the application.  Below is a screenshot of the main UI and a description of what each element does:

descrambleUI

  1. Game window finder – drag this target to the browser window that is running the Scramble game.  This allows the program to grab the window handle that is later used to interpret the game board.  In a future version I may attempt to try and find the window handle automagically but this works fine for now.
  2. Send Answers toggle – checking this option tells the program to send the answers to the game.
  3. Answer Speed slider – use this slider to change how fast the program sends the answers to the game.  From my testing anything lower than about 40ms tends to choke the game UI.
  4. Auto Stop/Start toggle (bot mode) – checking this option tells the program to automatically start and stop the solver during live games.
  5. Burst Mode toggle – checking this option tells the program to send the first 3 answers to the game immediately and then send answers based on the indicated answer speed.  This option is to ensure that when the scores are first posted that you have some points.  This eliminates the “cheaters lag” effect that is noticed when people have to type the board into a solver.
  6. Solve/Stop Solve button – this button starts and stops the solver.

.NET, DeScramble, Programming , , , , , ,

DeScramble – An Introduction

September 22nd, 2008

This summer I was introduced to a game on Facebook called Scramble. Essentially it’s Boggle but played in a web browser. I was immediately hooked on this game and started playing it regularly. One day as I was playing the game and wondered if I could write a program that could automate my playing this game. Surely software could play this game WAY more efficiently and accurately than I could right?

So I opened up my trusty IDE and started plugging away at trying to make a program smart enough to play Scramble better than I could. Seems like it should be easy enough with the bar set so low.

About a day later I had a very basic Scramble solver which could take a string of letters as input and then spit out a list of possible answers. While there some interesting things about writing a basic Scramble solver (these are very simple to make), I wanted something a little more automated. I also wanted something that didn’t just flat out cheat and win but would act more human to be less noticeable. About a week later I had it finished, my automated Scramble application affectionately called DeScramble.

It was a pretty fun summer project and I plan on spending the next several blog posts talking about the way it works and some of the things I learned as well as some of the challenges. I am also going to try and put together a video so everyone can see it in action.

So stay tuned.

.NET, DeScramble, Programming , , , , ,