Thursday, August 25, 2011

HexChess 360: Post Mortem

Well, that was fun! When I was trying to write my first game for publication, I couldn't come up with a solid, saleable idea that was simple enough to implement - so I took chess! A finished ruleset, a concept people are at least familiar with, it seemed a good idea and I am happy with the results. The code in previous posts is nowhere near what I ended up with, but moving forward, this will be more up to date!

HexChess 360

GOOD STUFF
1) A game, from start to finish, is a lot more work than one would think - from modeling and texturing, to managing input, to AI research and implemenation, to the menus and options.But doing it all was a ton of fun and a great learning experience.
2) I really got to understand the nitty-gritty of MinMax and AB pruning - boy, did I ever, and the learning curve dropoff from impossible to easy is astounding.
3) I learned TONS of optimization tricks, from 1D array usage, to internals, to garbage collection and  function management. Lots of this will come in handy in the future.
4) I learned a new game and had fun :)

BAD STUFF
1) It took a lot of time to get this far, and a lot out of me to have to work every evening on every aspect of the game. Next time, I'm going to try to space out the work with some other people.
2) There were a lot of  kinks to manage when moving from a PC to the XBox - how to handle user input, how much slower the XBox processor is (expecially with memory restrictions of my AB searching) compared to an i7, how to handle user elements within the 10% screen restrictions... these need to be considered from the START and a lot of it comes with experience.

OVERALL
 A great project and a great time. Obviously tough at some times, but a product that at least 540 people have liked enough to spend 80 points on. There have been some complaints about the user input (understandable), the AI search time (restricted as best I could) and the lack of music (which was purposefully left out, as I thought a chess game could use some silence), but overall, a good rating on XBL Indies.

Sales:



My next project, another board game, is underway now and has been for a few weeks. New updates soon!

Thursday, March 31, 2011

The Chess Pieces and Tiles

Bear with me as I work backwards in creating the board - this whole "documentation" thing sometimes is difficult.

The board is composed of tiles, each of which is a class. The most important parts of each tile are as follows:

   1:  public class Tile
   2:  {
   3:      public File file;
   4:      public Rank rank;
   5:      public ChessPiece piece;
   6:      public Tile[] neighbors;

If a tile does not have a piece on it, the piece variable is null; likewise, if a piece is a border tile, the entry for it's neighbor (of 6 possible) is null - this tells us when a piece is an edge tile.

Pieces are likewise classes, and their most important parts are as follows:

   1:  public class ChessPiece
   2:  {
   3:      public PieceType type;
   4:      public PieceColor side;
   5:      public Tile tile;
   6:      public bool Alive;
   7:      public bool WasMoved;
   8:      public bool WasOnStartingTile;
   9:      public List<Tile> MoveableTiles = new List<Tile>();
  10:      public List<Tile> AttackableTiles = new List<Tile>();
 
Besides the obvious components, "WasMoved" is used to determine if the piece has moved (castling) and "WasOnStartingTile" is used for pawns, to determine if they can be attacked en passant. The lists are updated to determine where a piece can move or attack from its current position.

Movements shall be covered next!

Tuesday, March 29, 2011

Introduction to the game: Hexagonal Chess

My first project began over a year ago, around the start of the 2010 year, developing a hex based 3D engine. After a few months of work, development was set aside to wrap up a graduate degree and upon completion, a smaller, more manageable project was undertaken in February of this year: Hexagonal Chess. This is a running development blog, hopefully complete by the DreamBuildPlay submission deadline.

Without any prior experience with hex chess, and not tons with regular chess anyways, in retrospect, I would not have started developing three versions at the start. But I did: Glinski, McCooey and Shafran. Shafran's version proved to be the biggest issue, thanks to the different board size, file/rank determination and extra moves such as castling.

Board Components

   1:          private GameVariant variant;
   2:          public GameVariant Variant
   3:          {
   4:              get { return variant; }
   5:          }
   6:          private Tile[,] tiles;          // Exist in FileRank format. Can be accessed: Tile t = tiles[(int)File.F, (int)Rank.Eleven];
   7:          public Tile[,] Tiles
   8:          {
   9:              get { return tiles; }
  10:          }
  11:          public Player[] players;
  12:   
  13:          private PieceColor CurrentTurn = PieceColor.White;
  14:   
  15:          public List<ChessPiece> WhitePieces = new List<ChessPiece>();
  16:          public List<ChessPiece> BlackPieces = new List<ChessPiece>();
  17:          public ChessPiece WhiteKing;
  18:          public ChessPiece BlackKing;
  19:   

The king pieces are given a shortcut, for quick referencing.

Creating the tiles and positions
The tiles are held in a two dimensional array, with extra spaces just held as null. For Glinsky and McCooey, the tiles are placed in a similar fashion:

   1:              // Assign tiles to the array, incrementing Rank then File into FileRank format
   2:              // We have 11 files and 11 ranks
   3:              for (int i = 0; i < 11; i++)
   4:              {
   5:                  // If our ranks are ranged 1 - 6, inclusive...
   6:                  if (i < 6)
   7:                  {
   8:                      // then we have 11 files
   9:                      for (int j = 0; j < 11; j++)
  10:                      {
  11:                          tiles[j, i] = new Tile((File)j, (Rank)i, null);
  12:                      }
  13:                  }
 
As we get to the "top" or black side of the board, we iterate towards the middle, leaving us with a much longer function.
Shafran has a special, and much easier to create, tile layout:


   1:              // Assign tiles to the array, File then Rank
   2:              // We have 9 files and 10 ranks, starting with files first.
   3:              // Construct the first 5 files (A - E inclusive) with all their ranks (increasing to 10 max)...
   4:              for (int i = 0; i < 5; i++)
   5:              {
   6:                  for (int j = 0; j < 6 + i; j++)
   7:                  {
   8:                      tiles[i, j] = new Tile((File)i, (Rank)j, null);
   9:                  }
  10:              }

We then continue in like manner to finish the rest of the tiles.

Placing the pieces
Placing the pieces at this point is easy. Since we've created the tile array to be addressable by file and rank for each version, we can simply:


   1:  tiles[(int)File.G, (int)Rank.Ten].piece = new ChessPiece(PieceType.King, PieceColor.Black, ref tiles[(int)File.G, (int)Rank.Ten], false, false, true, false, false, false);

Why did I use classes?
Each tile is a class, and each piece is a class - a piece points to a tile points to a piece, ad nauseum. Initially, this was done simply because it was easier. Structs, as value types, would not be as easy to compare as classes, requiring rank and file checks for each check of a piece or tile. This also generated some concern looking forward to the AI (not yet even begun) when considering the size of the heap when looking forward in multiple plys, but it was assuaged somewhat by looking through MSDN documentation on structs and recommending that structs are used in the majority of times for types less than 16 bytes; my classes were larger than that, with their position in space, type, available moves, etc.

If the performance is terrible, I may consider removing the chess piece class entirely, and simply having the tile class with chess piece type and side. This, however, would be a very time consuming change.