Click here to Skip to main content
15,892,697 members
Articles / Artificial Intelligence

Battlefield Simulator

Rate me:
Please Sign up or sign in to vote.
4.86/5 (40 votes)
17 Nov 2009CPOL17 min read 97.8K   2K   104  
KOEI-like old-school war game and battlefield simulator, with infantry, artillery, and cavalry units.
  • battlefield_c_2008.zip
    • BattleField
      • barrage.bmp
      • BattleField Intro.bmp
      • BattleField.sln
      • BattleField.suo
      • BattleField
        • BattleField.csproj
        • BattleField.csproj.user
        • BattleFieldIcon.ico
        • bin
          • Release
            • BattleField.pdb
            • Map001.map
            • Map002.map
            • Map003.map
            • Map004.map
            • map005.map
            • Map006.map
            • Map007.map
            • Map008.map
            • Map009.map
            • MapPlainField.map
            • MapPlainField_large.map
        • classBattle.cs
        • classBattleField.cs
        • classBattleUnit.cs
        • classMapEditor.cs
        • classMessageBox.cs
        • formBattleField.cs
        • formBattleField.Designer.cs
        • formBattleField.resx
        • Program.cs
        • Properties
        • Resources
          • barrage.bmp
          • BattleField Intro.bmp
          • Blue_Artillery.bmp
          • Blue_Cavalry.bmp
          • Blue_Infantry.bmp
          • Font_0.bmp
          • Font_1.bmp
          • Font_2.bmp
          • Font_3.bmp
          • Font_4.bmp
          • Font_5.bmp
          • Font_6.bmp
          • Font_7.bmp
          • Font_8.bmp
          • Font_9.bmp
          • Font_RightSlash.bmp
          • horse_Left.bmp
          • horse_Right.bmp
          • rank_captain.bmp
          • rank_colonel.bmp
          • rank_field_marshall.bmp
          • rank_general.bmp
          • rank_lieutenant.bmp
          • rank_major.bmp
          • Red_Artillery.bmp
          • Red_Cavalry.bmp
          • Red_Infantry.bmp
          • terrain_castle.bmp
          • terrain_castle_shaded.bmp
          • terrain_castle_target.bmp
          • terrain_forest.bmp
          • terrain_forest_shaded.bmp
          • terrain_forest_target.bmp
          • terrain_grass.bmp
          • terrain_grass_shaded.bmp
          • terrain_grass_target.bmp
          • terrain_mountain.bmp
          • terrain_mountain_shaded.bmp
          • terrain_mountain_target.bmp
          • terrain_road.bmp
          • terrain_road_shaded.bmp
          • terrain_road_target.bmp
          • terrain_water.bmp
          • terrain_water_shaded.bmp
          • terrain_water_target.bmp
      • BattleFieldIcon.ico
      • Blue_Artillery.bmp
      • Blue_Cavalry.bmp
      • Blue_Infantry.bmp
      • Font_0.bmp
      • Font_1.bmp
      • Font_2.bmp
      • Font_3.bmp
      • Font_4.bmp
      • Font_5.bmp
      • Font_6.bmp
      • Font_7.bmp
      • Font_8.bmp
      • Font_9.bmp
      • Font_RightSlash.bmp
      • horse_Left.bmp
      • horse_Right.bmp
      • rank_captain.bmp
      • rank_colonel.bmp
      • rank_field_marshall.bmp
      • rank_general.bmp
      • rank_lieutenant.bmp
      • rank_major.bmp
      • Red_Artillery.bmp
      • Red_Cavalry.bmp
      • Red_Infantry.bmp
      • terrain_castle.bmp
      • terrain_castle_shaded.bmp
      • terrain_castle_target.bmp
      • terrain_forest.bmp
      • terrain_forest_shaded.bmp
      • terrain_forest_target.bmp
      • terrain_grass.bmp
      • terrain_grass_shaded.bmp
      • terrain_grass_target.bmp
      • terrain_mountain.bmp
      • terrain_mountain_shaded.bmp
      • terrain_mountain_target.bmp
      • terrain_road.bmp
      • terrain_road_shaded.bmp
      • terrain_road_target.bmp
      • terrain_water.bmp
      • terrain_water_shaded.bmp
      • terrain_water_target.bmp
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using battle;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.Serialization.Formatters.Binary;

namespace battle
{
    public class classMapEditor : Form
    {
        #region "objects"
        public Form callingForm;
        public classBattle cLibBattle;
        System.Windows.Forms.Panel pnlMap = new Panel();
        PictureBox picMap = new PictureBox();
        VScrollBar VSB = new VScrollBar();
        HScrollBar HSB = new HScrollBar();
        System.Windows.Forms.Timer tmrSizechange = new System.Windows.Forms.Timer();
        Graphics gr;
        public  classEditControls formEditControls;
        #endregion

        #region "structures"

        public struct udtInitUnitLoc
        {
            public classBattle.enuInitialUnitLocDirIndices typeLoc;
            public int intIndex;
            public bool flag;
        }

        public struct udtMapEditTerrain
        {
            public classBattle.enuTerrainTypes type;
            public udtInitUnitLoc initUnitLoc;
        }
        public struct udt2DTerrain
        {
            public udtMapEditTerrain[] Rows;
        }
        #endregion

        #region "enumerated types"
        public enum enuDrawingStyle { singleCell, brush, floodfill }
        public enum enuModes { Drawing, RedLaunchSet, BlueLaunchSet }
        #endregion

        #region "variables"
        const int intVerticalOffset = 40;
        const int intScrollBarMax = 1000;

        public udt2DTerrain[] TerrainColumns;

        public classBattle.udtCartesian MapSize;
        public int intMapGridSize = 35;   // pixel size of each map square as they appear on the screen

        public classBattle.udtCartesian udrMouseHoverIndex = new classBattle.udtCartesian();

        public enuDrawingStyle DrawingStyle = enuDrawingStyle.singleCell;
        public  bool bolToggleBrush;
        bool bolKillEditForm = false;
        
        classBattle.udtCartesian[] udrBlueLaunchLocs = new classBattle.udtCartesian[(int)classBattle.intMaxInvasionForce];
        classInitLaunchDisplayLabel[] lblBlueLaunchLabels = new classInitLaunchDisplayLabel[classBattle.intMaxInvasionForce];
        
        classBattle.udtRedLaunchLocations udrRedLaunchLocs = new classBattle.udtRedLaunchLocations();
        classInitLaunchDisplayLabel[] lblRedLaunchLabels = new classInitLaunchDisplayLabel[classBattle.intMaxInvasionForce];
        public int intRedLaunchDirIndex = 0;
        public enuModes mode = enuModes.Drawing;
        public bool bolBlinkCursor, bolBlinkCursorImage;
        Cursor cRememberCursor;
        Timer tmrBlinkCurosr = new Timer();
        #endregion

        public classMapEditor(classBattle _cLibBattle, Form callingForm_local)
        {
            cLibBattle = _cLibBattle;
            callingForm = callingForm_local;
            Text = "Map Editor";

            Controls.Add(HSB);
            HSB.Visible = true;

            Controls.Add(VSB);
            VSB.Visible = true;

            Controls.Add(pnlMap);
            pnlMap.Visible = true;

            tmrSizechange.Tick += new EventHandler(tmrSizechange_Tick);
            SizeChanged += new EventHandler(classMapEditor_SizeChanged);

            Disposed += new EventHandler(classMapEditor_Disposed);

            VSB.ValueChanged += new EventHandler(VSB_ValueChanged);
            HSB.ValueChanged += new EventHandler(HSB_ValueChanged);

            setMenuStrip();
            pnlMap.Controls.Add(picMap);
            picMap.Dock = DockStyle.Fill;
            picMap.Visible = true;
            gr = picMap.CreateGraphics();
            MapSize.x = 15; MapSize.y = 15;
                        
            createEditForm();
            resizeMap();
            displayMap();
            resetScrollBars();
            tmrBlinkCurosr.Interval = 500;
            tmrBlinkCurosr.Tick += new EventHandler(tmrBlinkCurosr_Tick);
           
            picMap.MouseMove += new MouseEventHandler(picMap_MouseMove);
            picMap.Click += new EventHandler(picMap_Click);
            picMap.Paint += new PaintEventHandler(picMap_Paint);
            Activated += new EventHandler(classMapEditor_Activated);
        }

        void picMap_Paint(object sender, PaintEventArgs e)
        {
            PictureBox thisPic = (PictureBox)sender;

            //thisPic.Image = e.Graphics.
        }

        void classMapEditor_Activated(object sender, EventArgs e) 
        {
        //    displayMap(); 
        }

        void picMap_MouseMove(object sender, MouseEventArgs e)
        {
            PictureBox picMap = (PictureBox)sender;
            classBattle.udtCartesian udrLoc_New = determineMapGridLocByObjectLoc(e.X, e.Y);
            if (LocOnMap (udrLoc_New))
            {
            Text = "(" + udrLoc_New.x.ToString() + ", " + udrLoc_New.y.ToString() + ")";
            
            if (udrLoc_New.x != udrMouseHoverIndex.x
                || udrLoc_New.y != udrMouseHoverIndex.y)
            {
                displayMapLoc(udrMouseHoverIndex, classBattle.enuTerrainImageSetting.normal);
                udrMouseHoverIndex = udrLoc_New;
                displayMapLoc(udrMouseHoverIndex, classBattle.enuTerrainImageSetting.shaded);
             
            }
            if (DrawingStyle == enuDrawingStyle.brush && bolToggleBrush)
            {
                TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].type = formEditControls.SelectedNewTerrainType;
            }
            showHoverOverTerrainInfo();
            }
            picMap.Refresh();
        }

        void displayMapLoc(classBattle.udtCartesian udrLoc,classBattle. enuTerrainImageSetting terrainImageSetting)
        {
            if (LocOnMap(udrLoc))
            {
                Point pt = new Point(getGridMapObjectLeft(udrLoc.x), getGridMapObjectTop(udrLoc));
                gr.DrawImage(cLibBattle.getTerrainImage(TerrainColumns[udrLoc.x].Rows[udrLoc.y].type, terrainImageSetting), pt.X, pt.Y, intMapGridSize, intMapGridSize);
            }
        }

        Image ResizeImage(Image imgInput) { return ResizeImage(intMapGridSize, imgInput); }
        Image ResizeImage(int intSizeSquare, Image imgInput) { return ResizeImage(cLibBattle.getPos(intSizeSquare, intSizeSquare), imgInput); }
        Image ResizeImage(classBattle.udtCartesian udrNewDimensions, Image imgInput) { return new Bitmap(imgInput, udrNewDimensions.x, udrNewDimensions.y); }
 
        void picMap_Click(object sender, EventArgs e)
        {
            switch (mode)
            {
                case enuModes.Drawing:
                    if (DrawingStyle == enuDrawingStyle.singleCell)
                        TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].type = formEditControls.SelectedNewTerrainType;
                    else if (DrawingStyle == enuDrawingStyle.floodfill)
                        floodFill();
                    else if (DrawingStyle == enuDrawingStyle.brush)
                    {
                        bolToggleBrush = !bolToggleBrush;
                        displayBolToggleBrush();
                    }
                    break;

                case enuModes.BlueLaunchSet:
                    if (TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].initUnitLoc.flag)
                        return;
                    resetTerrainInitUnitLoc(udrBlueLaunchLocs[formEditControls.intCurrentBlueLaunchLabelCounter]);
                    udrBlueLaunchLocs[formEditControls.intCurrentBlueLaunchLabelCounter] = udrMouseHoverIndex;
                    setTerrainInitUnitLoc(udrMouseHoverIndex, classBattle.enuInitialUnitLocDirIndices.Blue, formEditControls.intCurrentBlueLaunchLabelCounter);
                    formEditControls.intCurrentBlueLaunchLabelCounter = (formEditControls.intCurrentBlueLaunchLabelCounter + 1) % classBattle.intMaxInvasionForce;
                    displayBlueLaunchLabels();
                    break;

                case enuModes.RedLaunchSet:
                    if (TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].initUnitLoc.flag)
                        return;
                    resetTerrainInitUnitLoc(udrRedLaunchLocs.dir[intRedLaunchDirIndex].loc[formEditControls.intCurrentRedLaunchLabelCounter]);
                    udrRedLaunchLocs.dir[intRedLaunchDirIndex].loc[formEditControls.intCurrentRedLaunchLabelCounter] = udrMouseHoverIndex;
                    setTerrainInitUnitLoc(udrMouseHoverIndex, (classBattle.enuInitialUnitLocDirIndices)formEditControls.intCurrentRedLaunchLabelCounter, formEditControls.intCurrentRedLaunchLabelCounter);
                    formEditControls.intCurrentRedLaunchLabelCounter = (formEditControls.intCurrentRedLaunchLabelCounter + 1) % classBattle.intMaxInvasionForce;
                    displayRedLaunchLabels();
                    break;
            }
            picMap.Refresh();
        }

        public void blinkCursor()
        {
            cRememberCursor = Cursor;
            bolBlinkCursor = true;
            tmrBlinkCurosr.Enabled = true;
        }

        void tmrBlinkCurosr_Tick(object sender, EventArgs e)
        {
            tmrBlinkCurosr.Enabled = bolBlinkCursor;
            if (bolBlinkCursorImage)
                Cursor = cRememberCursor;
            else
                Cursor = Cursors.Arrow;

            bolBlinkCursorImage = !bolBlinkCursorImage;
        }

        void initLaunchLocs()
        {
            // Red
            udrRedLaunchLocs.dir = new classBattle.udtCartesian_Array[(int)classBattle.enuInitialUnitLocDirIndices._num_RedInitialLocIndices];
            int intMidRangeValue = classBattle.intMaxInvasionForce/2;
            int intEdgeStart_X = (MapSize.x - intMidRangeValue ) / 2;
            int intEdgeStart_Y = (MapSize.y - intMidRangeValue ) / 2;
            classBattle.udtCartesian udrCorner = new classBattle.udtCartesian();
            classBattle.udtCartesian udrCornerSigns = new classBattle.udtCartesian();
            int[] intCornerShift_X = { 0, 0, 1, 0, 1, 2, 0, 1, 2, 3 };
            int[] intCornerShift_Y = { 0, 1, 0, 2, 1, 0, 3, 2, 1, 0 };

            for (int intX = 0; intX < MapSize.x; intX++)
                for (int intY = 0; intY < MapSize.y; intY++)
                    TerrainColumns[intX].Rows[intY].initUnitLoc.flag = false;

            for (classBattle.enuInitialUnitLocDirIndices dirCounter = 0; dirCounter < classBattle.enuInitialUnitLocDirIndices._num_RedInitialLocIndices; dirCounter++)
            {
                udrRedLaunchLocs.dir[(int)dirCounter].loc = new classBattle.udtCartesian[classBattle.intMaxInvasionForce];
                switch (dirCounter)
                {
                    case classBattle.enuInitialUnitLocDirIndices.Red_NE:
                        udrCorner.x = MapSize.x - 1;
                        udrCorner.y = 0;
                        udrCornerSigns.x = -1;
                        udrCornerSigns.y = 1;
                        break;

                    case classBattle.enuInitialUnitLocDirIndices.Red_NW:
                        udrCorner.x = 0;
                        udrCorner.y = 0;
                        udrCornerSigns.x = 1;
                        udrCornerSigns.y = 1;
                        break;

                    case classBattle.enuInitialUnitLocDirIndices.Red_SE:
                        udrCorner.x = MapSize.x - 1;
                        udrCorner.y = MapSize.y - 1;
                        udrCornerSigns.x = -1;
                        udrCornerSigns.y = -1;
                        break;

                    case classBattle.enuInitialUnitLocDirIndices.Red_SW:
                        udrCorner.x = 0;
                        udrCorner.y = MapSize.y - 1;
                        udrCornerSigns.x = 1;
                        udrCornerSigns.y = -1;
                        break;
                }
                for (int intLocCounter = 0; intLocCounter < classBattle.intMaxInvasionForce; intLocCounter++)
                {
                    int intMidRange_Offset = (intLocCounter >= (classBattle.intMaxInvasionForce / 2) ? 1 : 0);
                    switch (dirCounter)
                    {
                        case classBattle.enuInitialUnitLocDirIndices.Red_N:
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].x = intEdgeStart_X + intLocCounter - (intLocCounter >= intMidRangeValue ? intMidRangeValue : 0);
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].y = intMidRange_Offset;
                            break;

                        case classBattle.enuInitialUnitLocDirIndices.Red_E:
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].y = intEdgeStart_Y + intLocCounter - (intLocCounter >= intMidRangeValue ? intMidRangeValue : 0);
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].x = MapSize.x -1 - intMidRange_Offset;
                            break;

                        case classBattle.enuInitialUnitLocDirIndices.Red_S:
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].x = intEdgeStart_X + intLocCounter - (intLocCounter >= intMidRangeValue ? intMidRangeValue : 0);
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].y = MapSize.y -1 - intMidRange_Offset;
                            break;

                        case classBattle.enuInitialUnitLocDirIndices.Red_W:
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].y = intEdgeStart_Y + intLocCounter - (intLocCounter >= intMidRangeValue ? intMidRangeValue : 0);
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].x = intMidRange_Offset;
                            break;

                        case classBattle.enuInitialUnitLocDirIndices.Red_NE:
                        case classBattle.enuInitialUnitLocDirIndices.Red_SE:
                        case classBattle.enuInitialUnitLocDirIndices.Red_SW:
                        case classBattle.enuInitialUnitLocDirIndices.Red_NW:
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].x = udrCorner.x + udrCornerSigns.x * intCornerShift_X[intLocCounter];
                            udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter].y = udrCorner.y + udrCornerSigns.y * intCornerShift_Y[intLocCounter];
                            break;
                    }
                    setTerrainInitUnitLoc(udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter], dirCounter, intLocCounter);
                }
            }

            //Blue
            int[] intTurnCounter = { 1, 2, 4, 6, 9 };
            classBattle.udtCartesian udrPos = cLibBattle.getPos(MapSize.x / 2, MapSize.y / 2);
            classBattle.enuDirections[] dirArray = { 
                                                       classBattle.enuDirections.NE,
                                                       classBattle.enuDirections.NW ,
                                                       classBattle.enuDirections.SW,
                                                       classBattle.enuDirections.S_,
                                                       classBattle.enuDirections.SE,
                                                       classBattle.enuDirections.NE,
                                                       classBattle.enuDirections.NE,
                                                       classBattle.enuDirections.N_,
                                                       classBattle.enuDirections.NW,
                                                       classBattle.enuDirections.NW 
                                                   };
            for (int intLocCounter = 0; intLocCounter < udrBlueLaunchLocs.Length; intLocCounter++)
            {
                udrBlueLaunchLocs[intLocCounter] = udrPos;
                setTerrainInitUnitLoc(udrPos, classBattle.enuInitialUnitLocDirIndices.Blue);
                udrPos = getNextPos(udrPos, dirArray[intLocCounter]);
            }



        }

        void setMenuStrip()
        {
            MenuStrip ms = new MenuStrip();
                        
            ToolStripMenuItem mnuFile = new ToolStripMenuItem("&File");
            ms.Items.Add(mnuFile);
            mnuFile.Visible = true;

            ToolStripMenuItem mnuFileLoad = new ToolStripMenuItem("&Load", null, new EventHandler(mnuLoad_Click));
            mnuFile.DropDownItems.Add(mnuFileLoad);
            mnuFileLoad.Visible = true;
            
            ToolStripMenuItem mnuFileSave = new ToolStripMenuItem("&Save", null, new EventHandler(mnuSave_Click));
            mnuFile.DropDownItems.Add(mnuFileSave);
            mnuFileSave.Visible = true;
            
            ToolStripMenuItem mnuFileNew = new ToolStripMenuItem("&New", null, new EventHandler(mnuNew_Click));
            mnuFile.DropDownItems.Add(mnuFileNew);
            mnuFileNew.Visible = true;
            
            ToolStripMenuItem mnuFileQuit = new ToolStripMenuItem("&Quit", null, new EventHandler(mnuQuit_Click));
            mnuFile.DropDownItems.Add(mnuFileQuit);
            mnuFileQuit.Visible = true;
            
            Controls.Add(ms);
            ms.Visible = true;
            ms.BringToFront();
        }

        void mnuQuit_Click(object sender, EventArgs e) { Dispose(); }
        void mnuNew_Click(object sender, EventArgs e) { initMap(); }
        void mnuSave_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
            sfd.Filter = "Map files (*.map)|*.map";
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                string strFilename = sfd.FileName;
                if (!strFilename.Contains("."))
                    strFilename += ".map";

                BinaryFormatter formatter = new BinaryFormatter();

                FileStream fs;
                fs = new FileStream(strFilename, FileMode.Create);
                formatter.Serialize(fs, MapSize);
                
                for (int intY = 0; intY < MapSize.y; intY++)
                {
                    string strTerrain = "";
                    for (int intX = 0; intX < MapSize.x; intX++)
                        strTerrain += TerrainColumns[intX].Rows[intY].type.ToString().Substring(0, 1).ToUpper();
                    formatter.Serialize(fs, strTerrain);    
                }

                for (classBattle.enuInitialUnitLocDirIndices dirCounter = 0; dirCounter < classBattle.enuInitialUnitLocDirIndices._num_RedInitialLocIndices; dirCounter++)
                    for (int intLocCounter = 0; intLocCounter < classBattle.intMaxInvasionForce; intLocCounter++)
                        formatter.Serialize(fs, udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter]);

                for (int intLocCounter = 0; intLocCounter < classBattle.intMaxInvasionForce; intLocCounter++)
                    formatter.Serialize(fs, udrBlueLaunchLocs[intLocCounter]);

                fs.Close();
               
            }
        }

        public void resetTerrainInitUnitLoc(classBattle.udtCartesian udrLoc) { TerrainColumns[udrLoc.x].Rows[udrLoc.y].initUnitLoc.flag = false; }
        public void setTerrainInitUnitLoc(classBattle.udtCartesian udrLoc, classBattle.enuInitialUnitLocDirIndices initUnitLocType)
        {
            setTerrainInitUnitLoc(udrLoc, initUnitLocType, (initUnitLocType == classBattle.enuInitialUnitLocDirIndices.Blue)
                                      ? formEditControls.intCurrentBlueLaunchLabelCounter
                                      : formEditControls.intCurrentRedLaunchLabelCounter);
        }
            public void setTerrainInitUnitLoc(classBattle.udtCartesian udrLoc, classBattle.enuInitialUnitLocDirIndices initUnitLocType, int intIndex)
        {
            TerrainColumns[udrLoc.x].Rows[udrLoc.y].initUnitLoc.flag = true;
            TerrainColumns[udrLoc.x].Rows[udrLoc.y].initUnitLoc.intIndex = intIndex ;                 
            TerrainColumns[udrLoc.x].Rows[udrLoc.y].initUnitLoc.typeLoc = initUnitLocType;
        }

        void mnuLoad_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
            ofd.Filter = "map files (*.map)|*.map";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string strFilename = ofd.FileName;
                if (System.IO.File.Exists(strFilename))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    if (File.Exists(strFilename))
                    {
                        FileStream fs = new FileStream(strFilename, FileMode.Open);

                        MapSize = (classBattle.udtCartesian)formatter.Deserialize(fs);
                        formEditControls.nudHeight.Value = MapSize.y;
                        formEditControls.nudWidth.Value = MapSize.x;
                        string[] strTerrain = new string[MapSize.y+1];
                        for (int intY = 0; intY < MapSize.y; intY++)
                            strTerrain[intY] =((string)formatter.Deserialize(fs)).ToUpper();

                        if (strTerrain != null && strTerrain.Length > 0)
                        {
                            MapSize.y = strTerrain.Length - 1;
                            if (strTerrain[0].Length > 0)
                            {
                                string strTypeChar = "GFRWMC";// grass, forest, road, water, mountain, castle
                                MapSize.x = strTerrain[0].Length;
                                Array.Resize<udt2DTerrain>(ref TerrainColumns, MapSize.x + 1);

                                for (int intX = 0; intX < MapSize.x; intX++)
                                {
                                    Array.Resize<udtMapEditTerrain>(ref TerrainColumns[intX].Rows, MapSize.y);
                                    for (int intY = 0; intY < MapSize.y; intY++)
                                    {
                                        int intTerrainType = strTypeChar.IndexOf(strTerrain[intY].Substring(intX, 1));
                                        TerrainColumns[intX].Rows[intY].type = (classBattle.enuTerrainTypes)intTerrainType;
                                        TerrainColumns[intX].Rows[intY].initUnitLoc.flag = false;
                                    }
                                }
                            }
                            displayMap();
                        }

                        for (classBattle.enuInitialUnitLocDirIndices dirCounter = 0; dirCounter < classBattle.enuInitialUnitLocDirIndices._num_RedInitialLocIndices; dirCounter++)
                            for (int intLocCounter = 0; intLocCounter < classBattle.intMaxInvasionForce; intLocCounter++)
                                udrRedLaunchLocs.dir[(int)dirCounter].loc[intLocCounter] = (classBattle.udtCartesian) formatter.Deserialize(fs);

                        for (int intLocCounter = 0; intLocCounter < classBattle.intMaxInvasionForce; intLocCounter++)
                            udrBlueLaunchLocs[intLocCounter] = (classBattle.udtCartesian)formatter.Deserialize(fs);
                        
                        fs.Close();

                      
                    }
                }
            }
        }

        void initMap()
        {
            MapSize.x = 15; MapSize.y = 15;
            formEditControls.Dispose(); // will trip a new one
            resizeMap();

            for (int intX = 0; intX < MapSize.x; intX++)
            {
                for (int intY = 0; intY < MapSize.y; intY++)
                    TerrainColumns[intX].Rows[intY].type = classBattle.enuTerrainTypes.grass;
            }

            displayMap();
        }

        void classMapEditor_Disposed(object sender, EventArgs e) { killEditForm(); }

        void classMapEditor_SizeChanged(object sender, EventArgs e) { tmrSizechange.Enabled = true; }

        void tmrSizechange_Tick(object sender, EventArgs e)
        {
            tmrSizechange.Enabled = false;
            resetScrollBars();

            //displayMap();
        }

        void createEditForm()
        {
            formEditControls = new classEditControls(this,ref cLibBattle);
            formEditControls.Disposed += new EventHandler(formEditControls_Disposed);
        }

        public void resizeMap()
        {
            Array.Resize<udt2DTerrain>(ref TerrainColumns, MapSize.x);
            for (int intColumncounter = 0; intColumncounter < TerrainColumns.Length; intColumncounter++)
                Array.Resize<udtMapEditTerrain>(ref TerrainColumns[intColumncounter].Rows, MapSize.y);

            displayMap();
            initLaunchLocs();
        }

        //void displayMapLoc(classBattle.udtCartesian udrLoc, classBattle.enuTerrainImageSetting terrainImageSetting)
        //{
        //    if (LocOnMap(udrLoc))
        //    {
        //        Point pt = new Point(getGridMapObjectLeft(udrLoc.x), getGridMapObjectTop(udrLoc));
        //        gr.DrawImage(getTerrainImage(TerrainColumns[udrLoc.x].Rows[udrLoc.y].type, terrainImageSetting), pt.X, pt.Y, intMapGridSize, intMapGridSize);
        //    }
        //}

        public void displayMap()
        {
            Bitmap entireMap = new Bitmap(MapSize.x * intMapGridSize, (int)( (MapSize.y+.5) * intMapGridSize)); // make the bitmap large enough to contain all of your tiles.
            picMap.Image = entireMap;

            gr = Graphics.FromImage(entireMap);
            if (TerrainColumns != null && TerrainColumns[0].Rows != null)
                    for (int intY = 0; intY < MapSize.y; intY++)
                        for (int intX = 0; intX < MapSize.x; intX++)
                            displayMapLoc(cLibBattle.getPos(intX, intY),classBattle. enuTerrainImageSetting.normal);

                pnlMap.BackColor = Color.Black;
                pnlMap.Width = MapSize.x * intMapGridSize;
                pnlMap.Height = (int)(((double)MapSize.y + .5) * intMapGridSize);
            
        }

        public Cursor getTerrainTypeCursor(classBattle.enuTerrainTypes terrainType)
        {
            Bitmap btMap = new Bitmap(cLibBattle.getTerrainImage(terrainType), intMapGridSize/3, intMapGridSize/            3);
            IntPtr ptr = btMap.GetHicon();
            return new Cursor(ptr);
        }

        void displayBolToggleBrush()
        {
            formEditControls.rdbDrawingStyleBrush.ForeColor = (bolToggleBrush ? Color.Red : Color.Black);
            Cursor = (bolToggleBrush ? getTerrainTypeCursor(formEditControls.SelectedNewTerrainType   ) : Cursors.No);
        }
   
        void picMap_MouseClick(object sender, MouseEventArgs e)
        {
            switch (mode)
            {
                case enuModes.Drawing:
                    if (DrawingStyle == enuDrawingStyle.singleCell)
                        TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].type = formEditControls.SelectedNewTerrainType;
                    else if (DrawingStyle == enuDrawingStyle.floodfill)
                        floodFill();
                    else if (DrawingStyle == enuDrawingStyle.brush)
                    {
                        bolToggleBrush = !bolToggleBrush;
                        displayBolToggleBrush();
                    }
                    break;

                case enuModes.BlueLaunchSet:
                    if (TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].initUnitLoc.flag)
                        return;
                    resetTerrainInitUnitLoc(udrBlueLaunchLocs[formEditControls.intCurrentBlueLaunchLabelCounter]);
                    udrBlueLaunchLocs[formEditControls.intCurrentBlueLaunchLabelCounter] = udrMouseHoverIndex;
                    setTerrainInitUnitLoc(udrMouseHoverIndex, classBattle.enuInitialUnitLocDirIndices.Blue, formEditControls.intCurrentBlueLaunchLabelCounter);
                    formEditControls.intCurrentBlueLaunchLabelCounter = (formEditControls.intCurrentBlueLaunchLabelCounter + 1) % classBattle.intMaxInvasionForce;
                    displayBlueLaunchLabels();
                    break;

                case enuModes.RedLaunchSet:
                    if (TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].initUnitLoc.flag)
                        return;
                    resetTerrainInitUnitLoc(udrRedLaunchLocs.dir [intRedLaunchDirIndex ].loc [ formEditControls.intCurrentRedLaunchLabelCounter]);
                    udrRedLaunchLocs.dir[intRedLaunchDirIndex].loc[formEditControls.intCurrentRedLaunchLabelCounter] = udrMouseHoverIndex;
                    setTerrainInitUnitLoc(udrMouseHoverIndex, (classBattle.enuInitialUnitLocDirIndices)formEditControls.intCurrentRedLaunchLabelCounter, formEditControls.intCurrentRedLaunchLabelCounter);
                    formEditControls.intCurrentRedLaunchLabelCounter = (formEditControls.intCurrentRedLaunchLabelCounter + 1) % classBattle.intMaxInvasionForce;
                    displayRedLaunchLabels();
                    break;
            }
        }

       
        void killEditForm()
        {
            bolKillEditForm = true;
            formEditControls.Dispose();
        }

        void formEditControls_Disposed(object sender, EventArgs e)
        {
            if (bolKillEditForm)
                return;
            createEditForm();
        }

        bool LocOnMap(classBattle.udtCartesian udrLoc)
        {
            return (udrLoc.x >= 0
                    && udrLoc.x < MapSize.x
                    && udrLoc.y >= 0
                    && udrLoc.y < MapSize.y);
        }

        void showHoverOverTerrainInfo()
        {
            if (LocOnMap(udrMouseHoverIndex))
                formEditControls.lblMouseInfo.Text = "("
                                                   + udrMouseHoverIndex.x.ToString()
                                                   + ", "
                                                   + udrMouseHoverIndex.y.ToString()
                                                   + ") : "
                                                   + TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].type.ToString();
        }

        #region "scroll bars"
        void resetScrollBars()
        {
            VSB.Top = 5; VSB.Left = Width - VSB.Width - 15;
            VSB.Height = Height - intVerticalOffset - HSB.Height;
            VSB.Visible = true;

            HSB.Top = VSB.Top + VSB.Height;
            HSB.Left = 5;
            HSB.Width = Width - 35;
            HSB.Visible = true;

            VSB.BringToFront();
            HSB.BringToFront();

            // remember what was visible before size change
            classBattle.udtCartesian udrVisiblePos = new classBattle.udtCartesian();
            udrVisiblePos.x = -pnlMap.Left;
            udrVisiblePos.y = -pnlMap.Top;

            classBattle.udtCartesian udrVisibleMapSquare = determineMapGridLocByObjectLoc(udrVisiblePos);

            // adjust scroll bars to fit new size
            if (Width > pnlMap.Width)
                HSB.Visible = false;
            else
            {
                HSB.LargeChange = (int)(((double)Width / (double)pnlMap.Width) * intScrollBarMax / 2);
                HSB.Maximum = intScrollBarMax - HSB.LargeChange;
            }

            if (Height - intVerticalOffset > pnlMap.Height)
            {
                VSB.Visible = false;
                pnlMap.Top = intVerticalOffset;
            }
            else
            {
                VSB.LargeChange = (int)(((double)Height / (double)pnlMap.Height) * intScrollBarMax / 2);
                VSB.Maximum = intScrollBarMax - VSB.LargeChange;
            }

            try { HSB.Value = (int)((double)udrVisibleMapSquare.x / (double)MapSize.x * HSB.Maximum); }
            catch (Exception) { }
            try { VSB.Value = (int)((double)udrVisibleMapSquare.y / (double)MapSize.y * VSB.Maximum); }
            catch (Exception) { }
        }

        void HSB_ValueChanged(object sender, EventArgs e)
        {
            int intMaxLeft = pnlMap.Width - VSB.Left;
            double dblPercentageLeft = (double)HSB.Value / (double)(HSB.Maximum - HSB.LargeChange);
            pnlMap.Left = -(int)((double)intMaxLeft * dblPercentageLeft);
            //displayMap();
        }

        void VSB_ValueChanged(object sender, EventArgs e)
        {
            int intMaxTop = pnlMap.Height + intVerticalOffset - HSB.Top;
            double dblPercentageTop = (double)VSB.Value / (double)(VSB.Maximum - VSB.LargeChange);
            pnlMap.Top = intVerticalOffset - (int)((double)intMaxTop * dblPercentageTop);
            //displayMap();
        }
#endregion

        #region "helper function"

        classBattle.udtCartesian determineMapGridLocByObjectLoc(classBattle.udtCartesian udrPos) { return determineMapGridLocByObjectLoc(udrPos.x, udrPos.y); }
        classBattle.udtCartesian determineMapGridLocByObjectLoc(int intLeft, int intTop)
        {
            classBattle.udtCartesian udrRetVal;
            for (udrRetVal.x = 0; udrRetVal.x < MapSize.x; udrRetVal.x++)
                if (getGridMapObjectLeft(udrRetVal.x + 1) > intLeft)
                    break;
            for (udrRetVal.y = 0; udrRetVal.y < MapSize.y; udrRetVal.y++)
                if (getGridMapObjectTop(udrRetVal.x, udrRetVal.y + 1) > intTop)
                    break;

            return udrRetVal;
        }

        bool intIsEven(int intX) { return (intX % 2 == 0); }
        public classBattle.udtCartesian getNextPos(classBattle.udtCartesian unitPos, classBattle.enuDirections dir)
        {
            classBattle.udtCartesian udrMoveVector;
            udrMoveVector.x = 0;
            udrMoveVector.y = 0;
            if (intIsEven(unitPos.x))
            {
                switch (dir)
                {
                    case classBattle.enuDirections.NW:
                        udrMoveVector.x = -1;
                        udrMoveVector.y = 0;
                        break;
                    case classBattle.enuDirections.N_:
                        udrMoveVector.x = 0;
                        udrMoveVector.y = -1;
                        break;
                    case classBattle.enuDirections.NE:
                        udrMoveVector.x = 1;
                        udrMoveVector.y = 0;
                        break;

                    case classBattle.enuDirections.SE:
                        udrMoveVector.x = 1;
                        udrMoveVector.y = 1;
                        break;
                    case classBattle.enuDirections.S_:
                        udrMoveVector.x = 0;
                        udrMoveVector.y = 1;
                        break;
                    case classBattle.enuDirections.SW:
                        udrMoveVector.x = -1;
                        udrMoveVector.y = 1;
                        break;
                }
            }
            else
            {
                switch (dir)
                {
                    case classBattle.enuDirections.NW:
                        udrMoveVector.x = -1;
                        udrMoveVector.y = -1;
                        break;
                    case classBattle.enuDirections.N_:
                        udrMoveVector.x = 0;
                        udrMoveVector.y = -1;
                        break;
                    case classBattle.enuDirections.NE:
                        udrMoveVector.x = 1;
                        udrMoveVector.y = -1;
                        break;

                    case classBattle.enuDirections.SE:
                        udrMoveVector.x = 1;
                        udrMoveVector.y = 0;
                        break;
                    case classBattle.enuDirections.S_:
                        udrMoveVector.x = 0;
                        udrMoveVector.y = 1;
                        break;
                    case classBattle.enuDirections.SW:
                        udrMoveVector.x = -1;
                        udrMoveVector.y = 0;
                        break;
                }
            }
            unitPos.x += udrMoveVector.x;
            unitPos.y += udrMoveVector.y;
            return unitPos;
        }

        public int getGridMapObjectTop(classBattle.udtCartesian pos) { return getGridMapObjectTop(pos.x, pos.y); }
        public int getGridMapObjectTop(int intX, int intY)
        {
            return (int)((double)(intY + (intIsEven(intX) ? 0.5 : 0)) * (double)(intMapGridSize));
        }
        public int getGridMapObjectLeft(classBattle.udtCartesian pos) { return getGridMapObjectLeft(pos.x); }
        public int getGridMapObjectLeft(int intX) { return intMapGridSize * intX; }
        public classBattle.udtCartesian getGridLocation(classBattle.udtCartesian pos)
        {
            classBattle.udtCartesian udrRetVal = new classBattle.udtCartesian();
            udrRetVal.x = getGridMapObjectLeft(pos);
            udrRetVal.y = getGridMapObjectTop(pos);
            return udrRetVal;
        }
    
        public classBattle.enuDirections getDirFromString(string strDir)
        {
            switch (strDir)
            {
                case "NW":
                    return classBattle.enuDirections.NW;

                case "N_":
                    return classBattle.enuDirections.N_;

                case "NE":
                    return classBattle.enuDirections.NE;

                case "SW":
                    return classBattle.enuDirections.SW;

                case "S_":
                    return classBattle.enuDirections.S_;

                case "SE":
                    return classBattle.enuDirections.SE;

                default:
                    return classBattle.enuDirections._num_directions;
            }
        }
        #endregion

        #region "flood fill"

        void floodFill()
        {
            classBattle.enuTerrainTypes Type_Old = TerrainColumns[udrMouseHoverIndex.x].Rows[udrMouseHoverIndex.y].type;
            classBattle.enuTerrainTypes Type_New = formEditControls.SelectedNewTerrainType;

            int intInfinity = (int)Math.Pow(10, 5);

            classBattleUnit.udtPathMap[,] udrPathMap = new classBattleUnit.udtPathMap[MapSize.x, MapSize.y];
            for (int intX = 0; intX < MapSize.x; intX++)
                for (int intY = 0; intY < MapSize.y; intY++)
                {
                    udrPathMap[intX, intY].direction = classBattle.enuDirections._num_directions;
                    udrPathMap[intX, intY].intMovementCost = intInfinity;
                }

            classFloodFillElement FFeleQ = null;

            classFloodFillElement firstQele = new classFloodFillElement(0, udrMouseHoverIndex);
            enQFloodFillElement(ref FFeleQ, ref firstQele);

            udrPathMap[firstQele.pos.x, firstQele.pos.y].intMovementCost = 0;

            classFloodFillElement thisQEle = deQShortestPathElement(ref FFeleQ);

            while (thisQEle != null)
            {
                TerrainColumns[thisQEle.pos.x].Rows[thisQEle.pos.y].type = Type_New;
                string strDir = "";
                for (classBattle.enuDirections dirCounter = 0; dirCounter < classBattle.enuDirections._num_directions; dirCounter++)
                {
                    classBattle.udtCartesian udrNextPos = getNextPos(thisQEle.pos, dirCounter);
                    if (udrNextPos.x >= 0 && udrNextPos.y >= 0 && udrNextPos.x < MapSize.x && udrNextPos.y < MapSize.y)
                    {

                        int intNewMovementCost = thisQEle.intStepsFromStart + 1;
                        if (intNewMovementCost < udrPathMap[udrNextPos.x, udrNextPos.y].intMovementCost)
                            strDir += dirCounter.ToString();
                    }
                }

                while (strDir.Length > 0)
                {
                    string strThisDir = strDir.Substring(0, 2);
                    strDir = strDir.Substring(2);
                    int intDistanceFromStart_New = intInfinity;

                    classBattle.enuDirections dir_new = dir_new = getDirFromString(strThisDir);
                    classBattle.udtCartesian udrPos_new = getNextPos(thisQEle.pos, dir_new);
                    intDistanceFromStart_New = thisQEle.intStepsFromStart + 1;
                    if (intDistanceFromStart_New < udrPathMap[udrPos_new.x, udrPos_new.y].intMovementCost
                        && TerrainColumns[udrPos_new.x].Rows[udrPos_new.y].type == Type_Old)
                    {
                        udrPathMap[udrPos_new.x, udrPos_new.y].intMovementCost = intDistanceFromStart_New;

                        classFloodFillElement NewQele = new classFloodFillElement(udrPathMap[udrPos_new.x, udrPos_new.y].intStepsFromStart, udrPos_new);
                        enQFloodFillElement(ref FFeleQ, ref NewQele);
                    }
                }
                thisQEle = deQShortestPathElement(ref FFeleQ);
            }
            displayMap();
        }

        public classFloodFillElement deQShortestPathElement(ref classFloodFillElement FFele)
        {
            classFloodFillElement eleRetVal = FFele;
            if (FFele != null)
            {
                FFele = FFele.next;

                if (FFele != null)
                    FFele.previous = null;
                eleRetVal.next = null;
            }
            return eleRetVal;
        }

        public void enQFloodFillElement(ref classFloodFillElement FFele_thisQ, ref classFloodFillElement FFeleNew)
        {
            if (FFeleNew == null)
                return;

            if (FFele_thisQ == null)
            {
                FFele_thisQ = FFeleNew;
                FFeleNew.next = null;
                FFeleNew.previous = null;
            }
            else
            {  // rank by movement cost -> cheapest at the front
                if (FFele_thisQ.intStepsFromStart > FFeleNew.intStepsFromStart)
                {
                    FFeleNew.next = FFele_thisQ;
                    FFele_thisQ.previous = FFeleNew;

                    FFeleNew.previous = null;
                    FFele_thisQ = FFeleNew;
                }
                else
                {
                    classFloodFillElement thisElement = FFele_thisQ;
                    while (thisElement.next != null && thisElement.next.intStepsFromStart < FFeleNew.intStepsFromStart)
                        thisElement = thisElement.next;

                    FFeleNew.next = thisElement.next;
                    if (FFeleNew.next != null)
                        FFeleNew.next.previous = FFeleNew;

                    thisElement.next = FFeleNew;
                    FFeleNew.previous = thisElement;
                }
            }
        }
        #endregion

        public void eraseRedLaunchLabels() { eraseLaunchLabels(ref lblRedLaunchLabels); }
        public void displayRedLaunchLabels() { displayLaunchLabels(ref lblRedLaunchLabels, udrRedLaunchLocs.dir[intRedLaunchDirIndex].loc, classBattle.enuUnitColors.red); }
        public void eraseBlueLaunchLabels() { eraseLaunchLabels(ref lblBlueLaunchLabels); }
        public void displayBlueLaunchLabels() { displayLaunchLabels(ref lblBlueLaunchLabels, udrBlueLaunchLocs, classBattle.enuUnitColors.blue); }

        public void eraseLaunchLabels(ref classInitLaunchDisplayLabel[] lbls)
        {
            if (lbls != null)
                for (int intLabelCounter = 0; intLabelCounter < lbls.Length; intLabelCounter++)
                    if (lbls[intLabelCounter] != null)
                        lbls[intLabelCounter].Visible = false;
        }

        public void displayLaunchLabels(ref classInitLaunchDisplayLabel[] lbls, classBattle.udtCartesian[] udrLocs, classBattle.enuUnitColors clr)
        {
            if (udrLocs != null
                && udrLocs.Length >0)
            {
                if (lbls == null)
                    lbls = new classInitLaunchDisplayLabel[classBattle.intMaxInvasionForce];
                for (int intLocCounter = 0; intLocCounter < lbls.Length; intLocCounter++)
                {
                    if (lbls[intLocCounter] == null)
                    {
                        classInitLaunchDisplayLabel lblNew = new classInitLaunchDisplayLabel();
                        lblNew.AutoSize = true;
                        lblNew.Text = intLocCounter.ToString();
                        picMap.Controls.Add(lblNew);
                        lbls[intLocCounter] = lblNew;
                    }
                    else
                    {
                        lbls[intLocCounter].Visible = false;
                        // replace old image beneath now invisible label
                        //gr.DrawImage(lbls[intLocCounter].oldImage, lbls[intLocCounter].Left, lbls[intLocCounter].Top, lbls[intLocCounter].Width, lbls[intLocCounter].Height);
                    }
                    lbls[intLocCounter].Top = getGridMapObjectTop(udrLocs[intLocCounter]) +  5;
                    lbls[intLocCounter].Left = getGridMapObjectLeft(udrLocs[intLocCounter]) + 5;
                    
                    //// DEBUGHERE START
                    //// record old image 
                    //Bitmap bmpImage = new Bitmap(picMap.Image);
                    //Bitmap bmpCrop = bmpImage.Clone(new Rectangle(lbls[intLocCounter].Left, lbls[intLocCounter].Top, lbls[intLocCounter].Width, lbls[intLocCounter].Height), bmpImage.PixelFormat);
                    //lbls[intLocCounter].oldImage = (Image)(bmpCrop);
                    //// DEBUGHERE END

                    lbls[intLocCounter].Visible = true;
                    lbls[intLocCounter].BringToFront();

                    if (intLocCounter == formEditControls.intCurrentRedLaunchLabelCounter)
                    {
                        lbls[intLocCounter].ForeColor = (clr == classBattle.enuUnitColors.blue ? Color.Blue : Color.Red);
                        lbls[intLocCounter].BackColor = Color.Black;
                    }
                    else
                    {
                        lbls[intLocCounter].ForeColor = Color.Black;
                        lbls[intLocCounter].BackColor = (clr == classBattle.enuUnitColors.blue ? Color.Blue : Color.Red); 
                    }
                }
            }
        }
    }

    public class classPicSelection : PictureBox
    {
        public classBattle.enuTerrainTypes myTerrainType;
    }

    public class classEditControls : Form
    {
        public NumericUpDown nudWidth;
        public NumericUpDown nudHeight;
        classMapEditor callingForm;
        classBattle cLibBattle;
        public Label lblMouseInfo;
        classDirLabel[] lblRedInvasionDirLabels = new classDirLabel[(int)classBattle.intMaxInvasionForce];
        public classPicSelection[] picSelection = new classPicSelection[(int)classBattle.enuTerrainTypes._numTerrainTypes];
        Panel pnlBackOfSelectedPic = new Panel();

        public classBattle.enuTerrainTypes SelectedNewTerrainType;
        public int intCurrentRedLaunchLabelCounter =0;
        public int intCurrentBlueLaunchLabelCounter = 0;

        const int intBlindRedLocResetCountdown_max = 10;
        int intBlinkRedLocResetCountdown = intBlindRedLocResetCountdown_max;
        Timer tmrRedLocReset = new Timer();
        GroupBox grbRedInvasionDirection = new GroupBox();
        public GroupBox grbDrawingStyle = new GroupBox();
        RadioButton rdbDrawingStyleSingleCell = new RadioButton();
        public RadioButton rdbDrawingStyleBrush = new RadioButton();
        RadioButton rdbDrawingStyleFloodFill = new RadioButton();
        Label lblBlueDefenseLaunch = new Label();
                   
        public classEditControls( classMapEditor callingForm_local,ref classBattle cLibBattle_local)
        {
            callingForm = callingForm_local;
            cLibBattle = cLibBattle_local;

            Text = "Edit Controls";

            Label lblWidth = new Label();
            lblWidth.Text = "Width";
            lblWidth.AutoSize = true;
            Controls.Add(lblWidth);
            lblWidth.Left = 5; lblWidth.Top = 5;
            lblWidth.Visible = true;

            Label lblHeight = new Label();
            lblHeight.Text = "Height";
            lblHeight.AutoSize = true;
            Controls.Add(lblHeight);
            lblHeight.Left = 5; lblHeight.Top = lblWidth.Top + lblWidth.Height + 5;
            lblHeight.Visible = true;

            nudWidth = new NumericUpDown();
            nudWidth.Minimum = 10;
            nudWidth.Maximum = 100;
            nudWidth.Value = 15;
            nudWidth.Left = lblWidth.Left + (lblWidth.Width > lblHeight.Width ? lblWidth.Width : lblHeight.Width) + 5;
            nudWidth.Top = lblWidth.Top;
            nudWidth.Width = 50;
            Controls.Add(nudWidth);
            nudWidth.Visible = true;

            nudHeight = new NumericUpDown();
            nudHeight.Minimum = 10;
            nudHeight.Maximum = 100;
            nudHeight.Value = 15;
            nudHeight.Left = lblHeight.Left + (lblWidth.Width > lblHeight.Width ? lblWidth.Width : lblHeight.Width) + 5;
            nudHeight.Top = lblHeight.Top;
            nudHeight.Width = nudWidth.Width;
            Controls.Add(nudHeight);
            nudHeight.Visible = true;         

            lblMouseInfo = new Label();
            lblMouseInfo.Text = "()";
            lblMouseInfo.Left = 5; lblMouseInfo.Top = lblHeight.Top + lblHeight.Height + 5;
            lblMouseInfo.AutoSize = true;
            Controls.Add(lblMouseInfo);
            lblMouseInfo.Visible = true;

            pnlBackOfSelectedPic.Width = pnlBackOfSelectedPic.Height = 45;
            pnlBackOfSelectedPic.BackColor = Color.Black;

            for (int intPicSelected = 0; intPicSelected <(int) classBattle.enuTerrainTypes._numTerrainTypes; intPicSelected++)
            {
                picSelection[intPicSelected] = new classPicSelection();
                picSelection[intPicSelected].myTerrainType = (classBattle.enuTerrainTypes)intPicSelected;
                picSelection[intPicSelected].Image = cLibBattle.getTerrainImage((classBattle.enuTerrainTypes)intPicSelected, classBattle.enuTerrainImageSetting.shaded);
                picSelection[intPicSelected].SizeMode = PictureBoxSizeMode.StretchImage;
                picSelection[intPicSelected].Width = picSelection[intPicSelected].Height = pnlBackOfSelectedPic.Width -10;
                picSelection[intPicSelected].Left = 10 + intPicSelected * (5 + picSelection[intPicSelected].Width);
                picSelection[intPicSelected].Top =  lblMouseInfo.Top + lblMouseInfo.Height + 5;
                picSelection[intPicSelected].MouseEnter += new EventHandler(picTerrainType_MouseEnter);
                picSelection[intPicSelected].MouseLeave += new EventHandler(picTerrainType_MouseLeave);
                picSelection[intPicSelected].MouseClick += new MouseEventHandler(picTerrainType_MouseClick);
                
                Controls.Add(picSelection[intPicSelected]);
                picSelection[intPicSelected].Visible = true;
            }
            picSelection[0].Image = callingForm.cLibBattle.getTerrainImage(picSelection[0].myTerrainType, classBattle.enuTerrainImageSetting.normal);
            SelectedNewTerrainType = picSelection[0].myTerrainType;
            setPnlBackSelectedType();
            
            grbDrawingStyle.Text = "Drawing Style";

            rdbDrawingStyleSingleCell.Text = "Single Cell";
            rdbDrawingStyleSingleCell.AutoSize = true;
            grbDrawingStyle.Controls.Add(rdbDrawingStyleSingleCell);
            rdbDrawingStyleSingleCell.Top = 15; rdbDrawingStyleSingleCell.Left = 5;
            rdbDrawingStyleSingleCell.Visible = true;
            rdbDrawingStyleSingleCell.CheckedChanged += new EventHandler(rdbDrawingStyleSingleCell_CheckedChanged);

            rdbDrawingStyleBrush.Text = "Brush";
            rdbDrawingStyleBrush.AutoSize = true;
            grbDrawingStyle.Controls.Add(rdbDrawingStyleBrush);
            rdbDrawingStyleBrush.Top = rdbDrawingStyleSingleCell.Top + rdbDrawingStyleSingleCell.Height + 5; rdbDrawingStyleBrush.Left = 5;
            rdbDrawingStyleBrush.Visible = true;
            rdbDrawingStyleBrush.CheckedChanged += new EventHandler(rdbDrawingStyleBrush_CheckedChanged);

            rdbDrawingStyleFloodFill.Text = "FloodFill";
            rdbDrawingStyleFloodFill.AutoSize = true;
            grbDrawingStyle.Controls.Add(rdbDrawingStyleFloodFill);
            rdbDrawingStyleFloodFill.Top = rdbDrawingStyleBrush.Top + rdbDrawingStyleBrush.Height + 5; rdbDrawingStyleFloodFill.Left = 5;
            rdbDrawingStyleFloodFill.Visible = true;
            rdbDrawingStyleFloodFill.CheckedChanged += new EventHandler(rdbDrawingStyleFloodFill_CheckedChanged);

            rdbDrawingStyleSingleCell.Checked = true;
            callingForm.DrawingStyle = classMapEditor.enuDrawingStyle.singleCell;
            grbDrawingStyle.Left = 5;
            grbDrawingStyle.Top = picSelection[0].Top + picSelection[0].Height + 5;
            grbDrawingStyle.Height = 95; grbDrawingStyle.Width = 100;
            Controls.Add(grbDrawingStyle);
            grbDrawingStyle.Visible = true;

            classBattle.udtCartesian udrCenter = new classBattle.udtCartesian();
            grbRedInvasionDirection.Text = "Red locs";
            grbRedInvasionDirection.BackColor = Color.White;
            grbRedInvasionDirection.Width = 80;
            grbRedInvasionDirection.Height = grbRedInvasionDirection.Width + 15;
            udrCenter.x = grbRedInvasionDirection.Width / 2;
            udrCenter.y = udrCenter.x + 15;
            double dblRadius = udrCenter.x * 0.7;
            for (classBattle.enuInitialUnitLocDirIndices dirCounter = 0; dirCounter < classBattle.enuInitialUnitLocDirIndices._num_RedInitialLocIndices; dirCounter++)
            {
                classDirLabel dirLabel = new classDirLabel();
                grbRedInvasionDirection.Controls.Add(dirLabel);
                dirLabel.Visible = true;
                dirLabel.AutoSize = true;
                dirLabel.myDir = dirCounter;
                dirLabel.Text = dirCounter.ToString().Replace("Red_", "");
                double dblAngle =  (double)dirCounter / 8.0 * Math.PI * 2.0;
                classBattle.udtCartesian udrAbsLoc = new classBattle.udtCartesian();

                dirLabel.BackColor = Color.Red;
                udrAbsLoc.x = (int)(dblRadius * Math.Sin(dblAngle));
                udrAbsLoc.y = -(int)(dblRadius * Math.Cos(dblAngle));
                dirLabel.Top = (int)(udrCenter.y + udrAbsLoc.y - (double)dirLabel.Height /2.0);
                dirLabel.Left = (int)(udrCenter.x + udrAbsLoc.x - (double)dirLabel.Width/2.0);
                dirLabel.Click += new EventHandler(dirRedInvasionDirectionLabel_Click);
                dirLabel.MouseEnter += new EventHandler(dirRedInvasionDirectionLabel_MouseEnter);
                dirLabel.MouseLeave += new EventHandler(dirRedInvasionDirectionLabel_MouseLeave);
                lblRedInvasionDirLabels[(int)dirCounter] = dirLabel;
            }
            Controls.Add(grbRedInvasionDirection);
            grbRedInvasionDirection.Left = grbDrawingStyle.Left;
            grbRedInvasionDirection.Top = grbDrawingStyle.Top + grbDrawingStyle.Height + 5;

            grbRedInvasionDirection.Click += new EventHandler(grbRedInvasionDirection_Click);

            lblBlueDefenseLaunch.Text = "Defense Launch";
            lblBlueDefenseLaunch.Width = grbRedInvasionDirection.Width;
            lblBlueDefenseLaunch.Height = grbRedInvasionDirection.Height;
            lblBlueDefenseLaunch.Left = grbRedInvasionDirection.Left + grbRedInvasionDirection.Width + 5;
            lblBlueDefenseLaunch.Top = grbRedInvasionDirection.Top;
            lblBlueDefenseLaunch.BackColor = Color.White;
            Controls.Add(lblBlueDefenseLaunch);
            lblBlueDefenseLaunch.Visible = true;

            lblBlueDefenseLaunch.Click += new EventHandler(lblBlueDefenseLaunch_Click);

            Width = 300;
            Height = 400;
            Visible = true;

            tmrRedLocReset.Tick += new EventHandler(tmrRedLocReset_Tick);
            tmrRedLocReset.Interval = 500;

            nudHeight.ValueChanged += new EventHandler(nudHeight_ValueChanged);
            nudWidth.ValueChanged += new EventHandler(nudWidth_ValueChanged);
        }

       

        void blink()
        {
            intBlinkRedLocResetCountdown = intBlindRedLocResetCountdown_max;
            tmrRedLocReset.Enabled = true;
        }

        void tmrRedLocReset_Tick(object sender, EventArgs e)
        {
            intBlinkRedLocResetCountdown--;
            if (intBlinkRedLocResetCountdown <= 0)
            {
                grbRedInvasionDirection.BackColor = Color.White;
                tmrRedLocReset.Enabled = false;
            }
            else
                if (grbRedInvasionDirection.BackColor == Color.White)
                    grbRedInvasionDirection.BackColor = Color.Red;
                else
                    grbRedInvasionDirection.BackColor = Color.White;
        }

        void setEnabledObjects()
        {
            bool bolPicEnabled = false;
            switch (callingForm.mode)
            {
                case classMapEditor.enuModes.BlueLaunchSet:
                    bolPicEnabled = grbRedInvasionDirection.Enabled = grbDrawingStyle.Enabled = nudHeight.Enabled = nudWidth.Enabled = false;
                    lblBlueDefenseLaunch.Enabled = true;
                    break;

                case classMapEditor.enuModes.RedLaunchSet:
                    bolPicEnabled = lblBlueDefenseLaunch.Enabled =  grbDrawingStyle.Enabled = nudHeight.Enabled = nudWidth.Enabled = false;
                    grbRedInvasionDirection.Enabled = true;
                    break;

                case classMapEditor.enuModes.Drawing:
                    bolPicEnabled = grbRedInvasionDirection.Enabled = lblBlueDefenseLaunch.Enabled = grbDrawingStyle.Enabled = nudHeight.Enabled = nudWidth.Enabled = true;
                    break;
            }

            for (int intPicCounter = 0; intPicCounter < picSelection.Length; intPicCounter++)
                picSelection[intPicCounter].Enabled = bolPicEnabled;
        }

        void grbRedInvasionDirection_Click(object sender, EventArgs e)
        {           
            GroupBox thisGrRedInvasionDir = (GroupBox)sender;
            intCurrentRedLaunchLabelCounter = 0;
            if (callingForm.mode == classMapEditor.enuModes.RedLaunchSet)
            {
                callingForm.mode = classMapEditor.enuModes.Drawing;
                callingForm.eraseRedLaunchLabels();
            }
            else
            {
                callingForm.mode = classMapEditor.enuModes.RedLaunchSet;
                callingForm.displayRedLaunchLabels();
            }
            thisGrRedInvasionDir.BackColor = (callingForm.mode == classMapEditor.enuModes.RedLaunchSet ? Color.Red : Color.White);

            setEnabledObjects();
        }

        void lblBlueDefenseLaunch_Click(object sender, EventArgs e)
        {
            Label  thisBlueDefenseLabel = (Label)sender;
            intCurrentBlueLaunchLabelCounter = 0;
            if (callingForm.mode == classMapEditor.enuModes.BlueLaunchSet)
            {
                callingForm.mode = classMapEditor.enuModes.Drawing;
                callingForm.eraseBlueLaunchLabels();
            }
            else
            {
                callingForm.mode = classMapEditor.enuModes.BlueLaunchSet;
                callingForm.displayBlueLaunchLabels();
            }
            thisBlueDefenseLabel.BackColor = (callingForm.mode == classMapEditor.enuModes.BlueLaunchSet ? Color.Blue : Color.White);

            setEnabledObjects();
        }

        void dirRedInvasionDirectionLabel_MouseLeave(object sender, EventArgs e)
        {
            if (callingForm.mode != classMapEditor.enuModes.RedLaunchSet)
                return;
            classDirLabel thisDirLabel = (classDirLabel)sender;
            if (thisDirLabel.myDir == (classBattle.enuInitialUnitLocDirIndices)callingForm.intRedLaunchDirIndex)
            {
                thisDirLabel.BackColor = Color.Black;
                thisDirLabel.ForeColor = Color.Red;
            }
            else
            {
                thisDirLabel.BackColor = Color.Red;
                thisDirLabel.ForeColor = Color.Black;
            }
        }

        void dirRedInvasionDirectionLabel_MouseEnter(object sender, EventArgs e)
        {
            if (callingForm.mode != classMapEditor.enuModes.RedLaunchSet)
                return;
            classDirLabel thisDirLabel = (classDirLabel)sender;

            thisDirLabel.BackColor = Color.Black;
            thisDirLabel.ForeColor = Color.Purple;
        }

        void dirRedInvasionDirectionLabel_Click(object sender, EventArgs e)
        {
            if (callingForm.mode != classMapEditor.enuModes.RedLaunchSet)
                return;
            lblRedInvasionDirLabels[callingForm.intRedLaunchDirIndex].BackColor = Color.Red;
            lblRedInvasionDirLabels[callingForm.intRedLaunchDirIndex].ForeColor = Color.Black;
            classDirLabel thisDirLabel = (classDirLabel)sender;
            callingForm.eraseRedLaunchLabels();
            intCurrentRedLaunchLabelCounter = 0;
            callingForm.intRedLaunchDirIndex = (int)thisDirLabel.myDir;
            callingForm.displayRedLaunchLabels();
        }

        void rdbDrawingStyleFloodFill_CheckedChanged(object sender, EventArgs e) 
        {
            if (rdbDrawingStyleFloodFill.Checked)
            {
                callingForm.DrawingStyle = classMapEditor.enuDrawingStyle.floodfill;
                callingForm.Cursor = callingForm.getTerrainTypeCursor(SelectedNewTerrainType);
                callingForm.blinkCursor();
            }
        }

        void rdbDrawingStyleBrush_CheckedChanged(object sender, EventArgs e)
        {
            if (rdbDrawingStyleBrush.Checked)
            {
                callingForm.DrawingStyle = classMapEditor.enuDrawingStyle.brush;
                callingForm.bolBlinkCursor  = false;
                callingForm.Cursor = Cursors.No;
            }
        }
        void rdbDrawingStyleSingleCell_CheckedChanged(object sender, EventArgs e) 
        {
            if (rdbDrawingStyleSingleCell.Checked)
            {
                callingForm.DrawingStyle = classMapEditor.enuDrawingStyle.singleCell;
                callingForm.Cursor = callingForm.getTerrainTypeCursor(SelectedNewTerrainType);
                callingForm.bolBlinkCursor = false;
            }
        }


        void setPnlBackSelectedType()
        {
            int intSelectedPic = (int)SelectedNewTerrainType;
            pnlBackOfSelectedPic.Left = picSelection[intSelectedPic].Left - 5;
            pnlBackOfSelectedPic.Top = picSelection[intSelectedPic].Top - 5;
            pnlBackOfSelectedPic.SendToBack();
        }

        void picTerrainType_MouseClick(object sender, MouseEventArgs e)
        {
            classPicSelection thisPic = (classPicSelection)sender;
            picSelection[(int)SelectedNewTerrainType].Image = callingForm.cLibBattle.getTerrainImage(picSelection[(int)SelectedNewTerrainType].myTerrainType, classBattle.enuTerrainImageSetting.shaded);
            SelectedNewTerrainType = thisPic.myTerrainType;
            callingForm.bolBlinkCursor = false;
            switch (callingForm.mode)
            {
                case classMapEditor.enuModes.Drawing:
                    switch (callingForm.DrawingStyle)
                    {
                        case classMapEditor.enuDrawingStyle.brush:
                            callingForm.Cursor = Cursors.No;
                            callingForm.bolToggleBrush = false;
                            break;

                        case classMapEditor.enuDrawingStyle.floodfill:
                            callingForm.Cursor = callingForm.getTerrainTypeCursor(SelectedNewTerrainType);
                            callingForm.blinkCursor();
                            break;

                        case classMapEditor.enuDrawingStyle.singleCell:
                            callingForm.Cursor = callingForm.getTerrainTypeCursor(SelectedNewTerrainType);
                            break;
                    }
                    break;

                default:
                    break;
            }
        }

        void picTerrainType_MouseLeave(object sender, EventArgs e)
        {
            classPicSelection thisPic = (classPicSelection)sender;
            if (thisPic.myTerrainType != SelectedNewTerrainType)
                thisPic.Image = callingForm.cLibBattle.getTerrainImage(thisPic.myTerrainType, classBattle.enuTerrainImageSetting.shaded);
        }

        void picTerrainType_MouseEnter(object sender, EventArgs e)
        {
            classPicSelection thisPic = (classPicSelection)sender;
            thisPic.Image = callingForm.cLibBattle.getTerrainImage(thisPic.myTerrainType, classBattle.enuTerrainImageSetting.normal);
        }

        void nudWidth_ValueChanged(object sender, EventArgs e)
        {
            callingForm.MapSize.x = (int)nudWidth.Value;
            callingForm.resizeMap();
            blink();
        }

        void nudHeight_ValueChanged(object sender, EventArgs e)
        {
            callingForm.MapSize.y = (int)nudHeight.Value;
            callingForm.resizeMap();
            blink();
        }
    }

    public class classFloodFillElement
    {
        public classFloodFillElement next;
        public classFloodFillElement previous;
        public int intStepsFromStart;
        public classBattle.udtCartesian pos;
        public classBattleUnit unit;
        public bool flag;

        public classFloodFillElement(int intStepsFromStart_local,
                                         classBattle.udtCartesian pos_local)
        {
            pos = pos_local;
            intStepsFromStart = intStepsFromStart_local;
            next = null;
            previous = null;
        }
    }

    public class classDirLabel : Label
    {
        public classBattle.enuInitialUnitLocDirIndices myDir;
        public classDirLabel()
        {
            AutoSize = true;
        }
    }

    public class classInitLaunchDisplayLabel : Label
    {
        public Image oldImage;
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO unemployable
Canada Canada
Christ Kennedy grew up in the suburbs of Montreal and is a bilingual Quebecois with a bachelor’s degree in computer engineering from McGill University. He is unemployable and currently living in Moncton, N.B. writing his next novel.

Comments and Discussions