Beispiel #1
0
        // *** PRIVATE HELPER FUNCTIONS *** //

        #region createGame
        private Game createGame(string name, Dictionary <string, string> definitions = null, bool interactive = false)
        {
            try
            {
                Game newgame = interactive ?
                               Manager.CreateGame(name, definitions, new UnassignedGameVariablesForm(this).Helper)
                                        : newgame = Manager.CreateGame(name, definitions);

                return(newgame);
            }
            catch (Exception ex)
            {
                ExceptionForm exceptionForm = new ExceptionForm(ex, null, name);
                exceptionForm.ShowDialog();
                return(null);
            }
        }
Beispiel #2
0
 private void timer_Tick(object sender, EventArgs e)
 {
     timer.Stop();
     currentGame++;
     if (currentGame < savedGames.Length)
     {
         string filename = savedGames[currentGame];
         using (TextReader reader = new StreamReader(filename))
         {
             try
             {
                 Game loadedGame = Manager.LoadGame(reader);
                 reader.Close();
                 loadedGame.Variation  = Variation;
                 loadedGame.TTSizeInMB = 1024;
                 loadedGame.StartMatch();
                 loadedGame.ComputerControlled[loadedGame.CurrentSide]     = true;
                 loadedGame.ComputerControlled[loadedGame.CurrentSide ^ 1] = false;
                 loadedGame.AddInternalEngine(loadedGame.CurrentSide);
                 loadedGame.AddHuman(loadedGame.CurrentSide ^ 1);
                 TimeControl timeControl = new TimeControl();
                 if (FixedDepth != null)
                 {
                     timeControl.Infinite = true;
                     timeControl.PlyLimit = (int)FixedDepth;
                 }
                 else if (FixedTimeMinutes != null)
                 {
                     timeControl.TimePerMove = (int)FixedTimeMinutes * 1000 * 60;
                 }
                 loadedGame.Match.SetTimeControl(timeControl);
                 loadedGame.MovePlayed       += movePlayed;
                 loadedGame.ThinkingCallback += updateThinking;
                 //	Create and show the GameForm (the actual Game GUI)
                 gameForm = new GameForm(loadedGame);
                 gameForm.Show();
             }
             catch (Exception ex)
             {
                 ExceptionForm exceptionForm = new ExceptionForm(ex, null);
                 exceptionForm.ShowDialog();
             }
         }
     }
 }
Beispiel #3
0
 private void btnLoadGame_Click(object sender, EventArgs e)
 {
     if (openFileDialog.ShowDialog() == DialogResult.OK)
     {
         string filename = openFileDialog.FileName;
         using (TextReader reader = new StreamReader(filename))
         {
             try
             {
                 Game loadedGame = Manager.LoadGame(reader);
                 startGame(loadedGame);
             }
             catch (Exception ex)
             {
                 ExceptionForm exceptionForm = new ExceptionForm(ex, null);
                 exceptionForm.ShowDialog();
             }
         }
     }
 }
Beispiel #4
0
 private Bitmap createBitmapRenderingOfGame(Game game, double xScale, double yScale)
 {
     try
     {
         BoardPresentation presentation = PresentationFactory.CreatePresentation(game, true);
         Bitmap            b            = presentation.Render();
         Bitmap            scaled       = null;
         if (b.Height < 550)
         {
             if (b.Width < 625)
             {
                 scaled = new Bitmap(b, (int)(b.Width * 0.365 * xScale), (int)(b.Height * 0.365 * yScale));
             }
             else
             {
                 scaled = new Bitmap(b, (int)(b.Width * 0.275 * xScale), (int)(b.Height * 0.275 * yScale));
             }
         }
         else
         {
             if (b.Height > 675)
             {
                 scaled = new Bitmap(b, (int)(b.Width * 0.25 * xScale), (int)(b.Height * 0.25 * yScale));
             }
             else
             {
                 scaled = new Bitmap(b, (int)(b.Width * 0.3 * xScale), (int)(b.Height * 0.3 * yScale));
             }
         }
         return(scaled);
     }
     catch (Exception ex)
     {
         ExceptionForm exform = new ExceptionForm(ex, game);
         exform.ShowDialog();
         Close();
         return(null);
     }
 }
Beispiel #5
0
        private void appearanceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AppearanceSettingsForm form = new AppearanceSettingsForm(Theme);

            if (form.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    boardControl.Presentation.UpdateTheme(Theme);
                }
                catch (Exception ex)
                {
                    ExceptionForm exform = new ExceptionForm(ex, Game);
                    exform.ShowDialog();
                    return;
                }
                boardControl.Invalidate();
                mbControl.UpdateTheme(Theme);
                updateTheme();
                Theme.SaveToRegistry(Game.RegistryKey);
            }
        }
 private void UpdatePreviewImage()
 {
     try
     {
         Type                 gameClass     = Program.Manager.GameClasses[game.GameAttribute.GameName];
         GameAttribute        gameAttribute = game.GameAttribute;
         ConstructorInfo      ci            = gameClass.GetConstructor(new Type[] { });
         Game                 newgame;
         InitializationHelper initHelper = PreviewHelper;
         newgame = (Game)ci.Invoke(null);
         FieldInfo environmentField = newgame.GetType().GetField("Environment");
         if (environmentField != null)
         {
             environmentField.SetValue(newgame, new Compiler.Environment(Program.Manager.Environment));
         }
         newgame.Initialize(gameAttribute, null, initHelper);
         BoardPresentation presentation = PresentationFactory.CreatePresentation(newgame, true);
         Bitmap            b            = presentation.Render();
         if (b != null)
         {
             Bitmap scaled = null;
             double xscale = (double)pictSubGamePreview.Size.Width / (double)b.Width;
             xscale = xscale > 1.0 ? 1.0 : xscale;
             double yscale = (double)pictSubGamePreview.Size.Height / (double)b.Height;
             yscale = yscale > 1.0 ? 1.0 : yscale;
             double scale = xscale > yscale ? yscale : xscale;
             scaled = new Bitmap(b, (int)(b.Width * scale), (int)(b.Height * scale));
             pictSubGamePreview.Image = scaled;
         }
     }
     catch (Exception ex)
     {
         ExceptionForm form = new ExceptionForm(ex, game);
         form.ShowDialog();
     }
 }
Beispiel #7
0
        // *** EVENT HANDLERS *** //

        #region Event Handlers
        #region Form Load Event
        private void MainForm_Load(object sender, EventArgs e)
        {
            //	Tweek the user interface depending on whether or not we
            //	are running on Windows.  This is because the program looks
            //	best with "Visual Styles" but Mono on Linux does not support
            //	this and it will look extra cheezy if we don't compensate.
            //	NOTE: Windows versions prior to Vista also don't support
            //	Visual Styles, but we don't bother to compensate for that.
            if (Program.RunningOnWindows)
            {
                BackColor = Color.LemonChiffon;
            }
            else
            {
                panelGameIndexHeader.BackColor = Color.DarkGray;
            }

            //	Populate the master game list with all known games
            updateMasterGameList();


            // *** POPULATE TAB CONTROL WITH GAME BUTTONS *** //

            //	Determine scaling in case the tab page size has been changed
            //	(by operating system hiDPI settings for example.)
            double xScale = (double)tabIndexPage.Width / 1086;
            double yScale = (double)tabIndexPage.Height / 546;

            mainTabControl.SuspendLayout();
            int pageNumber = 0;

            //	Iterate through the GameCatalog makeing a tab for each top-level category
            foreach (CatalogNode node in Program.GameCatalog.Root.Children)
            {
                //	Create a tab page for this category
                TabPage page = new TabPage(node.Name);
                //	Tweek colors if we're running on Windows (and thus
                //	we assume we have Visual Styles available)
                if (Program.RunningOnWindows)
                {
                    page.BackColor = Color.White;
                }
                //	Insert the tab page into the tab control
                tabControlPages.Add(node, page);
                mainTabControl.TabPages.Insert(pageNumber++, page);

                //	For now, no more than 6 games per top-level category supported
                if (node.Children.Count <= 6)
                {
                    // *** BUTTON VIEW *** //

                    //	determine number of rows and columns of buttons
                    int nRows, nColumns;
                    calcRowAndColumnCountsForButtonDisplay(node.Children.Count, out nRows, out nColumns);

                    //	layout game nodes into rows and columns
                    CatalogNode[,] nodes = new CatalogNode[nRows, nColumns];
                    for (int x = 0; x < node.Children.Count; x++)
                    {
                        nodes[x / nColumns, x % nColumns] = node.Children[x];
                    }

                    int placed = 0;
                    foreach (CatalogNode gamenode in node.Children)
                    {
                        if ((!gamenode.IsAbstract && Program.Manager.GameClasses.ContainsKey(gamenode.Name)) ||
                            (gamenode.IsAbstract && gamenode.SampleGameName != null && Program.Manager.GameClasses.ContainsKey(gamenode.SampleGameName)))
                        {
                            try
                            {
                                //	calculate basic button position based on number of columns/rows
                                int xoffset = (int)((nColumns == 3 ? 48 : (nColumns == 2 ? 218 : 388)) * xScale);
                                int yoffset = (int)((nRows == 2 ? 32 : 162) * yScale);
                                //	additional adjustments to compensate for auto-scaling based on font size
                                //xoffset += (ClientSize.Width - 1118) / 2;
                                //yoffset += (ClientSize.Height - 648) / 2;
                                //	create an actual Game object of this type so we can ask it to
                                //	draw a presentation of itself which we will draw on the button
                                Game game = createGame(gamenode.IsAbstract ? gamenode.SampleGameName : gamenode.Name);
                                //	create the button and configure it
                                Button newbutton = new Button();
                                newbutton.BackgroundImage       = createBitmapRenderingOfGame(game, xScale, yScale);
                                newbutton.BackgroundImageLayout = ImageLayout.Center;
                                newbutton.Location  = new Point((int)((340 * (placed % nColumns) + xoffset) * xScale), (int)((260 * (placed / nColumns) + yoffset) * yScale));
                                newbutton.Name      = "btnChess";
                                newbutton.Size      = new Size((int)(293 * xScale), (int)(206 * yScale));
                                newbutton.TabIndex  = 0;
                                newbutton.BackColor = SystemColors.ControlLight;
                                newbutton.UseVisualStyleBackColor = true;
                                newbutton.Tag    = gamenode;
                                newbutton.Click += new EventHandler(btnSelectorButtons_Click);
                                //	add this button to the controls on the tab page
                                page.Controls.Add(newbutton);
                                //	now create a label to go underneath the button
                                Label newlabel = new Label();
                                newlabel.AutoSize  = false;
                                newlabel.Size      = new Size((int)(293 * xScale), (int)(24 * yScale));
                                newlabel.Location  = new Point((int)((340 * (placed % nColumns) + xoffset) * xScale), (int)((260 * (placed / nColumns) + yoffset + 208) * yScale));
                                newlabel.TextAlign = ContentAlignment.MiddleCenter;
                                newlabel.Text      = gamenode.Name;
                                newlabel.Font      = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
                                //	add the label to the controls on the tab page
                                page.Controls.Add(newlabel);
                                //	keep track of how many we've placed so the
                                //	next one will be placed in the correct location
                                placed++;
                            }
                            catch (Exception ex)
                            {
                                //	Something went horribly wrong.  Sadly, this isn't all that
                                //	uncommon when creating new kinds of games, so we display a
                                //	fancy ExceptionForm that gives great detail about the
                                //	exception and allows navigating to inner exceptions.
                                ExceptionForm exceptionForm = new ExceptionForm(ex, null);
                                exceptionForm.ShowDialog();
                            }
                        }
                    }
                }
            }
            //	we now switch pages from zero to one and back to zero
            //	to compensate for a glitch in the Mono tab control on Linux
            mainTabControl.SelectedTab = mainTabControl.TabPages[1];
            mainTabControl.ResumeLayout();
            mainTabControl.SelectedTab = mainTabControl.TabPages[0];

            //	start the timer (which will only fire once, just for initialization.)
            //	when it goes off, we initialize the catalog of engines and discover
            //	any new engines automatically (if auto-discovery is enabled.)
            startTimer.Start();
        }
Beispiel #8
0
        static void Main()
        {
            // *** INITIALIZATION *** //

            Manager = new ChessV.Manager.Manager();

            //	Are we running on Windows?
            RunningOnWindows = Path.DirectorySeparatorChar == '\\';

            //	Base manager for registry key settings
            int currentRegistryVersion = RegistrySettings.Initialize();

            //	Factory object for dynamically creating a BoardPresentation for any Game object
            PresentationFactory.Initialize();

            //	Library object containing the collection of bitmap textures
            TextureLibrary.Initialize();

            //	Library object cointaining the collection of defined color schemes
            ColorSchemeLibrary.Initialize(currentRegistryVersion);

            //	Library object containing the collection of defined piece sets
            PieceSetLibrary.Initialize();
            //	Make sure we loaded at least a standard piece set successfully or
            //	else we'll need to inform the user to reinstall and then exit
            if (PieceSetLibrary.PieceSets == null)
            {
                MessageBox.Show("Directory of piece set graphics could not be found.\n" +
                                "Please re-install ChessV.", "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                Application.Exit();
                return;
            }
            if (!PieceSetLibrary.PieceSets.ContainsKey("Standard"))
            {
                MessageBox.Show("The 'Standard' piece set  graphics could not be found.\n" +
                                "Please re-install ChessV.", "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                Application.Exit();
                return;
            }


            // *** INITIALIZE GAME CATALOG *** //
            string gameCatalog =
                ".Chess" +
                "\n\tChess" +
                "\n\t.Shuffled Variants|Fischer Random Chess" +
                "\n\t\tFischer Random Chess" +
                "\n\t\tChess480" +
                "\n\t\tWild Castle" +
                "\n\t\tChess256" +
                "\n\tPocket Knight" +
                "\n\tChess with Different Armies" +
                "\n\tKnightmate" +
                "\n\tAlice Chess" +
                "\n.Medium" +
                "\n\t.Capablanca Variants|Capablanca Chess" +
                "\n\t\tCapablanca Chess" +
                "\n\t\tCarrera's Chess" +
                "\n\t\tBird's Chess" +
                "\n\t\tModern Carrera's Chess" +
                "\n\t\tGothic Chess" +
                "\n\t\tGrotesque Chess" +
                "\n\t\tEmbassy Chess" +
                "\n\t\tVictorian Chess" +
                "\n\t\tLadorean Chess" +
                "\n\t\tSchoolbook Chess" +
                "\n\t\tUnivers Chess" +
                "\n\t\tOpti Chess" +
                "\n\tGrand Chess" +
                "\n\tFalcon Chess" +
                "\n\tOdin's Rune Chess" +
                "\n\tEurasian Chess" +
                "\n\tUnicorn Great Chess" +
                "\n.Large" +
                "\n\tWildebeest Chess" +
                "\n\tOmega Chess" +
                "\n\tGross Chess" +
                "\n\tDouble Chess (16 x 8)" +
                "\n\tOdyssey" +
                "\n\tChess on a 12 by 12 Board" +
                "\n.Historical" +
                "\n\tShatranj" +
                "\n\tCourier Chess" +
                "\n\tArchchess" +
                "\n\tEmperor's Game";

            byte[]     gameCatalogBytes = Encoding.ASCII.GetBytes(gameCatalog);
            TextReader textReader       = new StreamReader(new MemoryStream(gameCatalogBytes));

            GameCatalog.LoadIndex(textReader);


            // *** START APPLICATION *** //

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            try
            {
                Application.Run(new MainForm());
            }
            catch (Exception ex)
            {
                ExceptionForm exform;
                if (ex is ChessV.Exceptions.ChessVException)
                {
                    exform = new ExceptionForm(((ChessV.Exceptions.ChessVException)ex).InnerException, ((ChessV.Exceptions.ChessVException)ex).Game);
                }
                else
                {
                    exform = new ExceptionForm(ex, null);
                }
                exform.ShowDialog();
                return;
            }
        }
Beispiel #9
0
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (!Directory.Exists(txtFolder.Text))
            {
                MessageBox.Show("You must select a valid folder containing saved games");
                return;
            }

            listResults.Items.Clear();
            hashcodes  = new Dictionary <string, List <ulong> >();
            savedGames = Directory.GetFiles(txtFolder.Text, "*.sgf");
            foreach (string game in savedGames)
            {
                List <ulong> gameHashes = new List <ulong>();
                using (TextReader reader = new StreamReader(game))
                {
                    try
                    {
                        Game loadedGame = manager.LoadGame(reader, gameHashes);
                        reader.Close();
                        hashcodes.Add(game, gameHashes);
                    }
                    catch (Exception ex)
                    {
                        ExceptionForm exceptionForm = new ExceptionForm(ex, null);
                        exceptionForm.ShowDialog();
                    }
                }
            }
            int total = 0;

            foreach (string game in savedGames)
            {
                //	find the position hashcodes for this game
                List <ulong> hashes = hashcodes[game];
                //	identify deepest match and with which game
                int    deepestMatch     = 0;
                string deepestMatchGame = "";
                //	iterate through every other game
                foreach (KeyValuePair <string, List <ulong> > otherGame in hashcodes)
                {
                    //	don't compare with ourself
                    if (otherGame.Key != game)
                    {
                        List <ulong> otherHashes = otherGame.Value;
                        //	iterate through all hashcodes within game backwards
                        for (int x = hashes.Count - 1; x >= 0; x--)
                        {
                            ulong thisHash = hashes[x];
                            if (otherHashes.Contains(thisHash) && x >= deepestMatch)
                            {
                                deepestMatch     = x;
                                deepestMatchGame = otherGame.Key;
                            }
                        }
                    }
                }
                ListViewItem lvi = new ListViewItem(game.Substring(game.LastIndexOf('\\') + 1));
                lvi.SubItems.Add(hashes.Count.ToString());
                lvi.SubItems.Add((deepestMatch + 1).ToString());
                lvi.SubItems.Add(deepestMatchGame.Substring(deepestMatchGame.LastIndexOf('\\') + 1));
                listResults.Items.Add(lvi);
                total += deepestMatch + 1;
            }
            lblTotal.Text = total.ToString();
        }
        public virtual Bitmap Render(bool highlightComputerMove = false, bool rotateBoard = false, Piece piece = null, bool endgame = false)
        {
            try
            {
                Size     boardSize = NativeSize();
                Bitmap   bmp       = new Bitmap(boardSize.Width, boardSize.Height, PixelFormat.Format32bppArgb);
                Graphics g         = Graphics.FromImage(bmp);

                SolidBrush moveBrush    = null;
                SolidBrush captureBrush = null;
                if (PieceLifted != null)
                {
                    moveBrush    = new SolidBrush(Color.FromArgb(0, 255, 0));
                    captureBrush = new SolidBrush(Color.FromArgb(255, 0, 0));
                }

                //	Draw border - may be texture or color
                if (Theme.ColorScheme.BorderTexture != null)
                {
                    Image borderImage =
                        Theme.ColorScheme.BorderTexture.LargeImage != null
                                                ? Theme.ColorScheme.BorderTexture.LargeImage
                                                : Theme.ColorScheme.BorderTexture.Images[0];
                    g.DrawImage(borderImage, new Rectangle(0, 0, mapping.TotalWidth + 1, mapping.TotalHeight + 1));
                }
                else
                {
                    SolidBrush borderBrush = new SolidBrush(Theme.ColorScheme.BorderColor);
                    g.FillRectangle(borderBrush, 0, 0, mapping.TotalWidth + 1, mapping.TotalHeight + 1);
                }

                //	Have Game render board if custom theme is active
                if (Theme.CustomThemeName != null)
                {
                    Game.RenderCustomThemeBoard(g, mapping.BorderSize, Theme.CustomThemeName);
                }

                //	Create brushes for square colors
                SolidBrush[] squareBrushes = new SolidBrush[Theme.ColorScheme.NumberOfColors];
                for (int colorNumber = 0; colorNumber < Theme.ColorScheme.NumberOfColors; colorNumber++)
                {
                    squareBrushes[colorNumber] = new SolidBrush(Theme.ColorScheme.SquareColors[colorNumber]);
                }

                //	Created required pens
                Pen blackOutlinePen = null;
                if (Theme.NSquareColors == 1)
                {
                    blackOutlinePen = new Pen(Color.Black, 2);
                }
                Brush pstNumberDisplayBrush = null;
                if (piece != null)
                {
                    pstNumberDisplayBrush = new SolidBrush(Color.Black);
                }


                // *** ITERATE THROUGH ALL SQUARES *** //

                for (int square = 0; square < Board.NumSquaresExtended; square++)
                {
                    //	Draw the square itself
                    Location  location          = Board.SquareToLocation(square);
                    int       squareColorNumber = Game.GetSquareColor(location, Theme.NSquareColors);
                    Rectangle rect = mapping.MapLocation(location, rotateBoard);
                    if (Theme.CustomThemeName == null /*&& piece == null*/)
                    {
                        if (Theme.ColorScheme.SquareTextures != null && Theme.ColorScheme.SquareTextures.ContainsKey(squareColorNumber))
                        {
                            g.DrawImage(Theme.ColorScheme.SquareTextures[squareColorNumber].Images[square % Theme.ColorScheme.SquareTextures[squareColorNumber].NumberOfImages], rect);
                        }
                        else
                        {
                            g.FillRectangle(squareBrushes[squareColorNumber], rect);
                        }
                    }
                    //	if we are showing the PST (piece-square-table) then draw the value for this square
                    if (piece != null)
                    {
                        int    relativeSquare = piece.Board.PlayerSquare(piece.Player, square);
                        string pstValue       = endgame ? piece.PieceType.GetEndgamePST(relativeSquare).ToString() : piece.PieceType.GetMidgamePST(relativeSquare).ToString();
                        g.DrawString(pstValue, System.Drawing.SystemFonts.CaptionFont, pstNumberDisplayBrush, rect);
                    }
                    //	draw black outline if this is uncheckered board or if we are showing PST
                    if (Theme.NSquareColors == 1 && Theme.CustomThemeName == null)
                    {
                        g.DrawRectangle(blackOutlinePen, rect);
                    }

                    //	is the current square one to which the lifted piece can move?
                    if (PieceLifted != null)
                    {
                        MoveInfo[] moves;
                        int        nMoves = Game.GetRootMoves(out moves, PieceLifted);
                        for (int x = 0; x < nMoves; x++)
                        {
                            if (moves[x].ToSquare == square)
                            {
                                Brush br = (moves[x].MoveType & MoveType.StandardCapture) > 0 ? captureBrush : moveBrush;
                                if (PieceSetPresentation.PieceSet.Name == "Eurasian")
                                {
                                    //	Cheezy hack so that the Eurasian peices don't cover the capture indicators
                                    g.FillRectangle(br, new Rectangle(rect.X + 4, rect.Y + 4, rect.Width - 8, rect.Height - 8));
                                    g.DrawRectangle(Pens.Black, new Rectangle(rect.X + 4, rect.Y + 4, rect.Width - 8, rect.Height - 8));
                                }
                                else
                                {
                                    g.FillEllipse(br, new Rectangle(rect.X + 6, rect.Y + 6, rect.Width - 12, rect.Height - 12));
                                    g.DrawEllipse(Pens.Black, new Rectangle(rect.X + 6, rect.Y + 6, rect.Width - 12, rect.Height - 12));
                                }

                                if (square == Board.LocationToSquare(GetMouseLocation(rotateBoard)) ||
                                    (!LiftedPieceIsDragged && square == PieceLifted.Square))
                                {
                                    Pen borderpen = new Pen(Color.FromArgb(0, 0, 0), 3);
                                    g.DrawRectangle(borderpen, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 3, rect.Height - 3));
                                }
                            }
                        }
                    }

                    //	Draw piece on square (if any)
                    if (pieces.ContainsKey(location))
                    {
                        PieceInfo pieceOnSquare = pieces[location];
                        if (PieceLifted == null || !LiftedPieceIsDragged || location != PieceLifted.Location)
                        {
                            pieceSetPresentation.Render(g, rect, pieceOnSquare.Player, pieceOnSquare.PieceType.TypeNumber);
                        }
                    }
                }

                //	draw thin line between squares and border and outside border
                Pen thinBlackPen = new Pen(Color.Black, 1);
                if (Theme.NSquareColors > 1 && GetType() == typeof(BoardPresentation))
                {
                    g.DrawRectangle(thinBlackPen, mapping.BorderSize, mapping.BorderSize, mapping.SquareSize * Board.NumFiles,
                                    mapping.SquareSize * Board.NumRanks);
                }
                g.DrawRectangle(thinBlackPen, 0, 0, mapping.TotalWidth - 1, mapping.TotalHeight - 1);

                //  highlight border of squares of recent move if computer has just finished moving
                if (highlightComputerMove && Game.HighlightSquares != null)
                {
                    Pen moveOutlinePen = new Pen(Theme.ColorScheme.HighlightColor, 3);
                    foreach (int square in Game.HighlightSquares)
                    {
                        Location  location = Board.SquareToLocation(square);
                        Rectangle rect     = mapping.MapLocation(location, rotateBoard);
                        rect = new Rectangle(rect.Left, rect.Top, rect.Width - 1, rect.Height - 1);
                        g.DrawRectangle(moveOutlinePen, rect);
                    }
                }

                //	create "centered" text alignment for drawing rank & file labels
                StringFormat centered = new StringFormat();
                centered.Alignment     = StringAlignment.Center;
                centered.LineAlignment = StringAlignment.Center;

                if (!SmallPreview)
                {
                    //	draw file labels
                    for (int file = 0; file < Board.NumFiles; file++)
                    {
                        Location  squareAboveLocation = new Location(0, rotateBoard ? Board.NumFiles - file - 1 : file);
                        Rectangle squareAboveRect     = mapping.MapLocation(squareAboveLocation);
                        Rectangle textrect            = new Rectangle(squareAboveRect.Left, squareAboveRect.Bottom + 2, squareAboveRect.Width, mapping.BorderSize - 2);
                        g.DrawString(Board.GetFileNotation(file), System.Drawing.SystemFonts.CaptionFont, new SolidBrush(Theme.ColorScheme.TextColor), textrect, centered);
                    }

                    //	draw rank labels
                    for (int rank = 0; rank < Board.NumRanks; rank++)
                    {
                        Location  squareToTheRightLocation = new Location(rotateBoard ? Board.NumRanks - rank - 1 : rank, 0);
                        Rectangle squareToTheRightRect     = mapping.MapLocation(squareToTheRightLocation);
                        Rectangle textrect = new Rectangle(squareToTheRightRect.Left - mapping.BorderSize, squareToTheRightRect.Top, mapping.BorderSize, squareToTheRightRect.Height);
                        g.DrawString(Board.GetRankNotation(rank), System.Drawing.SystemFonts.CaptionFont, new SolidBrush(Theme.ColorScheme.TextColor), textrect, centered);
                    }
                }

                //	draw lifted piece (if any)
                if (PieceLifted != null && LiftedPieceIsDragged)
                {
                    pieceSetPresentation.RenderFloatingPiece(g, MouseCoordinate, PieceLifted);
                }

                return(bmp);
            }
            catch (Exception ex)
            {
                ExceptionForm form = new ExceptionForm(ex, Game);
                form.ShowDialog();
                return(null);
            }
        }