public override GameLevel GetLevel(int n)
        {
            if (n < 1 || n > levelCount)
            {
                throw new ArgumentException("Level outside of range");
            }

            GameLevel gameLevel = null;

            try
            {
                int offset = GetLevelOffset(n);
                chipDat.Seek(offset);
                int numBytesLevel = chipDat.ReadUnsignedWord();

                // So we don't have to skip over the same level again later
                levelOffsets[n + 1] = offset + numBytesLevel + 2;

                int levelNumber    = chipDat.ReadUnsignedWord();
                int numSeconds     = chipDat.ReadUnsignedWord();
                int numChipsNeeded = chipDat.ReadUnsignedWord();
                int mapDetail      = chipDat.ReadUnsignedWord();

                gameLevel = new GameLevel(32, 32, numChipsNeeded, numSeconds, levelNumber);

                int numberOfBytesLayer1 = chipDat.ReadUnsignedWord();
                ReadLayer(gameLevel, numberOfBytesLayer1, 1); // Layer 1, upper

                int numberOfBytesLayer2 = chipDat.ReadUnsignedWord();
                ReadLayer(gameLevel, numberOfBytesLayer2, 0); // Layer 2, lower
                int numBytesOptional     = chipDat.ReadUnsignedWord();
                int numOptionalBytesRead = 0;

                while (numOptionalBytesRead < numBytesOptional)
                {
                    int fieldType   = chipDat.ReadUnsignedByte();
                    int sizeOfField = chipDat.ReadUnsignedByte();
                    numOptionalBytesRead += 2;

                    switch (fieldType)
                    {
                    case 0x03:     // Map title
                        sbyte[] ASCIITitle = new sbyte[sizeOfField - 1];
                        chipDat.ReadFully(ASCIITitle);
                        string title = StringHelperClass.NewString(ASCIITitle, "ASCII");
                        gameLevel.MapTitle = title;
                        chipDat.SkipBytes(1);
                        break;

                    case 0x04:     // Brown buttons to traps
                        for (int i = 0; i < sizeOfField / 10; i++)
                        {
                            int buttonX = chipDat.ReadUnsignedWord();
                            int buttonY = chipDat.ReadUnsignedWord();
                            int trapX   = chipDat.ReadUnsignedWord();
                            int trapY   = chipDat.ReadUnsignedWord();

                            // Locate button
                            BlockContainer bc     = gameLevel.GetBlockContainer(buttonX, buttonY);
                            Block          button = bc.Find(Type.BROWNBUTTON);

                            // Locate trap
                            bc = gameLevel.GetBlockContainer(trapX, trapY);
                            Block trap = bc.Find(Type.TRAP);

                            if (button != null && trap != null)     // Perhaps throw an exception otherwise
                            {
                                Buttons.AddBrownButtonListener(button, trap);
                            }

                            chipDat.SkipBytes(2);
                        }
                        break;

                    case 0x05:
                        for (int i = 0; i < sizeOfField / 8; i++)
                        {
                            int buttonX = chipDat.ReadUnsignedWord();
                            int buttonY = chipDat.ReadUnsignedWord();
                            int clonerX = chipDat.ReadUnsignedWord();
                            int clonerY = chipDat.ReadUnsignedWord();

                            // Locate button
                            BlockContainer bc     = gameLevel.GetBlockContainer(buttonX, buttonY);
                            Block          button = bc.Find(Type.REDBUTTON);

                            // Locate cloner
                            bc = gameLevel.GetBlockContainer(clonerX, clonerY);
                            Block cloner = bc.Find(Type.CLONEMACHINE);

                            if (button != null && cloner != null)     // Perhaps throw an exception otherwise
                            {
                                Buttons.AddRedButtonListener(button, cloner);
                            }
                        }
                        break;

                    case 0x06:     // Password
                        string password = ReadPassword(sizeOfField);
                        gameLevel.Password        = password;
                        passwordToLevel[password] = n;
                        levelToPassword[n]        = password;
                        chipDat.SkipBytes(1);
                        break;

                    case 0x07:     // Hint
                        sbyte[] ASCIIHint = new sbyte[sizeOfField - 1];
                        chipDat.ReadFully(ASCIIHint);
                        string hint = StringHelperClass.NewString(ASCIIHint, "ASCII");
                        gameLevel.Hint = hint;
                        chipDat.SkipBytes(1);
                        break;

                    case 0x0A:     // Movement
                        for (int i = 0; i < sizeOfField / 2; i++)
                        {
                            int            creatureX = chipDat.ReadUnsignedByte();
                            int            creatureY = chipDat.ReadUnsignedByte();
                            Block          creature  = null;
                            BlockContainer bc;
                            Block          upper;

                            // Locate creature
                            bc    = gameLevel.GetBlockContainer(creatureX, creatureY);
                            upper = bc.Upper;
                            if (upper.Creature)
                            {
                                creature = upper;
                            }

                            if (creature != null)     // Perhaps throw an exception otherwise
                            {
                                Creatures.AddCreature(creature);
                            }
                        }
                        break;

                    default:
                        chipDat.SkipBytes(sizeOfField);
                        break;
                    }

                    numOptionalBytesRead += sizeOfField;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                Debug.Write(ex.StackTrace);
                Debug.WriteLine("While loading level: " + ex.Message);
            }

            return(gameLevel);
        }