Why you lose at bridge

I have recently taken-up studying bridge, and picked up Why you lose at bridge at a second-hand book sale for $1.

My first running joke was “I lose because I don’t play”, but jokes aside, it was a great read, even 63 years after it being published.

The book is aimed at experienced players, offering insight to common mistakes in bidding and game play.  It was interesting jumping ahead of myself, as  I have only read a beginners guide a couple of times, and the subtlety of the bidding signals seemed over the top, but after reading how the hand is played out, and how the inferences are used to guide play, I’ve become motivated to learn correct bidding.  Bridge feels very similar to Preference or 500, just with a mind boggling large set of signaling bids and plays.

Much learning ahead, but I’m excited…

Creating Palette based GIFs

A question was asked on the mailing list (ages ago) about creating 8-bit GIF files.  I proved this code for simple palette based GIFs, so here it is:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Project
{
    class ProjectMain
    {
        public static void Main()
        {
            GenerateBackgroundImage(Color.AliceBlue, Color.Beige, Color.Cyan, 10, 10, 10, @"c:\image.gif");
        }

        public static void GenerateBackgroundImage(Color leftColour, Color centerColour,
            Color rightColour, int leftWidth, int centerWidth, int rightWidth, string path)
        {

            int width = leftWidth + centerWidth + rightWidth + 2;
            int height = 10;

            using (Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed))
            {
                Color backColour = Color.White;
                byte idxBackground = 0;
                byte idxLeft = 1;
                byte idxCenter = 2;
                byte idxRight = 3;

                ColorPalette cp = bitmap.Palette;
                cp.Entries[idxBackground] = backColour;
                cp.Entries[idxLeft] = leftColour;
                cp.Entries[idxCenter] = centerColour;
                cp.Entries[idxRight] = rightColour;

                bitmap.Palette = cp;

                fillrect(idxBackground, bitmap, new Rectangle(0, 0, width, height));
                fillrect(idxLeft, bitmap, new Rectangle(0, 0, leftWidth, height));
                fillrect(idxCenter, bitmap, new Rectangle(leftWidth + 1, 0, centerWidth, height));
                fillrect(idxRight, bitmap, new Rectangle(leftWidth + 2 + centerWidth, 0, rightWidth, height));

                bitmap.Save(path, ImageFormat.Gif);
            }
        }

        static void fillrect(byte colorIndex, Bitmap b, Rectangle r)
        {
            BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.WriteOnly, b.PixelFormat);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            // This code is specific to a bitmap with 8 bits index per pixels.
            int bytes = b.Width * b.Height;
            byte[] Values = new byte[bytes];

            // Copy the RGB values into the array.
            Marshal.Copy(ptr, Values, 0, bytes);

            for (int y = r.Top; y < r.Bottom; y++)
            {
                for (int x = r.Left; x < r.Right; x++)
                {
                    Values[(y * b.Width) + x] = colorIndex;
                }
            }

            // Copy the values back to the bitmap
            Marshal.Copy(Values, 0, ptr, bytes);

            // Unlock the bits.
            b.UnlockBits(bmpData);
        }
    }
}

I would change fillrect, to seperate out the locking, and Marshal calls, to CreateTempBuffer, FillTempBuffer, and WriteTempBuffer functions, if you were to use fillrect more than a couple times.  But as it stands, the code is correct after each call.