using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;
using the_Game_of_Clue_C__2022;
using PicTray;
using the_Game_of_Clue_C__2022.Properties;
using SpriteEditor_2017;
using Wordinator;

/// todo
/// - intro animation
namespace Clue_CS2022
{
	public partial class formClue_2022 : Form
	{

		public static classEventController cEC = new classEventController();
        #region "constants"
        public const double dblTwoPi = Math.PI * 2.0;
		#endregion

		#region "debug variables"
		public string strDebugFilename;
		
		/// <summary>
		/// when true : load sprites from c:\sprites\ 
		/// when false : search for sprite files by going to parent until(but not including) root of drive starting for current-directory
		/// </summary>
		public bool bolDebug = false; 

		#endregion

		#region "objects"
		public classMath cLibMath = new classMath();
		public PictureBox picBoard = new PictureBox();
		Button[] btnPlayerResponse = new Button[3];
		public ProgressBar proBar = new ProgressBar();

		MenuStrip mnu = new MenuStrip();

		public classButton[] cButtons;
				
		public Size sz;
		public Label lblSizer = new Label();

		public classPicTray_V2 cLibPicTraySuspects = new classPicTray_V2();
		public classPicTray_V2 cLibPicTrayWeapons = new classPicTray_V2();
		public classPicTray_V2 cLibPicTrayRooms = new classPicTray_V2();

		//public System.Windows.Forms.Timer tmrDelay = new System.Windows.Forms.Timer();
		public classEventController.classEventTicket cEventTicket_Delay = null;
		//public System.Windows.Forms.Timer tmrAutoProceed = new System.Windows.Forms.Timer();
		public classEventController.classEventTicket cEventTicket_AutoProceed = null;
		//public System.Windows.Forms.Timer tmrNextPlayer = new System.Windows.Forms.Timer();
		public classEventController.classEventTicket cEventTicket_NextPLayer = null;
		//System.Windows.Forms.Timer tmrInit = new System.Windows.Forms.Timer();
		public classEventController.classEventTicket cEventTicket_Init = null;

        public Random rnd = new Random();
		Label lblInitializing = new Label();
		#endregion

		#region "Variables"
		public Bitmap bmpBoard, bmpSuggestionBoard, bmpGameBoard, bmpDealAnimationBoard, bmpDealAnimationBoard_Base;
		//Bitmap bmpBaize = Clue_CS2022.Properties.Resources.baize;
		Bitmap bmpBaize = Resources.baize;
		Bitmap bmpSuggestionBubble = Resources.SuggestionBubble;
		Bitmap bmpCardBack = Resources.cardback;
		Bitmap bmpBannerNoCard = Resources.NoCardsToShow;
		Bitmap bmpBannerCardToShow = Resources.CanShowACard;

		formInstructions frmInstructions;

		Bitmap bmpResponseBubble;
		public Bitmap bmpNotebook;

		public Bitmap[] bmpPieces = new Bitmap[(int)enuSuspects._numSuspects];
		public Bitmap[] bmpSuspects = new Bitmap[(int)enuSuspects._numSuspects];
		public Bitmap[] bmpWeapons_PicTray = new Bitmap[(int)enuWeapons._numWeapons];
		public Bitmap[] bmpWeapons_Board = new Bitmap[(int)enuWeapons._numWeapons];
		public Bitmap[] bmpRooms = new Bitmap[(int)enuRooms._numRooms];
				
		public classCard cCardUnknown;
		public classCard[] cCards;

		public classSuspect[] cSuspects;
		public classRoom[] cRooms;
		public classWeapon[] cWeapons;

		public Color[] clrSuspects;

		public enuCards[] eValidPlayerResponseCards;

		Rectangle recBannerButton;
		
		classNote[,] cPlayerNotes = new classNote[(int)enuSuspects._numSuspects, (int)enuCards._numCards];
		classNote cMouseOverNote;
		
		enuMode _eMode = enuMode.chooseCharacter;

		classMoveAnimationInfo cMoveAnimationInfo = new classMoveAnimationInfo();
		string strCardsDealt;
		
		Point[] ptAnimationTypeStackPos;
		Point ptMouseTile;
		Point ptMousePos;
		public Point ptBoardTL = new Point(26, 7);
		Point[] ptSetAI;
		Point[] ptRoomCenters;
		Point ptSuggestionBubbleTL, ptResponseBubbleTL;

		bool _bolDisableMouseClickBoard = false;
		bool bolHideOptions = false;
		public bool bolAutoProceed = false;

		public int intSuspectTurn;
		public int intNumTurns = 0;
		int intBaseAutoProceedInterval = 3500;

		double dblSpeedFactor = 1.0;
				
		public classRotatedImage[] cBmpDie;
		public classRollDieInfo cRollDieInfo = new classRollDieInfo();
		public classSuggestionAnimation cSuggestionAnimation = new classSuggestionAnimation();
		public classAnimationSummons cAnimationSummonWeapon = new classAnimationSummons();
		public classAnimationSummons cAnimationSummonSuspect = new classAnimationSummons();
		public classAnimationSecretPassge cAnimationSecretPassage = new classAnimationSecretPassge();
		public classIntro_Animation cAnimationIntro = new classIntro_Animation();
		public classMurder cMurder = new classMurder ();
		public classMurder cSuggestion = new classMurder ();

		public classAnimateDealCards cAnimateDealCards = new classAnimateDealCards();
		public classAccusation_Animation cAnimationAccusation = new classAccusation_Animation();

		/// flood-lights accusation animation variables
		Bitmap bmpFloodlights;
		Color clrFloordlights = Color.Red;
		Color clrField = Color.Blue;
		Brush br;
		bool bolInit = false;

		#endregion
		
		public formClue_2022()
		{
			InitializeComponent();

			string strDevelopperWorkingDir = "C:\\C Sharp\\Projects - Games\\the Game of Clue C# 2022\\the Game of Clue C# 2022\\bin\\Debug";
			string strCurrentDirectory = System.IO.Directory.GetCurrentDirectory();
            bolDebug = strDevelopperWorkingDir == strCurrentDirectory;


			bmpNotebook = new Bitmap(Resources.notebook);
			bmpBoard = new Bitmap(Resources.ClueBoardMarble);
			sz = new Size(Resources.ClueFloor.Width, Resources.ClueFloor.Height);

			picBoard.Image = bmpBoard;
			picBoard.Refresh();
			PlaceControls();
			proBar.Visible = true; proBar.Maximum = 210;

			cEventTicket_Init = cEC.Ticket("Init", 5, tmrInit_Tick);
			cEventTicket_Init.AutoRepeat = true;
			//tmrInit.Interval = 5;
			//tmrInit.Tick += new EventHandler(tmrInit_Tick);
			//tmrInit.Enabled = true;
		}

		public bool bolDisableMouseClickBoard
		{
			get { return _bolDisableMouseClickBoard; }
			set 
			{
				_bolDisableMouseClickBoard = value;
			}
		}

		public void advanceProBar()
		{
			proBar.Value = (proBar.Value + 1) % proBar.Maximum;
		}

		void tmrInit_Tick(object sender, EventArgs e)
		{
			//tmrInit.Enabled = false;
			cEventTicket_Init.AutoRepeat = false;
			Location = new Point(0, 0);
			Size = Screen.PrimaryScreen.WorkingArea.Size;
			Refresh();

			initIntroMice(); advanceProBar();
			initMenu(); advanceProBar();
			initDieImages(); advanceProBar();
			initPieces(); advanceProBar();
			initSuspects(); advanceProBar();
			initWeapons(); advanceProBar();
			initColors(); advanceProBar();
			initRooms(); advanceProBar();
			resetPlayerNotes(); advanceProBar();
			initSetAIGroupBox(); advanceProBar();
			initCards(); advanceProBar();
			initAnimationIntroBehindTheLenseImages();
			eMode = (enuMode)0;
			initResponseBubble(); advanceProBar();

			bmpSuggestionBubble.MakeTransparent();
			bmpBannerCardToShow.MakeTransparent();
			bmpBannerNoCard.MakeTransparent();

			cButtons = new classButton[(int)enuButtons._numButtons];
			if (cEventTicket_NextPLayer == null)
			{
				cEventTicket_NextPLayer = cEC.Ticket("NextPlayer", 5, tmrNextPlayer_Tick);
				cEventTicket_NextPLayer.quit();
			}
			//tmrNextPlayer.Interval = 5;
			//tmrNextPlayer.Tick += new EventHandler(tmrNextPlayer_Tick);
			advanceProBar();
			ptAnimationTypeStackPos = new Point[3];
			ptAnimationTypeStackPos[(int)enuCardType.room] = new Point((int)(bmpBoard.Width * .1), (int)(bmpBoard.Height * .25));
			ptAnimationTypeStackPos[(int)enuCardType.Suspect] = new Point((int)(bmpBoard.Width * .1), (int)(bmpBoard.Height * .5));
			ptAnimationTypeStackPos[(int)enuCardType.weapon] = new Point((int)(bmpBoard.Width * .1), (int)(bmpBoard.Height * .75));


			//tmrDelay.Tick += new EventHandler(tmrDelay_Tick);
			if (cEventTicket_Delay == null)
			{
				cEventTicket_Delay = cEC.Ticket("Delay", 100, tmrDelay_Tick);
			}
			cEventTicket_Delay.quit();

			strDebugFilename = System.IO.Directory.GetCurrentDirectory() + "\\AI test results.txt";

			FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
			Size = Screen.PrimaryScreen.WorkingArea.Size;
			Activated += new EventHandler(formClue_Activated);
			advanceProBar();
			resetPlayerNotes(); resetSuspects(enuSuspects.MissScarlet);

			advanceProBar();
			#region "init tray : cLibPicTrayRooms"
			{
				picBoard.Controls.Add(cLibPicTrayRooms);
				cLibPicTrayRooms.BackColor = Color.Transparent;

				cLibPicTrayRooms.tmrRotate.Tick += new EventHandler(cLibPicTraySuspectTmrRotate_Tick);

				for (enuRooms eRoomCounter = (enuRooms)0; eRoomCounter < enuRooms._numRooms; eRoomCounter++)
					cLibPicTrayRooms.addImageToTray(new Bitmap(cCards[(int)classCard.getECardFromERoom(eRoomCounter)].cBmp.getImage(0)), eRoomCounter.ToString());
				cLibPicTrayRooms.Visible = false;
			}
			#endregion
			advanceProBar();
			#region "init tray : cLibPicTraySuspects"
			{
				picBoard.Controls.Add(cLibPicTraySuspects);
				cLibPicTraySuspects.Options.BackColor = Color.Transparent;
				cLibPicTraySuspects.RoundImages = true;

				cLibPicTraySuspects.tmrRotate.Tick += new EventHandler(cLibPicTraySuspectTmrRotate_Tick);

				for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
					cLibPicTraySuspects.addImageToTray(bmpSuspects[(int)eSuspectCounter], eSuspectCounter.ToString());
				cLibPicTraySuspects.Visible = false;
			}
			#endregion
			advanceProBar();
			#region "init tray : cLibPicTrayWeapons"
			{
				picBoard.Controls.Add(cLibPicTrayWeapons);
				cLibPicTrayWeapons.Options.BackColor = Color.Transparent;
				cLibPicTrayWeapons.Location = new Point(355, 0);
				cLibPicTrayWeapons.RoundImages = true;

				cLibPicTrayWeapons.tmrRotate.Tick += new EventHandler(cLibPicTrayWeaponTmrRotate_Tick);

				for (enuWeapons eSuspectCounter = (enuWeapons)0; eSuspectCounter < enuWeapons._numWeapons; eSuspectCounter++)
					cLibPicTrayWeapons.addImageToTray(new Bitmap(bmpWeapons_PicTray[(int)eSuspectCounter]), eSuspectCounter.ToString());
				cLibPicTrayWeapons.Visible = false;
			}
			#endregion

			// init accusation animation variables
			bmpFloodlights = new Bitmap(bmpBoard.Width, bmpBoard.Height);
			using (Graphics g = Graphics.FromImage(bmpFloodlights))
				g.FillRectangle(new SolidBrush(clrField), new Rectangle(0, 0, bmpBoard.Width, bmpBoard.Height));
			bmpFloodlights.MakeTransparent(clrFloordlights);
			br = new SolidBrush(clrFloordlights);
			advanceProBar();
			commitMurder(); dealCards();
			eMode = enuMode.idle; eDealMode = enuDealCardsMode.SortCardsIntotypes;

			lblInitializing.Visible =
				proBar.Visible = false;
			bolInit = true;
			eMode = enuMode.animateIntroduction;
		}

		bool bolActivated = false;
		void formClue_Activated(object sender, EventArgs e)
		{
			if (bolActivated) return;
			Location = new Point(0, 0);


			picDieBox.Image = (Bitmap)new Bitmap(Resources.baize);//  global::Resources.baize;
			picNotebook.Image = (Bitmap)new Bitmap(Resources.notebook);//((System.Drawing.Image)(resources.GetObject("picNotebook.Image")));

            bolActivated = true;
		}

		#region "timers"
		public void setDelayTimer(int intMilliseconds)
		{
			int intNewInterval = (int)(intMilliseconds * dblSpeedFactor);
			if (intNewInterval < 1)
				intNewInterval = 1;
			if (cEventTicket_Delay == null)
			{
				return;
			}

			cEventTicket_Delay.Milliseconds_ConditionTestDelay = intNewInterval;
			cEventTicket_Delay.Reschedule();
			//tmrDelay.Interval = intNewInterval;
			//tmrDelay.Enabled = false;
			//tmrDelay.Enabled = true;
		}

		void tmrAutoProceed_Tick(object sender, EventArgs e)
		{
			autoProceedEnabled = false;

			switch (eMode)
			{
				case enuMode.playerChoosesCardToShow:
					if (eValidPlayerResponseCards.Length == 1)
						btnPlayerResponse_Click((object)btnPlayerResponse[0], new MouseEventArgs(System.Windows.Forms.MouseButtons.Left, 1, 1, 1, 1));
					else
						PlayerChoosesCardToShowBannerClick();
					break;

				default:
					btnRespondSuggestion_OK_click();
					break;
			}
		}

		void tmrDelay_Tick(object sender, EventArgs e)
		{
			//tmrDelay.Enabled = false;
			cEventTicket_Delay.AutoRepeat = false;
			switch (eMode)
			{	
				case enuMode.warnPlayerNextTurn:
					eMode = enuMode.beginTurn;
					break;

				case enuMode.animateMove:
					moveStep();
					break;

				case enuMode.showAllowableMoves:
					cSuspects[intSuspectTurn].endShowAllowableMoves();
					break;

				case enuMode.rollDie_animate:
					rollDie_animate();
					break;

				case enuMode.animateIntroduction:
					animateIntroduction();
					break;

				case enuMode.animateSummonSuspect:
					animateSummonSuspect();
					break;

				case enuMode.animateSummonWeapon:
					animateSummonWeapon();
					break;

				case enuMode.Accuse_Animation:
				case enuMode.Accuse:
					animateAccusation();
					break;

				case enuMode.animateSecretPassage:
					AnimateSecretPassage();
					break;

				case enuMode.gameOver:
					eMode = enuMode.animateIntroduction;
					break;

				case enuMode.idle:
				case enuMode.dealCards:
					animateDealCards();
					break;
			}


		}
		void cLibPicTraySuspectTmrRotate_Tick(object sender, EventArgs e)
		{
			switch (eMode)
			{
				case enuMode.Accuse:
					setAccusation();
					break;

				case enuMode.Suggest:
					setSuggestion();
					break;

				case enuMode.chooseCharacter:
					setBtnChooseSuspectColorAndText();
					break;
			}
		}

		void cLibPicTrayWeaponTmrRotate_Tick(object sender, EventArgs e)
		{
			switch (eMode)
			{
				case enuMode.Accuse:
					setAccusation();
					break;

				case enuMode.Suggest:
					setSuggestion();
					break;
			}
		}

		#endregion		

		#region "animate intro"
		enuIntroAnimationMode eIntroMode
		{
			get { return cAnimationIntro.eMode; }
			set
			{
				cAnimationIntro.eMode = value;
				cAnimationIntro.bolInit = false;
			}
		}

		void initAnimationIntroBehindTheLenseImages()
		{
			Bitmap bmpMegaBoard = new Bitmap(Resources.Board_Under_Lense);
			cAnimationIntro.cMagnifyingGlass = new classIntro_MagnifyingGlass();

            cAnimationIntro.cMagnifyingGlass.bmpLense = new Bitmap(Resources.magnifying_glass);
			cAnimationIntro.cMagnifyingGlass.bmpHandle = new Bitmap(Resources.magnifying_handle);
			cAnimationIntro.cMagnifyingGlass.bmpHandle.MakeTransparent(cAnimationIntro.cMagnifyingGlass.bmpHandle.GetPixel(0, 0));


			int intMaxFitHorizontally = (int)(Math.Floor((double)bmpMegaBoard.Width / (2.0 * (double)Resources.magnifying_glass.Width)));
			int intMaxFitVertically = (int)(Math.Floor((double)bmpMegaBoard.Height / (2.0 * (double)Resources.magnifying_glass.Height)));
			cAnimationIntro.cBoardUnderLense = new classIntro_Animation_Board();

            cAnimationIntro.cBoardUnderLense.szArray = new System.Drawing.Size(2 * intMaxFitHorizontally - 1,
																			 2 * intMaxFitVertically - 1);
			cAnimationIntro.cBoardUnderLense.cArrayParcels =new classIntro_Animation_BoardParcel[cAnimationIntro.cBoardUnderLense.szArray.Width, cAnimationIntro.cBoardUnderLense.szArray.Height];
			cAnimationIntro.cBoardUnderLense.szParcels  = new Size(bmpMegaBoard.Width / intMaxFitHorizontally, bmpMegaBoard.Height / intMaxFitVertically);
			Rectangle recDest = new Rectangle(0, 0, cAnimationIntro.cBoardUnderLense.szParcels.Width, cAnimationIntro.cBoardUnderLense.szParcels.Height);

			for (int intX = 0; intX < cAnimationIntro.cBoardUnderLense.szArray.Width; intX++)
			{
				for (int intY = 0; intY < cAnimationIntro.cBoardUnderLense.szArray.Height; intY++)
				{
					cAnimationIntro.cBoardUnderLense.cArrayParcels[intX, intY] = new classIntro_Animation_BoardParcel();

                    cAnimationIntro.cBoardUnderLense.cArrayParcels[intX, intY].bmp = new Bitmap(cAnimationIntro.cBoardUnderLense.szParcels.Width, cAnimationIntro.cBoardUnderLense.szParcels.Height);
					cAnimationIntro.cBoardUnderLense.cArrayParcels[intX, intY].rec = new Rectangle(intX * cAnimationIntro.cBoardUnderLense.szParcels.Width / 2, intY * cAnimationIntro.cBoardUnderLense.szParcels.Height / 2, cAnimationIntro.cBoardUnderLense.szParcels.Width, cAnimationIntro.cBoardUnderLense.szParcels.Height);
					using (Graphics g = Graphics.FromImage(cAnimationIntro.cBoardUnderLense.cArrayParcels[intX, intY].bmp))
						g.DrawImage(bmpMegaBoard, recDest, cAnimationIntro.cBoardUnderLense.cArrayParcels[intX, intY].rec, GraphicsUnit.Pixel);
					advanceProBar();
				}
			}
		}

		void initAnimateIntroduction()
		{
			//bolGameOver = false;
			Bitmap bmpTemp = new Bitmap(bmpBoard.Width + bmpNotebook.Width +5, bmpBoard.Height);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				g.DrawImage(bmpBoard, new Point(0, 0));
				g.DrawImage(bmpNotebook, new Point(bmpBoard.Width+5, 0));
				Bitmap bmpLogo = new Bitmap(Resources.clue_logo);
				bmpLogo.MakeTransparent();
				g.DrawImage(bmpLogo, (bmpTemp.Width - bmpLogo.Width) / 2, (bmpTemp.Height - bmpLogo.Height) / 2);
			}
			picBoard.Size = bmpTemp.Size;
			picBoard.Image = bmpTemp;
			picBoard.BringToFront();
			cAnimationIntro.bmpBoard = bmpTemp;
			
			cAnimationIntro.cMagnifyingGlass.ptCenterLense = new Point(cAnimationIntro.cMagnifyingGlass.bmpLense.Width / 2, cAnimationIntro.cMagnifyingGlass.bmpLense.Height / 2);
			cAnimationIntro.cMagnifyingGlass.clrBackground = cAnimationIntro.cMagnifyingGlass.bmpLense.GetPixel(0, 0);
			cAnimationIntro.cMagnifyingGlass.clrLense = cAnimationIntro.cMagnifyingGlass.bmpLense.GetPixel(cAnimationIntro.cMagnifyingGlass.ptCenterLense.X, cAnimationIntro.cMagnifyingGlass.ptCenterLense.Y);

			//initialize intro animation sprites
			classSpriteMaker cSpriteMaker = new classSpriteMaker();
			cAnimationIntro.lstSprites = new List<classIntro_Animation_Sprites>();
			string strWaldoSpriteFilename = getSpriteFilename(enuIntroAnimationSprites.waldo.ToString());
			classIntro_Animation_Sprites cAnimationSprite_Waldo = new classIntro_Animation_Sprites();

			cAnimationSprite_Waldo.cSpriteData = new classSpriteData();
            cAnimationSprite_Waldo.cSpriteData.cAnimationData.cSprite =  cSpriteMaker .Load(strWaldoSpriteFilename);
			cAnimationSprite_Waldo.cSpriteData.cAnimationData.cSprite.UseRamCache = true;
            cAnimationSprite_Waldo.udrAniInfo.ptPos = new Point(336, 1784);
            cAnimationIntro.lstSprites.Add(cAnimationSprite_Waldo);

            
			string strBettyBoopSpriteFilename = getSpriteFilename(enuIntroAnimationSprites.BettyBoop.ToString());
			classIntro_Animation_Sprites cAnimation_BettyBoop = new classIntro_Animation_Sprites();
			
            cAnimation_BettyBoop.cSpriteData = new classSpriteData();
            cAnimation_BettyBoop.cSpriteData.cAnimationData.cSprite = cSpriteMaker.Load(strBettyBoopSpriteFilename);
            cAnimation_BettyBoop.cSpriteData.cAnimationData.cSprite.UseRamCache = true;
            cAnimation_BettyBoop.udrAniInfo.ptPos = new Point(420, 708);
			cAnimationIntro.lstSprites.Add(cAnimation_BettyBoop);

			eIntroMode = (enuIntroAnimationMode)0;
			setDelayTimer(10);
		}

		string getSpriteFilename(string strFilename)
		{
			//if (bolDebug)
			//	return "c:\\sprites\\" + strFilename + "\\" + strFilename + ".sp6";

			string strDirectory = System.IO.Directory.GetCurrentDirectory();
			string strFilenameAndDirectory = strDirectory + "\\" + strFilename + ".sp6";
			while (strFilenameAndDirectory.Length > 0 && !System.IO.File.Exists(strFilenameAndDirectory))
			{
				int intIndex = strDirectory.LastIndexOf("\\");
				if (intIndex > 0)
				{
					strDirectory = strDirectory.Substring(0, intIndex);
					strFilenameAndDirectory = strDirectory + "\\" + strFilename + ".sp6";
				}
				else
					strFilenameAndDirectory = "";
			}
			return strFilenameAndDirectory;
		}

		void animateIntroduction()
		{
			if (!cAnimationIntro.bolInit)
			{
				switch (cAnimationIntro.eMode)
				{
					case enuIntroAnimationMode.moveToBawdyMansion:
						cAnimationIntro.cMagnifyingGlass.ptStart = new Point(-550, 50);
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(1092, 60);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 10;
						break;

					case enuIntroAnimationMode.moveToRat:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(1059, 418);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 5;
						break;

					case enuIntroAnimationMode.moveToTheButlerDidIt:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(2720, 244);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 6;
						break;

					case enuIntroAnimationMode.moveToCKLovesTalise:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(2632, 1568);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 6;
						break;

					case enuIntroAnimationMode.moveToSpider:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(1904, 1687);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 3;
						break;

					case enuIntroAnimationMode.moveToCheese:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(2076, 2020);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 3;
						break;

					case enuIntroAnimationMode.moveToCat:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(1100, 2044);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 4;
						break;

					case enuIntroAnimationMode.moveToWaldo:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(336, 1784);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 15;
						break;

					case enuIntroAnimationMode.moveToBettyBoop:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(420, 700);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 15;
						break;

					case enuIntroAnimationMode.moveToWrittenBy:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(884, 952);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 5;
						break;

					case enuIntroAnimationMode.moveToChristKennedy:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(2299, 1265);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 20;
						break;

					case enuIntroAnimationMode.moveToYear:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(289, 1429);
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 4;
						break;

					case enuIntroAnimationMode.moveToEnd:
						cAnimationIntro.cMagnifyingGlass.ptStart = cAnimationIntro.cMagnifyingGlass.ptPos;
						cAnimationIntro.cMagnifyingGlass.ptEnd = new Point(-550, (Resources.Board_Under_Lense.Height) - 50);
						cAnimationIntro.cMagnifyingGlass.intHoverMax = 0;
						cAnimationIntro.cMagnifyingGlass.intHoverStep = 0;
						break;
				}

				cAnimationIntro.cMagnifyingGlass.intStep = 0;
				cAnimationIntro.cMagnifyingGlass.dblTravelAngle = classMath.arcTan(cAnimationIntro.cMagnifyingGlass.ptEnd, cAnimationIntro.cMagnifyingGlass.ptStart);
				cAnimationIntro.cMagnifyingGlass.dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationIntro.cMagnifyingGlass.ptEnd, cAnimationIntro.cMagnifyingGlass.ptStart);
				cAnimationIntro.cMagnifyingGlass.intMaxSteps = (int)(Math.Ceiling(cAnimationIntro.cMagnifyingGlass.dblTravelDistance / 60));
				cAnimationIntro.bolInit = true;
			}

			// move magnifying glass over mega board
			if (cAnimationIntro.cMagnifyingGlass.intStep < cAnimationIntro.cMagnifyingGlass.intMaxSteps)
			{
				cAnimationIntro.cMagnifyingGlass.intStep++;
				double dblPercentDistanceTravelled = ((double)cAnimationIntro.cMagnifyingGlass.intStep / (double)cAnimationIntro.cMagnifyingGlass.intMaxSteps);
				cAnimationIntro.cMagnifyingGlass.ptPos.X = (int)(cAnimationIntro.cMagnifyingGlass.ptStart.X + dblPercentDistanceTravelled * cAnimationIntro.cMagnifyingGlass.dblTravelDistance * Math.Cos(cAnimationIntro.cMagnifyingGlass.dblTravelAngle));
				cAnimationIntro.cMagnifyingGlass.ptPos.Y = (int)(cAnimationIntro.cMagnifyingGlass.ptStart.Y + dblPercentDistanceTravelled * cAnimationIntro.cMagnifyingGlass.dblTravelDistance * Math.Sin(cAnimationIntro.cMagnifyingGlass.dblTravelAngle));
			}
			// create image of lense
			Bitmap bmpTempLense = new Bitmap(cAnimationIntro.cMagnifyingGlass.bmpLense.Width, cAnimationIntro.cMagnifyingGlass.bmpLense.Height);
			Rectangle recSrcMegaParcel;
			Rectangle recDestMegaBoard = new Rectangle(0, 0, bmpTempLense.Width, bmpTempLense.Height);
			Rectangle recSrcMegaBoard = new Rectangle(getMagnifyingLenseTLOnMegaBoard(cAnimationIntro.cMagnifyingGlass.ptPos), bmpTempLense.Size);
			using (Graphics g = Graphics.FromImage(bmpTempLense))
			{
				// copy mega board image onto temp bmp

				Point ptIndex = new Point(cAnimationIntro.cBoardUnderLense.szArray.Width - 1, cAnimationIntro.cBoardUnderLense.szArray.Height - 1);
				while (ptIndex.X > 0 && cAnimationIntro.cBoardUnderLense.cArrayParcels[ptIndex.X, ptIndex.Y].rec.Left > recSrcMegaBoard.Left)
					ptIndex.X--;
				while (ptIndex.Y > 0 && cAnimationIntro.cBoardUnderLense.cArrayParcels[ptIndex.X, ptIndex.Y].rec.Top > recSrcMegaBoard.Top)
					ptIndex.Y--;
				int intTestX  = (cAnimationIntro.cMagnifyingGlass.ptPos.X >0 
									?  
									(int)(Math.Floor((double)cAnimationIntro.cMagnifyingGlass.ptPos.X / ((double)cAnimationIntro.cBoardUnderLense.szParcels.Width / 2.0)))
									:
									0);

				int intTestY = (cAnimationIntro.cMagnifyingGlass.ptPos.Y > 0
									?
									(int)(Math.Floor((double)cAnimationIntro.cMagnifyingGlass.ptPos.Y / ((double)cAnimationIntro.cBoardUnderLense.szParcels.Height / 2.0)))
									:
									0);

				recSrcMegaParcel = new Rectangle(recSrcMegaBoard.Left - cAnimationIntro.cBoardUnderLense.cArrayParcels[ptIndex.X, ptIndex.Y].rec.Left,
														   recSrcMegaBoard.Top - cAnimationIntro.cBoardUnderLense.cArrayParcels[ptIndex.X, ptIndex.Y].rec.Top,
														   recSrcMegaBoard.Width,
														   recSrcMegaBoard.Height);

				g.DrawImage(cAnimationIntro.cBoardUnderLense.cArrayParcels[ptIndex.X, ptIndex.Y].bmp, recDestMegaBoard, recSrcMegaParcel, GraphicsUnit.Pixel);

				Point ptLenseCenter = cAnimationIntro.cMagnifyingGlass.ptPos;
				for (int intSpriteCounter = 0; intSpriteCounter < cAnimationIntro.lstSprites.Count; intSpriteCounter++)
				{
					enuIntroAnimationSprites eSprite = (enuIntroAnimationSprites)intSpriteCounter;
					double dblDistance = classMath.distanceBetweenTwoPoints(ptLenseCenter, cAnimationIntro.lstSprites[intSpriteCounter].udrAniInfo.ptPos);

					if (dblDistance < 200)
					{ // draw this sprite
					
						Point ptSprite = new Point(cAnimationIntro.lstSprites[intSpriteCounter].udrAniInfo.ptPos.X - recSrcMegaBoard.Left,
															   cAnimationIntro.lstSprites[intSpriteCounter].udrAniInfo.ptPos.Y - recSrcMegaBoard.Top);

						classSpriteData cSpriteData = cAnimationIntro.lstSprites[(int)eSprite].cSpriteData;
                        switch (eSprite)
                        {
                            case enuIntroAnimationSprites.BettyBoop:
                                {
									if (cSpriteData.cAnimationData.cAnimation == null)
									{
										cSpriteData.cAnimationData.cAnimation = cAnimationIntro.lstSprites[(int)eSprite].cSpriteData.cAnimationData.cSprite.lstAnimations[(int)enuBettyBoop_Animations.FrontStep_Left];
									}
									else if (cSpriteData.cAnimationData.intFrameIndex >= cSpriteData.cAnimationData.cAnimation.lstFrames.Count)
									{
										Random rnd = new Random();
										int intRnd = ((int)(100000 * rnd.NextDouble())) % 100;
										if (intRnd %2 ==0)
										{
                                            cSpriteData.cAnimationData.cAnimation = cAnimationIntro.lstSprites[(int)eSprite].cSpriteData.cAnimationData.cSprite.lstAnimations[(int)enuBettyBoop_Animations.FrontStep_Left];
                                        }
										else
										{
                                            cSpriteData.cAnimationData.cAnimation = cAnimationIntro.lstSprites[(int)eSprite].cSpriteData.cAnimationData.cSprite.lstAnimations[(int)enuBettyBoop_Animations.FrontStep_Right];
                                        }
									}
                                }
                                break;

                            case enuIntroAnimationSprites.waldo:
                                {
									if (cSpriteData.cAnimationData.cAnimation == null)
                                    cSpriteData.cAnimationData.cAnimation = cAnimationIntro.lstSprites[(int)eSprite].cSpriteData.cAnimationData.cSprite.lstAnimations[0];
                                    else if (cSpriteData.cAnimationData.intFrameIndex >= cSpriteData.cAnimationData.cAnimation.lstFrames.Count)
                                    {
                                        Random rnd = new Random();
                                        int intRnd = ((int)(100000 * rnd.NextDouble())) % 100;
                                        if (intRnd % 2 == 0)
                                        {
                                            cSpriteData.cAnimationData.cAnimation = cAnimationIntro.lstSprites[(int)eSprite].cSpriteData.cAnimationData.cSprite.lstAnimations[(int)enuwaldo_Animations.wave];
                                        }
                                        else
                                        {
                                            cSpriteData.cAnimationData.cAnimation = cAnimationIntro.lstSprites[(int)eSprite].cSpriteData.cAnimationData.cSprite.lstAnimations[(int)enuwaldo_Animations.wriggle_dance];
                                        }
                                    }
                                }
                                break;
                        }
                        
						cSpriteData.cAnimationData.intFrameIndex = (cSpriteData.cAnimationData.intFrameIndex + 1) % cSpriteData.cAnimationData.cAnimation.lstFrames.Count;
						cSpriteData.cAnimationData.dblDrawSizeFactor = 0.5f;

						List<Bitmap> lstImages = cSpriteData.Draw();
						classSprite_Limb cLimb_Torso = (classSprite_Limb)cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.cBT_Limbs.Search("torso");

						if (lstImages.Count > 0)
						{
							classAnimation_Frame cAnimationFrame = cSpriteData.cAnimationData.cAnimation.lstFrames[cSpriteData.cAnimationData.intFrameIndex];
							Bitmap bmpDraw = lstImages[0];
							Point ptDraw = new Point(ptSprite.X + cAnimationFrame.ptTL.X,
													 ptSprite.Y + cAnimationFrame.ptTL.Y);
							g.DrawImage(bmpDraw, ptDraw);
						}
					}
				}


				cAnimationIntro.cMagnifyingGlass.bmpLense.MakeTransparent(cAnimationIntro.cMagnifyingGlass.clrLense);
				g.DrawImage(cAnimationIntro.cMagnifyingGlass.bmpLense, new Point(0, 0));
			}

			// make temp lense background transparent then draw onto regular board
			bmpTempLense.MakeTransparent(cAnimationIntro.cMagnifyingGlass.clrBackground);

			Bitmap bmpNewBoard = new Bitmap(cAnimationIntro.bmpBoard);
			using (Graphics g = Graphics.FromImage(bmpNewBoard))
			{
				Point ptTLLense = getMagnifyingLenseTLOnRegularBoard(cAnimationIntro.cMagnifyingGlass.ptPos);
				g.DrawImage(bmpTempLense, ptTLLense);
				g.DrawImage(cAnimationIntro.cMagnifyingGlass.bmpHandle, new Point(ptTLLense.X - 198, ptTLLense.Y + 229));
			}

			picBoard.Image = bmpNewBoard; picBoard.Refresh();

			if (cAnimationIntro.cMagnifyingGlass.intStep >= cAnimationIntro.cMagnifyingGlass.intMaxSteps)
			{
				if (cAnimationIntro.cMagnifyingGlass.intHoverStep < cAnimationIntro.cMagnifyingGlass.intHoverMax)
				{
					cAnimationIntro.cMagnifyingGlass.intHoverStep++;
				}
				else
					eIntroMode = (enuIntroAnimationMode)(((int)eIntroMode + 1) % (int)enuIntroAnimationMode._numIntroMode);
			}

			setDelayTimer(100);
		}

		Point getMagnifyingLenseTLOnRegularBoard(Point ptLenseCenterOnMegaBoard)
		{
			Point ptLenseCenterOnRegularBoard = new Point(ptLenseCenterOnMegaBoard.X / 3, ptLenseCenterOnMegaBoard.Y / 3);
			return new Point(ptLenseCenterOnRegularBoard.X - cAnimationIntro.cMagnifyingGlass.ptCenterLense.X, ptLenseCenterOnRegularBoard.Y - cAnimationIntro.cMagnifyingGlass.ptCenterLense.Y);
		}

		Point getMagnifyingLenseTLOnMegaBoard(Point ptLenseCenterOnMegaBoard)
		{
			return new Point(ptLenseCenterOnMegaBoard.X - cAnimationIntro.cMagnifyingGlass.ptCenterLense.X, ptLenseCenterOnMegaBoard.Y - cAnimationIntro.cMagnifyingGlass.ptCenterLense.Y);
		}

		#endregion

		#region "animate Deal Cards"
		enuDealCardsMode eDealMode
		{
			get { return cAnimateDealCards._eMode; }
			set
			{
				int intHalfCardWidth = cCards[0].cBmp.getImage(0).Width / 2;
				int intHalfCardHeight = cCards[0].cBmp.getImage(0).Height / 2;
				if (cAnimateDealCards._eMode != value)
				{
					cAnimateDealCards._eMode = value;

					// initialize animation for each mode
					switch (eDealMode)
					{
						case enuDealCardsMode.SortCardsIntotypes:
							cAnimateDealCards.strCards = shuffleCards(false);
							cAnimateDealCards.intAnimationCounter = 0;
							cAnimateDealCards.lstCardsCurrentAnimation = new List<classCard>();

                            cAnimateDealCards.lstCardsCurrentAnimation.Clear();// = new classCard[0];
							setDelayTimer(100);
							break;

						case enuDealCardsMode.gatherTypes:
							cAnimateDealCards.intAnimationCounter = 0;
							break;

						/// shuffle, select & hide weapons
						case enuDealCardsMode.spreadWeaponCardsFaceUp:
							bmpDealAnimationBoard_Base = AnimateDealCards_getBlankDealCardsImage();

							using (Graphics g = Graphics.FromImage(bmpDealAnimationBoard_Base))
							{
								classCard cThisCard = cAnimateDealCards.udrTypeOrder.lstSuspects[cAnimateDealCards.udrTypeOrder.lstSuspects.Count - 1];
								Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - intHalfCardWidth, cThisCard.cAnimationInfo.ptPos.Y - intHalfCardHeight);
								g.DrawImage(cThisCard.cBmp.getImage(0), ptTL);

								cThisCard = cAnimateDealCards.udrTypeOrder.lstRooms[cAnimateDealCards.udrTypeOrder.lstRooms.Count - 1];
								ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - intHalfCardWidth, cThisCard.cAnimationInfo.ptPos.Y - intHalfCardHeight);
								g.DrawImage(cThisCard.cBmp.getImage(0), ptTL);
							}

							cAnimateDealCards.intAnimationCounter = 0;
							break;

						case enuDealCardsMode.flipWeaponcards:
							cAnimateDealCards.bolInit = false;
							cAnimateDealCards.intAnimationCounter = 0;
							break;

						case enuDealCardsMode.shuffleWeaponCards:
							cAnimateDealCards.bolInit = false;
							cAnimateDealCards.intAnimationCounter = 0;
							break;

						case enuDealCardsMode.gatherFaceDownWeapons:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.spreadWeapondsCardsFaceDown:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.selectWeapon:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.gatherFaceDownWeapons_LessMurderWeapon:
							cAnimateDealCards.bolInit = false;
							break;


						/// shuffle, select & hide suspects
						case enuDealCardsMode.spreadSuspectCardsFaceUp:
							cAnimateDealCards.intAnimationCounter = 0;

							bmpDealAnimationBoard_Base = AnimateDealCards_getBlankDealCardsImage();

							using (Graphics g = Graphics.FromImage(bmpDealAnimationBoard_Base))
							{
								// draw back weapon card stack
								classCard cThisCard = cAnimateDealCards.udrTypeOrder.lstSuspects[cAnimateDealCards.udrTypeOrder.lstSuspects.Count - 1];
								Point ptTL = new Point(ptAnimationTypeStackPos[(int)enuCardType.weapon].X - intHalfCardWidth, ptAnimationTypeStackPos[(int)enuCardType.weapon].Y - intHalfCardHeight);
								g.DrawImage(cCardUnknown.cBmp.getImage(0), ptTL);

								// draw front room stack
								cThisCard = cAnimateDealCards.udrTypeOrder.lstRooms[cAnimateDealCards.udrTypeOrder.lstRooms.Count - 1];
								ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - intHalfCardWidth, cThisCard.cAnimationInfo.ptPos.Y - intHalfCardHeight);
								g.DrawImage(cThisCard.cBmp.getImage(0), ptTL);
							}
							break;

						case enuDealCardsMode.flipSuspectcards:
							cAnimateDealCards.bolInit = false;
							cAnimateDealCards.intAnimationCounter = 0;
							break;

						case enuDealCardsMode.shuffleSuspectCards:
							cAnimateDealCards.bolInit = false;
							cAnimateDealCards.intAnimationCounter = 0;
							break;

						case enuDealCardsMode.gatherFaceDownSuspects:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.spreadSuspectdsCardsFaceDown:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.selectSuspect:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.gatherFaceDownSuspects_LessMurderSuspect:
							cAnimateDealCards.bolInit = false;
							break;


						/// shuffle, select & hide Rooms
						case enuDealCardsMode.spreadRoomCardsFaceUp:
							cAnimateDealCards.intAnimationCounter = 0;
							bmpDealAnimationBoard_Base = AnimateDealCards_getBlankDealCardsImage();

							using (Graphics g = Graphics.FromImage(bmpDealAnimationBoard_Base))
							{
								// draw back weapon card stack
								Point ptTL = new Point(ptAnimationTypeStackPos[(int)enuCardType.weapon].X - intHalfCardWidth, ptAnimationTypeStackPos[(int)enuCardType.weapon].Y - intHalfCardHeight);
								g.DrawImage(cCardUnknown.cBmp.getImage(0), ptTL);

								// draw back suspect stack
								ptTL = new Point(ptAnimationTypeStackPos[(int)enuCardType.Suspect].X - intHalfCardWidth, ptAnimationTypeStackPos[(int)enuCardType.Suspect].Y - intHalfCardHeight);
								g.DrawImage(cCardUnknown.cBmp.getImage(0), ptTL);
							}
							break;

						case enuDealCardsMode.flipRoomcards:
							cAnimateDealCards.bolInit = false;
							cAnimateDealCards.intAnimationCounter = 0;
							break;

						case enuDealCardsMode.shuffleRoomCards:
							cAnimateDealCards.bolInit = false;
							cAnimateDealCards.intAnimationCounter = 0;
							break;

						case enuDealCardsMode.gatherFaceDownRooms:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.spreadRoomdsCardsFaceDown:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.selectRoom:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.gatherFaceDownRooms_LessMurderRoom:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.shuffleCards:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.joinCardsAfterShuffle:
							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.dealToPlayers:
							cAnimateDealCards.bolInit = false;
							int intCardIndex = (int)classCard.getECardFromEWeapon(cMurder.eWeapon);
							cCards[intCardIndex].cAnimationInfo.intStep = cCards[intCardIndex].cAnimationInfo.intMaxSteps;

							intCardIndex = (int)classCard.getECardFromERoom(cMurder.eRoom);
							cCards[intCardIndex].cAnimationInfo.intStep = cCards[intCardIndex].cAnimationInfo.intMaxSteps;

							intCardIndex = (int)classCard.getECardFromESuspect(cMurder.eSuspect);
							cCards[intCardIndex].cAnimationInfo.intStep = cCards[intCardIndex].cAnimationInfo.intMaxSteps;

							cAnimateDealCards.strCards = strCardsDealt;
							break;

						case enuDealCardsMode.moveMurderCardsToCenter:
							bmpDealAnimationBoard_Base = AnimateDealCards_getBlankDealCardsImage();
							cAnimateDealCards.lstCardsCurrentAnimation.Clear();
							cAnimateDealCards.lstCardsCurrentAnimation.Add(cCards[(int)classCard.getECardFromESuspect ( cMurder.eSuspect)]);
							cAnimateDealCards.lstCardsCurrentAnimation.Add(cCards[(int)classCard.getECardFromERoom ( cMurder.eRoom)]);
							cAnimateDealCards.lstCardsCurrentAnimation.Add(cCards[(int)classCard.getECardFromEWeapon ( cMurder.eWeapon)]);

							enuCards eWeapon = classCard.getECardFromEWeapon(cMurder.eWeapon);
							enuCards eSuspect = classCard.getECardFromESuspect(cMurder.eSuspect);
							enuCards eRoom = classCard.getECardFromERoom(cMurder.eRoom);

							using (Graphics g = Graphics.FromImage(bmpDealAnimationBoard_Base))
							{
								for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
									for (int intCardCounter = 0; intCardCounter < cSuspects[(int)eSuspectCounter].cCards.Length; intCardCounter++)
									{
										classCard cThisCard = cSuspects[(int)eSuspectCounter].cCards[intCardCounter];

										int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing);

										Bitmap bmp = cThisCard.cSuspect.bolPlayerControlled ? cThisCard.cBmp.getImage(intImageIndex) : cCardUnknown.cBmp.getImage(intImageIndex);
										Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
										g.DrawImage(bmp, ptTL);

										cThisCard.cAnimationInfo.intStep++;
									}
							}

							cAnimateDealCards.bolInit = false;
							break;

						case enuDealCardsMode.endDealCardsAnimation:
							if (eMode == enuMode.idle)
							{
								eDealMode  = enuDealCardsMode.SortCardsIntotypes;
								return;
							}
							break;
					}
				}
			}
		}

		Bitmap AnimateDealCards_getBlankDealCardsImage()
		{
			Bitmap bmpTemp = new Bitmap(pnlNotebook.Left + 240, picBoard.Height);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				g.DrawImage(bmpBoard, 0, 0);
				g.DrawImage((Bitmap)Resources.notebook, pnlNotebook.Left, 0);
			}
			return bmpTemp;
		}

		void animateDealCards()
		{
			if (cAnimateDealCards.bolQuitAnimation)
			{
				if (eMode == enuMode.idle)
					NewGame((object)this, new EventArgs());
				else
					eDealMode = enuDealCardsMode.endDealCardsAnimation;
			}
			switch (eDealMode)
			{
				case enuDealCardsMode.SortCardsIntotypes:
					bmpDealAnimationBoard_Base = AnimateDealCards_getBlankDealCardsImage();
					picBoard.Image = bmpDealAnimationBoard_Base;
					picBoard.BringToFront();
					AnimateDealCards_SortCardsIntoTypes();
					break;

				case enuDealCardsMode.gatherTypes:
					AnimateDealCards_GatherTypes();
					break;

				/// shuffle, select & hide weapons
				case enuDealCardsMode.spreadWeaponCardsFaceUp:
					AnimateDealCards_SpreadCards(enuCardType.weapon, true);
					break;

				case enuDealCardsMode.flipWeaponcards:
					AnimateDealCards_FlipCardsUtoD_DirR(enuCardType.weapon);
					break;

				case enuDealCardsMode.shuffleWeaponCards:
					AnimateDealCards_Shuffle(enuCardType.weapon);
					break;

				case enuDealCardsMode.gatherFaceDownWeapons:
					AnimateDealCards_GatherType(ptAnimationTypeStackPos[(int)enuCardType.weapon], enuCardType.weapon, false);
					break;

				case enuDealCardsMode.spreadWeapondsCardsFaceDown:
					AnimateDealCards_SpreadCards(enuCardType.weapon, false);
					break;

				case enuDealCardsMode.selectWeapon:
					AnimateDealCards_SelectCard(enuCardType.weapon);
					break;

				case enuDealCardsMode.gatherFaceDownWeapons_LessMurderWeapon:
					AnimateDealCards_GatherType(ptAnimationTypeStackPos[(int)enuCardType.weapon], enuCardType.weapon, false);
					break;


				/// shuffle, select & hide Suspects
				case enuDealCardsMode.spreadSuspectCardsFaceUp:
					AnimateDealCards_SpreadCards(enuCardType.Suspect, true);
					break;

				case enuDealCardsMode.flipSuspectcards:
					AnimateDealCards_FlipCardsUtoD_DirR(enuCardType.Suspect);
					break;

				case enuDealCardsMode.shuffleSuspectCards:
					AnimateDealCards_Shuffle(enuCardType.Suspect);
					break;

				case enuDealCardsMode.gatherFaceDownSuspects:
					AnimateDealCards_GatherType(ptAnimationTypeStackPos[(int)enuCardType.Suspect], enuCardType.Suspect, false);
					break;

				case enuDealCardsMode.spreadSuspectdsCardsFaceDown:
					AnimateDealCards_SpreadCards(enuCardType.Suspect, false);
					break;

				case enuDealCardsMode.selectSuspect:
					AnimateDealCards_SelectCard(enuCardType.Suspect);
					break;

				case enuDealCardsMode.gatherFaceDownSuspects_LessMurderSuspect:
					AnimateDealCards_GatherType(ptAnimationTypeStackPos[(int)enuCardType.Suspect], enuCardType.Suspect, false);
					break;


				/// shuffle, select & hide Rooms
				case enuDealCardsMode.spreadRoomCardsFaceUp:
					AnimateDealCards_SpreadCards(enuCardType.room, true);
					break;

				case enuDealCardsMode.flipRoomcards:
					AnimateDealCards_FlipCardsUtoD_DirR(enuCardType.room);
					break;

				case enuDealCardsMode.shuffleRoomCards:
					AnimateDealCards_Shuffle(enuCardType.room);
					break;

				case enuDealCardsMode.gatherFaceDownRooms:
					AnimateDealCards_GatherType(ptAnimationTypeStackPos[(int)enuCardType.room], enuCardType.room, false);
					break;

				case enuDealCardsMode.spreadRoomdsCardsFaceDown:
					AnimateDealCards_SpreadCards(enuCardType.room, false);
					break;

				case enuDealCardsMode.selectRoom:
					AnimateDealCards_SelectCard(enuCardType.room);
					break;

				case enuDealCardsMode.gatherFaceDownRooms_LessMurderRoom:
					AnimateDealCards_GatherType(ptAnimationTypeStackPos[(int)enuCardType.room], enuCardType.room, false);
					break;

				case enuDealCardsMode.shuffleCards:
					bmpDealAnimationBoard_Base = AnimateDealCards_getBlankDealCardsImage();
					AnimateDealCards_ShuffleCards();
					break;

				case enuDealCardsMode.joinCardsAfterShuffle:
					AnimateDealCards_JoinCards();
					break;

				case enuDealCardsMode.dealToPlayers:
					AnimateDealCards_DealToPlayers();
					break;

				case enuDealCardsMode.moveMurderCardsToCenter:
					
					AnimateDealCards_MoveMurderCardsToCenter();
					break;

				case enuDealCardsMode.endDealCardsAnimation:
					if (eMode == enuMode.idle)
					{
						eDealMode = enuDealCardsMode.SortCardsIntotypes;
					}
					else
					{
						setPlayerNoteBook();
						drawPlayerCards();
						setSuspectsAI();

						//grbControls.Enabled = 
							grbControls.Visible = true;
						intSuspectTurn = 0;

						eMode = enuMode.warnPlayerNextTurn;
					}
					break;
			}
		}

		void AnimateDealCards_MoveMurderCardsToCenter()
		{
			if (!cAnimateDealCards.bolInit)
			{
				cAnimateDealCards.bolInit = true;
				

				for (int intCardCounter = 0; intCardCounter < cAnimateDealCards.lstCardsCurrentAnimation.Count; intCardCounter++)
				{
					classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[intCardCounter];
					cThisCard.cAnimationInfo.ptStart = getRoomCenter(enuRooms.Kitchen);
					cThisCard.cAnimationInfo.ptEnd = getRoomCenter(enuRooms._numRooms);

					cThisCard.cAnimationInfo.dblTravelAngle =classMath.arcTan(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
					cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);

					cThisCard.cAnimationInfo.intMaxSteps = intCardCounter * 10 + 10;
					cThisCard.cAnimationInfo.intStep =0;

					cThisCard.cAnimationInfo.velTravel.X  = (int)(cThisCard.cAnimationInfo.dblTravelDistance / (double) cThisCard.cAnimationInfo.intMaxSteps * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle));
					cThisCard.cAnimationInfo.velTravel.Y = (int)(cThisCard.cAnimationInfo.dblTravelDistance / (double)cThisCard.cAnimationInfo.intMaxSteps * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle));

					double dblNumRotations = intCardCounter;
					cThisCard.cAnimationInfo.dblAngleTurning = (dblNumRotations * 2.0 * Math.PI) / (double)cThisCard.cAnimationInfo.intMaxSteps * ((int)(rnd.NextDouble() * 1000) % 2 == 0 ? 1 : -1);
				}
			}
			Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
			bool bolQuit = true;
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{				 
				for (int intCardCounter = 0; intCardCounter < cAnimateDealCards.lstCardsCurrentAnimation.Count; intCardCounter++)
				{
					classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[intCardCounter];

					if (cThisCard.cAnimationInfo.intStep < cThisCard.cAnimationInfo.intMaxSteps)
					{
						bolQuit = false;
						// move this card along 
						cThisCard.cAnimationInfo.ptPos.X += cThisCard.cAnimationInfo.velTravel.X;
						cThisCard.cAnimationInfo.ptPos.Y += cThisCard.cAnimationInfo.velTravel.Y;

						cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

						while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
							cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;
						while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
							cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;
					}

					int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing);
					Bitmap bmp = cCardUnknown.cBmp.getImage(intImageIndex);
					Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
					g.DrawImage(bmp, ptTL);

					cThisCard.cAnimationInfo.intStep++;
					if (cThisCard.cAnimationInfo.intStep == cThisCard.cAnimationInfo.intMaxSteps)
					{
						cThisCard.cAnimationInfo.ptPos = cThisCard.cAnimationInfo.ptEnd;
						cThisCard.cAnimationInfo.dblAngleFacing = 0;
					}
				}

				
			}
			picBoard.Image = bmpTemp; picBoard.Refresh();

			if (bolQuit)
			{
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
			}
			setDelayTimer(10);
		}

		void AnimateDealCards_JoinCards()
		{
			enuCards eWeapon = classCard.getECardFromEWeapon(cMurder.eWeapon);
			enuCards eSuspect = classCard.getECardFromESuspect(cMurder.eSuspect);
			enuCards eRoom = classCard.getECardFromERoom(cMurder.eRoom);

			if (!cAnimateDealCards.bolInit)
			{
				cAnimateDealCards.bolInit = true;

				for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
				{
					classCard cThisCard = cCards[intCardCounter];

					cThisCard.cAnimationInfo.intMaxSteps = (int)(rnd.NextDouble() * 1000) % 15 + 10;
					cThisCard.cAnimationInfo.intStep = 0;

					cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
					cThisCard.cAnimationInfo.ptEnd = getRoomCenter(enuRooms._numRooms);

					cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
					cThisCard.cAnimationInfo.dblTravelInitialVelocity = cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.intMaxSteps;

					cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
					cThisCard.cAnimationInfo.velTravel.X = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle));
					cThisCard.cAnimationInfo.velTravel.Y = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle));


					if (cThisCard.cAnimationInfo.dblAngleFacing > Math.PI)
						cThisCard.cAnimationInfo.dblAngleTurning = (dblTwoPi - cThisCard.cAnimationInfo.dblAngleFacing) / cThisCard.cAnimationInfo.intMaxSteps;
					else
						cThisCard.cAnimationInfo.dblAngleTurning = -cThisCard.cAnimationInfo.dblAngleFacing / cThisCard.cAnimationInfo.intMaxSteps;

					if (Math.Abs(cThisCard.cAnimationInfo.dblAngleTurning) < (Math.PI / 32.0))
					{
						cThisCard.cAnimationInfo.dblAngleTurning = 0;
						cThisCard.cAnimationInfo.dblAngleFacing = 0;
					}
				}
			}

			Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
			bool bolQuit = true;
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{

				for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
				{
					classCard cThisCard = cCards[intCardCounter];

					if (cThisCard.eCardName != eWeapon
						&& cThisCard.eCardName != eSuspect
						&& cThisCard.eCardName != eRoom)
					{
						if (cThisCard.cAnimationInfo.intStep < cThisCard.cAnimationInfo.intMaxSteps)
						{
							bolQuit = false;
							// move this card along 
							cThisCard.cAnimationInfo.ptPos.X += cThisCard.cAnimationInfo.velTravel.X;
							cThisCard.cAnimationInfo.ptPos.Y += cThisCard.cAnimationInfo.velTravel.Y;

							cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

							while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
								cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;
							while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
								cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;
						}

						int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing );
						Bitmap bmp = cCardUnknown.cBmp.getImage(intImageIndex);
						Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
						g.DrawImage(bmp, ptTL);

						cThisCard.cAnimationInfo.intStep++;
						if (cThisCard.cAnimationInfo.intStep == cThisCard.cAnimationInfo.intMaxSteps)
						{
							cThisCard.cAnimationInfo.ptPos = cThisCard.cAnimationInfo.ptEnd;
							cThisCard.cAnimationInfo.dblAngleFacing = 0;
						}
					}
				}

				AnimateDealCards_drawMurderCards(g);
			}
			picBoard.Image = bmpTemp; picBoard.Refresh();
			
			if (bolQuit)
			{
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
			}
			setDelayTimer(100);
		}

		int getImageIndex(double dblAngle) {return  (int)(dblAngle/ (Math.PI / 8.0)) % 16; }

		void AnimateDealCards_ShuffleCards()
		{
			if (!cAnimateDealCards.bolInit)
			{
				cAnimateDealCards.bolInit = true;

				for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
				{
					cCards[intCardCounter].cAnimationInfo.intStep = cCards[intCardCounter].cAnimationInfo.intMaxSteps;
					cCards[intCardCounter].cAnimationInfo.ptStart = cCards[intCardCounter].cAnimationInfo.ptPos;
				}

				cAnimateDealCards.udrShuffle.ptCentralShufflePos = getRoomCenter(enuRooms._numRooms);
				cAnimateDealCards.udrShuffle.intMaxDistance = (int)(bmpBoard.Width * .4);
				cAnimateDealCards.udrShuffle.intTimeShuffled = 0;
				cAnimateDealCards.udrShuffle.intMaxShuffle = 50;
			}

			Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				enuCards eWeapon = classCard.getECardFromEWeapon(cMurder.eWeapon);
				enuCards eSuspect = classCard.getECardFromESuspect(cMurder.eSuspect);
				enuCards eRoom = classCard.getECardFromERoom(cMurder.eRoom);

				AnimateDealCards_drawMurderCards(g);

				for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
				{
					classCard cThisCard = cCards[intCardCounter];

					if (cThisCard.eCardName != eWeapon
						&& cThisCard.eCardName != eSuspect
						&& cThisCard.eCardName != eRoom)
					{
						// prepare this card for next move
						if (cThisCard.cAnimationInfo.intStep >= cThisCard.cAnimationInfo.intMaxSteps)
						{
							int intRndDistance = (int)(rnd.NextDouble() * 10000) % cAnimateDealCards.udrShuffle.intMaxDistance;
							double dblRndRad = rnd.NextDouble() * Math.PI * 2.0;
							cThisCard.cAnimationInfo.intMaxSteps = (int)(rnd.NextDouble() * 1000) % 5 + 5;
							cThisCard.cAnimationInfo.intStep = 0;

							cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
							cThisCard.cAnimationInfo.ptEnd
								= new Point(cAnimateDealCards.udrShuffle.ptCentralShufflePos.X + (int)(intRndDistance * Math.Cos(dblRndRad)),
											cAnimateDealCards.udrShuffle.ptCentralShufflePos.Y + (int)(intRndDistance * Math.Sin(dblRndRad)));

							cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
							cThisCard.cAnimationInfo.dblTravelInitialVelocity = cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.intMaxSteps;

							cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
							cThisCard.cAnimationInfo.velTravel.X = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle));
							cThisCard.cAnimationInfo.velTravel.Y = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle));

							double dblMaxAngularVelocity = Math.PI * .2;
							cThisCard.cAnimationInfo.dblAngleTurning = rnd.NextDouble() * 2.0 * dblMaxAngularVelocity - dblMaxAngularVelocity;
						}

						// move this card along 
						cThisCard.cAnimationInfo.ptPos.X += cThisCard.cAnimationInfo.velTravel.X;
						cThisCard.cAnimationInfo.ptPos.Y += cThisCard.cAnimationInfo.velTravel.Y;

						cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

						while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
							cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;
						while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
							cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;

						int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing);
						Bitmap bmp = cCardUnknown.cBmp.getImage(intImageIndex);
						Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
						g.DrawImage(bmp, ptTL);

						cThisCard.cAnimationInfo.intStep++;
					}
				}

			}
			picBoard.Image = bmpTemp; picBoard.Refresh();

			cAnimateDealCards.udrShuffle.intTimeShuffled++;
			if (cAnimateDealCards.udrShuffle.intTimeShuffled > cAnimateDealCards.udrShuffle.intMaxShuffle)
			{
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
			}
			setDelayTimer(100);
		}

		void AnimateDealCards_DealToPlayers()
		{
			if (cAnimateDealCards.intAnimationCounter % 8 == 0 && cAnimateDealCards.strCards.Length > 0)
			{
				// throw new card across the table				
				int intNumCardsLeft = cAnimateDealCards.strCards.Length / 2;

				/// first card out is 6 + 6 + 9 = 21 - 3 = 18
				enuSuspects eSuspectReceivingCard = (enuSuspects)((18 - intNumCardsLeft)%(int)enuSuspects._numSuspects);

				string strThisCard = cAnimateDealCards.strCards.Substring(0, 2);
				cAnimateDealCards.strCards = cAnimateDealCards.strCards.Substring(2);
				enuCards eCard = (enuCards)Convert.ToInt16(strThisCard);
				//Array.Resize<classCard>(ref cAnimateDealCards.cCardsCurrentAnimation, cAnimateDealCards.cCardsCurrentAnimation.Length + 1);
				//cAnimateDealCards.cCardsCurrentAnimation[cAnimateDealCards.cCardsCurrentAnimation.Length - 1] = cCards[(int)eCard];
				cAnimateDealCards.lstCardsCurrentAnimation.Add(cCards[(int)eCard]);
				classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[cAnimateDealCards.lstCardsCurrentAnimation.Count - 1];
				cSuspects[(int)eSuspectReceivingCard].receiveCard(ref cThisCard);
				Point ptEnd = new Point(1, 1);
				int intEdge = 20;
				switch (eSuspectReceivingCard)
				{
					case enuSuspects.MissScarlet:
						ptEnd = new Point((int)(bmpBoard.Width * .6), intEdge );
						break;

					case enuSuspects.ColMustard:
						ptEnd = new Point((int)(bmpBoard.Width - intEdge ), (int)(bmpBoard.Height *.3));
						break;

					case enuSuspects.MrsWhite:
						ptEnd = new Point((int)(bmpBoard.Width *.7 ), (int)(bmpBoard.Height - intEdge));
						break;

					case enuSuspects.RevGreen:
						ptEnd = new Point((int)(bmpBoard.Width * .3), (int)(bmpBoard.Height - intEdge));
						break;

					case enuSuspects.MrsPeacock:
						ptEnd = new Point(intEdge, (int)(bmpBoard.Height *.7));
						break;

					case enuSuspects.ProfPlum:
						ptEnd = new Point(intEdge, (int)(bmpBoard.Height * .3));
						break;
				}

				cThisCard.cSuspect = cSuspects[(int)eSuspectReceivingCard];

				int intRangeError = (int)(bmpBoard.Height * .04);
				ptEnd = new Point((int)(ptEnd.X + (int)(rnd.NextDouble() * 1000) % intRangeError * Math.Cos(rnd.NextDouble() * Math.PI * 2)),
								  (int)(ptEnd.Y + (int)(rnd.NextDouble() * 1000) % intRangeError * Math.Sin(rnd.NextDouble() * Math.PI * 2)));

				cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
				cThisCard.cAnimationInfo.ptEnd = ptEnd;
				cThisCard.cAnimationInfo.dblTravelAcceleration = -5;
				cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(ptEnd, cThisCard.cAnimationInfo.ptStart);
				cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(ptEnd, cThisCard.cAnimationInfo.ptStart);
				cThisCard.cAnimationInfo.intMaxSteps = (int)Math.Ceiling(Math.Sqrt(-2.0 * cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.dblTravelAcceleration));
				cThisCard.cAnimationInfo.dblTravelInitialVelocity = -cThisCard.cAnimationInfo.dblTravelAcceleration * cThisCard.cAnimationInfo.intMaxSteps;
				cThisCard.cAnimationInfo.dblAngleTurning = rnd.NextDouble() * Math.PI * (1.0 / 8.0);
				cThisCard.cAnimationInfo.intStep = 0;
				cThisCard.cAnimationInfo.dblAngleTurningAttenuation = 0.95;
			}

			cAnimateDealCards.intAnimationCounter++;

			bmpDealAnimationBoard = new Bitmap(bmpDealAnimationBoard_Base);
			bool bolEndSortCards = true;

			using (Graphics g = Graphics.FromImage(bmpDealAnimationBoard))
			{
				if (cAnimateDealCards.strCards.Length > 0)
				{ // if there are still cards left in the center stack -> draw center stack
					Bitmap bmp = cCardUnknown.cBmp.getImage(0);
					Point ptTL = new Point(getRoomCenter(enuRooms._numRooms).X - bmp.Width / 2, getRoomCenter(enuRooms._numRooms).Y - bmp.Height / 2);
					g.DrawImage(bmp, ptTL);
				}
				
				// draw murder cards
				Bitmap bmpMurderCards = cCardUnknown.cBmp.getImage(0);
				Point ptTLMurderCards = new Point(getRoomCenter(enuRooms.Kitchen).X - bmpMurderCards.Width / 2, getRoomCenter(enuRooms.Kitchen).Y - bmpMurderCards.Height / 2);
				g.DrawImage(bmpMurderCards, ptTLMurderCards);


				for (int intCardCounter = 0; intCardCounter < cAnimateDealCards.lstCardsCurrentAnimation.Count; intCardCounter++)
				{
					classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[intCardCounter];
					if (cThisCard.cAnimationInfo.intStep < cThisCard.cAnimationInfo.intMaxSteps)
					{
						bolEndSortCards = false;

						cThisCard.cAnimationInfo.intStep++;

						double dblDistanceTravelled = cThisCard.cAnimationInfo.dblTravelInitialVelocity * cThisCard.cAnimationInfo.intStep + .5 * cThisCard.cAnimationInfo.dblTravelAcceleration * cThisCard.cAnimationInfo.intStep * cThisCard.cAnimationInfo.intStep;
						cThisCard.cAnimationInfo.ptPos = new Point(cThisCard.cAnimationInfo.ptStart.X + (int)(dblDistanceTravelled * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle)),
																	 cThisCard.cAnimationInfo.ptStart.Y + (int)(dblDistanceTravelled * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle)));

						cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

						while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
							cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;
						while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
							cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;

						cThisCard.cAnimationInfo.dblAngleTurning *= cThisCard.cAnimationInfo.dblAngleTurningAttenuation;
					}

					int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing);
					Bitmap bmp = cThisCard.cSuspect.bolPlayerControlled ? cThisCard.cBmp.getImage (intImageIndex): cCardUnknown.cBmp.getImage(intImageIndex);
					Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
					g.DrawImage(bmp, ptTL);
				}

				
			}

			picBoard.Image = bmpDealAnimationBoard; picBoard.Refresh();
			if (bolEndSortCards && cAnimateDealCards.strCards.Length == 0)
			{
				eDealMode  = (enuDealCardsMode)((int)eDealMode + 1);
				cAnimateDealCards.intAnimationCounter = 0;
			}
			setDelayTimer(10);
		}

		void AnimateDealCards_SelectCard(enuCardType eTypeCard)
		{
			classCard cThisCard = cCards[(int)classCard.getECardFromERoom(cMurder.eRoom)];
			classCard[] cCardsArray = cAnimateDealCards.udrTypeOrder.lstRooms.ToArray();

			switch (eTypeCard)
			{
				case enuCardType.Suspect:
					cCardsArray = cAnimateDealCards.udrTypeOrder.lstSuspects.ToArray();
					cThisCard = cCards[(int)classCard.getECardFromESuspect(cMurder.eSuspect)];
					break;

				case enuCardType.weapon:
					cCardsArray = cAnimateDealCards.udrTypeOrder.lstWeapons.ToArray();
					cThisCard = cCards[(int)classCard.getECardFromEWeapon(cMurder.eWeapon)];
					break;
			}

			if (!cAnimateDealCards.bolInit)
			{
				for (int intCardCounter = 0; intCardCounter < cCardsArray.Length; intCardCounter++)
				{
					cCardsArray[intCardCounter].cAnimationInfo.ptStart = cCardsArray[intCardCounter].cAnimationInfo.ptPos;
					cCardsArray[intCardCounter].cAnimationInfo.ptEnd = cCardsArray[intCardCounter].cAnimationInfo.ptPos;
					cCardsArray[intCardCounter].cAnimationInfo.dblAngleFacing = 0;
				}

				cAnimateDealCards.bolInit = true;
				cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
				cThisCard.cAnimationInfo.ptEnd = getRoomCenter(enuRooms.Kitchen);

				cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
				
				cThisCard.cAnimationInfo.intMaxSteps = (int)(cThisCard.cAnimationInfo.dblTravelDistance / 40);
				cThisCard.cAnimationInfo.intStep = 0;

				cThisCard.cAnimationInfo.dblTravelInitialVelocity = cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.intMaxSteps;

				cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
				cThisCard.cAnimationInfo.velTravel.X = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle));
				cThisCard.cAnimationInfo.velTravel.Y = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle));

			}

			Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				if (eDealMode > enuDealCardsMode.selectWeapon)
					AnimateDealCards_drawMurderCards(g);
				
				// move this card along 
				cThisCard.cAnimationInfo.ptPos.X += cThisCard.cAnimationInfo.velTravel.X;
				cThisCard.cAnimationInfo.ptPos.Y += cThisCard.cAnimationInfo.velTravel.Y;

				cThisCard.cAnimationInfo.intStep++;

				for (int intCardCounter = 0; intCardCounter < cCardsArray.Length; intCardCounter++)
				{
					int intImageIndex = getImageIndex(cCardsArray[intCardCounter].cAnimationInfo.dblAngleFacing);
					Bitmap bmp = cCardUnknown.cBmp.getImage(intImageIndex);
					Point ptTL = new Point(cCardsArray[intCardCounter].cAnimationInfo.ptPos.X - bmp.Width / 2, cCardsArray[intCardCounter].cAnimationInfo.ptPos.Y - bmp.Height / 2);
					g.DrawImage(bmp, ptTL);
				}
				
			}

			picBoard.Image = bmpTemp; picBoard.Refresh();

			if (cThisCard.cAnimationInfo.intStep >= cThisCard.cAnimationInfo.intMaxSteps)
			{
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
			}
			setDelayTimer(10);
		}

		void AnimateDealCards_drawMurderCards(Graphics g)
		{
			Point ptKitchen = getRoomCenter(enuRooms.Kitchen);
			Bitmap bmpCard = cCardUnknown.cBmp.getImage(0);
			Point ptTL = new Point(ptKitchen.X - bmpCard.Width / 2, ptKitchen.Y - bmpCard.Height / 2);
			g.DrawImage(bmpCard, ptTL);
		}

		void AnimateDealCards_Shuffle(enuCardType eTypeCard)
		{
			if (!cAnimateDealCards.bolInit)
			{
				cAnimateDealCards.bolInit = true;
				cAnimateDealCards.intAnimationCounter = 0;

				classCard[] cCardsInitArray = cAnimateDealCards.udrTypeOrder.lstRooms.ToArray();
				switch (eTypeCard)
				{
					case enuCardType.Suspect:
						cCardsInitArray = cAnimateDealCards.udrTypeOrder.lstSuspects.ToArray();
						break;

					case enuCardType.weapon:
						cCardsInitArray = cAnimateDealCards.udrTypeOrder.lstWeapons.ToArray();
						break;
				}

				for (int intCardCounter = 0; intCardCounter < cCardsInitArray.Length; intCardCounter++)
				{
					cCardsInitArray[intCardCounter].cAnimationInfo.intStep = cCardsInitArray[intCardCounter].cAnimationInfo.intMaxSteps;
					cCardsInitArray[intCardCounter].cAnimationInfo.ptStart = cCardsInitArray[intCardCounter].cAnimationInfo.ptPos;
					cCardsInitArray[intCardCounter].cAnimationInfo.dblAngleFacing = 0;
				}
				cAnimateDealCards.udrShuffle = new classAnimateDealCards_Shuffle();

                cAnimateDealCards.udrShuffle.ptCentralShufflePos = cCardsInitArray[cCardsInitArray.Length / 2].cAnimationInfo.ptPos;
				cAnimateDealCards.udrShuffle.intMaxDistance = (int)(bmpBoard.Width * .3);
				cAnimateDealCards.udrShuffle.intTimeShuffled = 0;
				cAnimateDealCards.udrShuffle.intMaxShuffle = 40;
			}

			classCard[] cCardsArray = cAnimateDealCards.udrTypeOrder.lstRooms.ToArray();
			switch (eTypeCard)
			{
				case enuCardType.Suspect:
					cCardsArray = cAnimateDealCards.udrTypeOrder.lstSuspects.ToArray();
					break;

				case enuCardType.weapon:
					cCardsArray = cAnimateDealCards.udrTypeOrder.lstWeapons.ToArray();
					break;
			}

			Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				if (eDealMode > enuDealCardsMode.selectWeapon)
					AnimateDealCards_drawMurderCards(g);
				
				for (int intCardCounter = 0; intCardCounter < cCardsArray.Length; intCardCounter++)
				{
					classCard cThisCard = cCardsArray[intCardCounter];

					// prepare this card for next move
					if (cThisCard.cAnimationInfo.intStep >= cThisCard.cAnimationInfo.intMaxSteps)
					{
						int intRndDistance = (int)(rnd.NextDouble() * 10000) % cAnimateDealCards.udrShuffle.intMaxDistance;
						double dblRndRad = rnd.NextDouble() * Math.PI * 2.0;
						cThisCard.cAnimationInfo.intMaxSteps = (int)(rnd.NextDouble() * 1000) % 10 + 5;
						cThisCard.cAnimationInfo.intStep = 0;

						cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
						cThisCard.cAnimationInfo.ptEnd
							= new Point(cAnimateDealCards.udrShuffle.ptCentralShufflePos.X + (int)(intRndDistance * Math.Cos(dblRndRad)),
										cAnimateDealCards.udrShuffle.ptCentralShufflePos.Y + (int)(intRndDistance * Math.Sin(dblRndRad)));

						cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
						cThisCard.cAnimationInfo.dblTravelInitialVelocity = cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.intMaxSteps;

						cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
						cThisCard.cAnimationInfo.velTravel.X = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle));
						cThisCard.cAnimationInfo.velTravel.Y = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle));

						double dblMaxAngularVelocity = Math.PI * .02;
						cThisCard.cAnimationInfo.dblAngleTurning = rnd.NextDouble() * 2.0 * dblMaxAngularVelocity - dblMaxAngularVelocity;
						cThisCard.cAnimationInfo.dblAngleFacing = 0;
					}

					// move this card along 
					cThisCard.cAnimationInfo.ptPos.X += cThisCard.cAnimationInfo.velTravel.X;
					cThisCard.cAnimationInfo.ptPos.Y += cThisCard.cAnimationInfo.velTravel.Y;

					cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

					while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
						cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;
					while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
						cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;

					int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing);
					Bitmap bmp = cCardUnknown.cBmp.getImage(intImageIndex);
					Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
					g.DrawImage(bmp, ptTL);

					cThisCard.cAnimationInfo.intStep++;
				}
				
			}
			picBoard.Image = bmpTemp; picBoard.Refresh();

			// randomly swap two cards

			if (cAnimateDealCards.udrShuffle.intTimeShuffled > 10)
			{
				int intRndA = 0, intRndB = 0;
				while (intRndA == intRndB)
				{
					intRndB = (int)(rnd.NextDouble() * 1000) % cCardsArray.Length;
					intRndA = (int)(rnd.NextDouble() * 1000) % cCardsArray.Length;
				}

				classCard cTemp = cCardsArray[intRndA];
				cCardsArray[intRndA] = cCardsArray[intRndB];
				cCardsArray[intRndB] = cTemp;
			}

			cAnimateDealCards.udrShuffle.intTimeShuffled++;
			if (cAnimateDealCards.udrShuffle.intTimeShuffled > cAnimateDealCards.udrShuffle.intMaxShuffle)
			{
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
			}
			setDelayTimer(10);
		}

		void AnimateDealCards_GatherType(Point ptDestination, enuCardType eCardType, bool bolFaceUp)
		{
			classCard[] cCardsArray = cAnimateDealCards.udrTypeOrder.lstRooms.ToArray();
			classCard cCardException = null;

			switch (eCardType)
			{
				case enuCardType.room:
					if (eDealMode > enuDealCardsMode.selectRoom)
						cCardException = cCards[(int)classCard.getECardFromERoom(cMurder.eRoom)];
					break;

				case enuCardType.Suspect:
					cCardsArray = cAnimateDealCards.udrTypeOrder.lstSuspects.ToArray();
					if (eDealMode > enuDealCardsMode.selectSuspect)
						cCardException = cCards[(int)classCard.getECardFromESuspect(cMurder.eSuspect)];
					break;

				case enuCardType.weapon:
					cCardsArray = cAnimateDealCards.udrTypeOrder.lstWeapons.ToArray();
					if (eDealMode > enuDealCardsMode.selectWeapon)
						cCardException = cCards[(int)classCard.getECardFromEWeapon(cMurder.eWeapon)];
					break;
			}

			if (!cAnimateDealCards.bolInit)
			{
				cAnimateDealCards.bolInit = true;

				for (int intCardCounter = 0; intCardCounter < cCardsArray.Length; intCardCounter++)
				{
					classCard cThisCard = cCardsArray[intCardCounter];
					if (cThisCard != cCardException)
					{
						cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
						cThisCard.cAnimationInfo.ptEnd = ptDestination;
						int intMaxSteps = (int)(rnd.NextDouble() * 1000) % 7 + 7;
						cThisCard.cAnimationInfo.intMaxSteps = intMaxSteps;
						cThisCard.cAnimationInfo.intStep = 0;

						if (cThisCard.cAnimationInfo.dblAngleFacing > Math.PI)
							cThisCard.cAnimationInfo.dblAngleTurning = (dblTwoPi - cThisCard.cAnimationInfo.dblAngleFacing) / cThisCard.cAnimationInfo.intMaxSteps;
						else
							cThisCard.cAnimationInfo.dblAngleTurning = -cThisCard.cAnimationInfo.dblAngleFacing / cThisCard.cAnimationInfo.intMaxSteps;

						if (Math.Abs(cThisCard.cAnimationInfo.dblAngleTurning) < (Math.PI / 32.0))
						{
							cThisCard.cAnimationInfo.dblAngleTurning = 0;
							cThisCard.cAnimationInfo.dblAngleFacing = 0;
						}

						cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
						cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
						cThisCard.cAnimationInfo.dblTravelInitialVelocity = cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.intMaxSteps;
						cThisCard.cAnimationInfo.velTravel.X = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle));
						cThisCard.cAnimationInfo.velTravel.Y = (int)(cThisCard.cAnimationInfo.dblTravelInitialVelocity * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle));
					}
				}
			}

			Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
			bool bolQuit = true;
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				for (int intCardCounter = 0; intCardCounter < cCardsArray.Length; intCardCounter++)
				{
					classCard cThisCard = cCardsArray[intCardCounter];
					if (cThisCard != cCardException)
					{
						cThisCard.cAnimationInfo.ptPos.X += cThisCard.cAnimationInfo.velTravel.X;
						cThisCard.cAnimationInfo.ptPos.Y += cThisCard.cAnimationInfo.velTravel.Y;

						cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

						while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
							cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;
						while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
							cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;

						cThisCard.cAnimationInfo.intStep++;
						int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing);

						if (cThisCard.cAnimationInfo.intStep >= cThisCard.cAnimationInfo.intMaxSteps)
						{
							cThisCard.cAnimationInfo.ptPos = cThisCard.cAnimationInfo.ptEnd;
							intImageIndex = 0;
						}
						else
							bolQuit = false;

						Bitmap bmp = cThisCard.cBmp.getImage(intImageIndex);

						if (!bolFaceUp)
							bmp = cCardUnknown.cBmp.getImage(intImageIndex);

						Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
						g.DrawImage(bmp, ptTL);
					}
				}
				if (eDealMode > enuDealCardsMode.selectWeapon)
					AnimateDealCards_drawMurderCards(g);
			}
			picBoard.Image = bmpTemp; picBoard.Refresh();

			if (bolQuit)
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);

			setDelayTimer(100);
		}

		/// <summary>
		/// flip the weapon cards from a face up state to a face down one, moving from left-to-right
		/// </summary>
		void AnimateDealCards_FlipCardsUtoD_DirR(enuCardType eTypeCard)
		{
			classCard[] cAnimate = cAnimateDealCards.udrTypeOrder.lstRooms.ToArray();

			switch (eTypeCard)
			{
				case enuCardType.Suspect:
					cAnimate = cAnimateDealCards.udrTypeOrder.lstSuspects.ToArray();
					break;

				case enuCardType.weapon:
					cAnimate = cAnimateDealCards.udrTypeOrder.lstWeapons.ToArray();
					break;
			}

			int intHalfCardWidth = cCards[0].cBmp.getImage(0).Width / 2;
			int intCardHeight = cCards[0].cBmp.getImage(0).Height;
			double dblCardWidth = cCards[0].cBmp.getImage(0).Width;
			double dblK = 0;

			if (!cAnimateDealCards.bolInit)
			{
				for (int intCardCounter = 0; intCardCounter < cAnimate.Length; intCardCounter++)
				{
					classCard cThisCard = cAnimate[intCardCounter];
					// record the edge of the card which remains in contact with the table in ptStart
					cThisCard.cAnimationInfo.ptStart = new Point(cThisCard.cAnimationInfo.ptPos.X + intHalfCardWidth, cThisCard.cAnimationInfo.ptPos.Y);
					cThisCard.cAnimationInfo.ptEnd = new Point(cThisCard.cAnimationInfo.ptStart.X + cThisCard.cBmp.getImage(0).Width, cThisCard.cAnimationInfo.ptStart.Y);
				}

				cAnimateDealCards.intAnimationCounter = 0;
				cAnimateDealCards.bolInit = true;
				setDelayTimer(100);
				return;
			}

			int intMaxSteps = 30;
			cAnimateDealCards.intAnimationCounter++;
			if (cAnimateDealCards.intAnimationCounter >= intMaxSteps)
			{
				for (int intCardCounter = 0; intCardCounter < cAnimate.Length; intCardCounter++)
				{
					classCard cThisCard = cAnimate[intCardCounter];
					// record the edge of the card which remains in contact with the table in ptStart
					cThisCard.cAnimationInfo.ptPos.X += (int)dblCardWidth;
				}


				cAnimateDealCards.intAnimationCounter = 0;
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
				setDelayTimer(100);
				return;
			}

			double dblTotalDistance = 2 * dblCardWidth + cAnimate[cAnimate.Length - 1].cAnimationInfo.ptStart.X - cAnimate[0].cAnimationInfo.ptStart.X;
			double dblMPivot = 0;
			int intPivotPoint = (int)(((double)(cAnimateDealCards.intAnimationCounter) / (double)(intMaxSteps)) * dblTotalDistance);
			int intLeftMostPoint = cAnimate[0].cAnimationInfo.ptStart.X - (int)dblCardWidth;
			int intPivotCardIndex = cAnimate.Length;
			Point ptTLImage;
			Point ptTLPivotCard = new Point(0, 0);

			// select Pivot Card
			for (int intCardCounter = 0; intCardCounter < cAnimate.Length; intCardCounter++)
			{
				if (intLeftMostPoint + intPivotPoint < cAnimate[intCardCounter].cAnimationInfo.ptStart.X)
				{
					intPivotCardIndex = intCardCounter;
					break;
				}
			}

			Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				if (intPivotCardIndex < cAnimate.Length)
				{
					// calculate size and draw location of pivot card
					int intLeftPivotCard = intPivotPoint;
					classCard cPivotCard = cAnimate[intPivotCardIndex];
					int intRightPivotCard = cPivotCard.cAnimationInfo.ptStart.X;
					ptTLImage = new Point(intLeftPivotCard + intLeftMostPoint, cPivotCard.cAnimationInfo.ptPos.Y - cPivotCard.cBmp.getImage(0).Height / 2);
					int intImageWidth = cPivotCard.cAnimationInfo.ptStart.X - ptTLImage.X;

					Bitmap bmpPivotCard = new Bitmap(cPivotCard.cBmp.getImage(0), intImageWidth, intCardHeight);
					g.DrawImage(bmpPivotCard, ptTLImage);

					if (intPivotCardIndex < cAnimate.Length - 1)
					{
						// calculate contact point with card to the right
						/// view cards side-ways for calculations
						/// form two lines of bottom edge of pivot card and card to the right of it (pivot cards leans towards the left w/ right-neighbor card pressed onto it)
						/// where card to the right is leaning on pivot card
						/// both lines are of equal lengths and share a common fixed y-value for their lowest points(table)
						/// TL point of pivot card must be calculated given width of card (hypotenuse) & width of image (distance on x-plane away from pivot card's base point)
						/// set common Y value = 0(table top)
						/// set pivot card's known base point x value = 0(pivot card is in contact with that table in the system's origin)
						/// forming a right-angle triangle with X-axis, Card's edge & imaginary vertical line
						/// TL point of pivot card can be found
						/// c^2 = a^2 + b^2 -> a = sqrt(c^2-b^2), 
						/// here Y point of TL is sqrt(CardWidth^2 - CardImageWidth^2)
						/// and  X point of TL is -CardImageWidth
						ptTLPivotCard = new Point(-bmpPivotCard.Width, (int)Math.Sqrt(Math.Pow(dblCardWidth, 2) - Math.Pow(bmpPivotCard.Width, 2)));
						dblMPivot = (double)ptTLPivotCard.Y / (double)ptTLPivotCard.X;

						/// using the line equation y = Mx + B for both lines 
						/// we can calculate the point where both lines are in contact (x, y)
						/// by using the two line equations separately
						/// y = M1x + B1 and also y = M2x + B2 
						/// where (x,y) is common to both lines 
						/// we can drop an imaginary vertical line and form a right-angled triangle 
						/// knowing the hypotenuse is equal to C = card width
						/// and the adjacent side alone the x-axis = (x - k) where K is the distance between cards
						/// then solving the pythagorean triangle C^2 = A^2 + B^2 = (x-k)^2 + y^2 for y
						/// we get	y = sqrt(c^2 + 2xk - x^2 -k^2) 
						///			y = M1x + B1
						/// putting these two equations together gives us the quadratic
						/// x^2(M1^2 + 1) + x(-2k) + (K^2 - C^2) = 0						

						// constant distance between cards K
						Point ptTLPreviousCard = ptTLPivotCard;

						// calculate size and draw locations of all cards to the right of pivot card
						for (int intCardCounter = intPivotCardIndex + 1; intCardCounter < cAnimate.Length; intCardCounter++)
						{
							classCard cThisCard = cAnimate[intCardCounter];
							// solve for slope of pivot-card = dY/dX
							double dblM1 = (double)ptTLPreviousCard.Y / (double)ptTLPreviousCard.X;
							dblK = (cAnimate[intCardCounter].cAnimationInfo.ptStart.X - cAnimate[intCardCounter - 1].cAnimationInfo.ptStart.X);

							// variables of quadratic equation
							double dbl_A = (dblM1 * dblM1 + 1.0);
							double dbl_B = -2 * dblK;
							double dbl_C = dblK * dblK - dblCardWidth * dblCardWidth;

							double dblX_Plus = (-dbl_B + Math.Sqrt(dbl_B * dbl_B - 4 * dbl_A * dbl_C)) / (2 * dbl_A);
							double dblX_Minus = (-dbl_B - Math.Sqrt(dbl_B * dbl_B - 4 * dbl_A * dbl_C)) / (2 * dbl_A);

							Point ptCommon = new Point(0, 0);
							int intWidthImage = (int)dblCardWidth;

							if (dblX_Minus > ptTLPreviousCard.X - 1 && dblX_Minus < 0)
							{
								double dblX = dblX_Minus - dblK;
								ptCommon = new Point((int)dblX, (int)(dblX_Minus * dblM1));
								intWidthImage = (int)(dblK - dblX_Minus);
							}
							else if (dblX_Plus > ptTLPreviousCard.X - 1 && dblX_Plus < 0)
							{
								double dblX = dblX_Plus - dblK;
								ptCommon = new Point((int)dblX, (int)(dblX_Plus * dblM1));
								intWidthImage = (int)(dblK - dblX_Plus);
							}
							else
							{
								ptCommon = new Point(cThisCard.cAnimationInfo.ptStart.X - (int)dblCardWidth, 0);
							}

							/// previous card's base edge (ptStart.x + intHalfCard) is on the origin
							if (ptCommon.X == 0)
								ptCommon.X = 1;

							Bitmap bmpThisCardImage = new Bitmap(cThisCard.cBmp.getImage(0), intWidthImage, intCardHeight);
							ptTLImage = new Point(cThisCard.cAnimationInfo.ptStart.X - intWidthImage, cThisCard.cAnimationInfo.ptStart.Y - intCardHeight / 2);
							g.DrawImage(bmpThisCardImage, ptTLImage);

							ptTLPreviousCard = ptCommon;
						}
					}
				}

				if (intPivotCardIndex > 0)
				{ // calculate size and draw locations of all cards to the left of pivot card
					Point ptTRPreviousCard = new Point(0, 0);
					Bitmap bmpCardUnknown;
					int intWidthImage;

					for (int intCardCounter = intPivotCardIndex - 1; intCardCounter >= 0; intCardCounter--)
					{
						classCard cThisCard = cAnimate[intCardCounter];

						if (intCardCounter == cAnimate.Length - 1)
						{
							// all cards are faced down -> use Pivot point as x of TR corner for this right-most card
							intWidthImage = intLeftMostPoint + intPivotPoint - (cThisCard.cAnimationInfo.ptStart.X);
							ptTLImage = new Point(cThisCard.cAnimationInfo.ptStart.X, cThisCard.cAnimationInfo.ptStart.Y - intCardHeight / 2);
							bmpCardUnknown = new Bitmap(bmpCardBack, intWidthImage, intCardHeight);
							g.DrawImage(bmpCardUnknown, ptTLImage);

							ptTRPreviousCard = new Point(bmpCardUnknown.Width, (int)Math.Sqrt(Math.Pow(dblCardWidth, 2) - Math.Pow(bmpCardUnknown.Width, 2)));
						}
						else if (intCardCounter == intPivotCardIndex - 1)
						{  // one or more cards are face down and this is the first card to the left of the pivot card
							dblK = (cAnimate[intCardCounter + 1].cAnimationInfo.ptStart.X - cAnimate[intCardCounter].cAnimationInfo.ptStart.X);
							intWidthImage = intLeftMostPoint + intPivotPoint - cAnimate[intCardCounter].cAnimationInfo.ptStart.X;

							ptTRPreviousCard = new Point(intWidthImage,
														 (int)(Math.Sqrt(dblCardWidth * dblCardWidth - intWidthImage * intWidthImage)));
							ptTLImage = new Point(cThisCard.cAnimationInfo.ptStart.X, cThisCard.cAnimationInfo.ptStart.Y - intCardHeight / 2);
							if (intWidthImage == 0)
							{
								intWidthImage = 1;
								ptTRPreviousCard.X = 1;
							}
							bmpCardUnknown = new Bitmap(bmpCardBack, intWidthImage, intCardHeight);

							g.DrawImage(bmpCardUnknown, ptTLImage);
						}
						else
						{
							dblK = (cAnimate[intCardCounter + 1].cAnimationInfo.ptStart.X - cAnimate[intCardCounter].cAnimationInfo.ptStart.X);
							// this is one of the cards to the left of the pivot card
							// calculate slope of the card on which this card is leaning
							double dblM1 = (double)ptTRPreviousCard.Y / (double)ptTRPreviousCard.X;

							/// we know the TR point of the previous card
							/// both this card and card to the right lean towards the right with this card falling onto its right-neaghbor
							/// drop an imaginary line from the point of contact(x,y) to form a right-angle triangle 
							/// using the previous card's base point as the origin
							/// solve for y, set equal to y = M1x eq'n, drop the y's
							/// get identical quadratic as previous case above

							// variables of quadratic equation
							double dbl_A = (dblM1 * dblM1 + 1);
							double dbl_B = 2 * dblK;
							double dbl_C = dblK * dblK - dblCardWidth * dblCardWidth;

							double dblX_Plus = (-dbl_B + Math.Sqrt(dbl_B * dbl_B - 4 * dbl_A * dbl_C)) / (2 * dbl_A);
							double dblX_Minus = (-dbl_B - Math.Sqrt(dbl_B * dbl_B - 4 * dbl_A * dbl_C)) / (2 * dbl_A);

							int intImageWidth = (int)dblCardWidth;
							if (dblX_Plus > 0 && dblX_Plus < ptTRPreviousCard.X)
							{
								intImageWidth = (int)(dblX_Plus + dblK);
								ptTRPreviousCard = new Point((int)(dblK - dblX_Plus), (int)(dblM1 * (double)dblX_Plus));
							}
							else if (dblX_Minus > 0 && dblX_Minus < ptTRPreviousCard.X)
							{
								intImageWidth = (int)(dblX_Minus + dblK);
								ptTRPreviousCard = new Point((int)(dblK - dblX_Plus), (int)(dblM1 * (double)dblX_Plus));
							}
							else
							{
								ptTRPreviousCard = new Point(cThisCard.cAnimationInfo.ptStart.X + (int)dblCardWidth, 0);
							}

							ptTLImage = new Point(cThisCard.cAnimationInfo.ptStart.X, cThisCard.cAnimationInfo.ptStart.Y - intCardHeight / 2);
							bmpCardUnknown = new Bitmap(bmpCardBack, intImageWidth, intCardHeight);
							g.DrawImage(bmpCardUnknown, ptTLImage);
						}
					}
				}
				if (eDealMode > enuDealCardsMode.selectWeapon)
					AnimateDealCards_drawMurderCards(g);
			}
			picBoard.Image = bmpTemp; picBoard.Refresh();

			setDelayTimer(100);
			cAnimateDealCards.intAnimationCounter++;
		}

		void AnimateDealCards_SpreadCards(enuCardType eCardType, bool bolFaceUp)
		{
			classCard[] cAnimate = cAnimateDealCards.udrTypeOrder.lstRooms.ToArray();
			int intHGap = (int)(cCards[0].cBmp.getImage(0).Width * .45);
			switch (eCardType)
			{
				case enuCardType.Suspect:
					cAnimate = cAnimateDealCards.udrTypeOrder.lstSuspects.ToArray();
					intHGap = (int)(cCards[0].cBmp.getImage(0).Width * .65);
					break;

				case enuCardType.weapon:
					cAnimate = cAnimateDealCards.udrTypeOrder.lstWeapons.ToArray();
					intHGap = (int)(cCards[0].cBmp.getImage(0).Width * .65);
					break;
			}

			switch (cAnimateDealCards.intAnimationCounter)
			{
				case 0: // init spread out top facing  cards
					Point ptBase = cAnimate[0].cAnimationInfo.ptPos;
					int intMaxSteps = 30;
					for (int intCardCounter = 0; intCardCounter < cAnimate.Length; intCardCounter++)
					{
						classCard cThisCard = cAnimate[intCardCounter];
						cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
						cThisCard.cAnimationInfo.ptEnd = new Point(ptBase.X + intCardCounter * intHGap, ptBase.Y);
						cThisCard.cAnimationInfo.intMaxSteps = intMaxSteps;
						cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
						cThisCard.cAnimationInfo.dblTravelInitialVelocity = cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.intMaxSteps;
						cThisCard.cAnimationInfo.intStep = 0;
					}
					cAnimateDealCards.intAnimationCounter++;
					break;

				case 1: // spread out cards
					bool bolStartFlipCards = false;
					Bitmap bmpTemp = new Bitmap(bmpDealAnimationBoard_Base);
					using (Graphics g = Graphics.FromImage(bmpTemp))
					{
						for (int intCardCounter = 0; intCardCounter < cAnimate.Length; intCardCounter++)
						{
							classCard cThisCard = cAnimate[intCardCounter];
							cThisCard.cAnimationInfo.ptPos = new Point(cThisCard.cAnimationInfo.ptPos.X + (int)cThisCard.cAnimationInfo.dblTravelInitialVelocity, cThisCard.cAnimationInfo.ptPos.Y);
							cThisCard.cAnimationInfo.intStep++;
							if (cThisCard.cAnimationInfo.intStep >= cThisCard.cAnimationInfo.intMaxSteps)
								bolStartFlipCards = true;
							Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - cThisCard.cBmp.getImage(0).Width / 2, cThisCard.cAnimationInfo.ptPos.Y - cThisCard.cBmp.getImage(0).Height / 2);
							if (bolFaceUp)
								g.DrawImage(cThisCard.cBmp.getImage(0), ptTL);
							else
								g.DrawImage(cCardUnknown.cBmp.getImage(0), ptTL);
						}
						if (eDealMode > enuDealCardsMode.selectWeapon)
							AnimateDealCards_drawMurderCards(g);
					}
					if (bolStartFlipCards)
						eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
					picBoard.Image = bmpTemp; picBoard.Refresh();
					break;
			}
			setDelayTimer(10);
		}

		void AnimateDealCards_GatherTypes()
		{
			switch (cAnimateDealCards.intAnimationCounter)
			{
				case 0:					// initialize card animations
					int intMaxSteps = 10;

					for (int intCardCounter = 0; intCardCounter < cAnimateDealCards.lstCardsCurrentAnimation.Count; intCardCounter++)
					{
						classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[intCardCounter];
						cThisCard.cAnimationInfo.ptStart = cThisCard.cAnimationInfo.ptPos;
						cThisCard.cAnimationInfo.ptEnd = ptAnimationTypeStackPos[(int)cThisCard.eType];
						cThisCard.cAnimationInfo.intMaxSteps = intMaxSteps;
						cThisCard.cAnimationInfo.intStep = 0;

						if (cThisCard.cAnimationInfo.dblAngleFacing > Math.PI)
							cThisCard.cAnimationInfo.dblAngleTurning = (dblTwoPi - cThisCard.cAnimationInfo.dblAngleFacing) / cThisCard.cAnimationInfo.intMaxSteps;
						else
							cThisCard.cAnimationInfo.dblAngleTurning = -cThisCard.cAnimationInfo.dblAngleFacing / cThisCard.cAnimationInfo.intMaxSteps;

						cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
						cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(cThisCard.cAnimationInfo.ptEnd, cThisCard.cAnimationInfo.ptStart);
						cThisCard.cAnimationInfo.dblTravelInitialVelocity = cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.intMaxSteps;
					}
					cAnimateDealCards.intAnimationCounter++;
					cAnimateDealCards.udrTypeOrder = new classTypeOrder();

                    cAnimateDealCards.udrTypeOrder.lstRooms.Clear();// = new classCard[0];
					cAnimateDealCards.udrTypeOrder.lstSuspects.Clear();// = new classCard[0];
					cAnimateDealCards.udrTypeOrder.lstWeapons.AddRange(new classCard[0].ToList<classCard>());
					break;

				case 1:				 // animate cards
					bmpDealAnimationBoard = new Bitmap(bmpDealAnimationBoard_Base);
					bool bolGatherTopCardsAndExit = false;
					bool bolInsertIntoTypeOrder = (cAnimateDealCards.udrTypeOrder.lstSuspects.Count == 0);
					using (Graphics g = Graphics.FromImage(bmpDealAnimationBoard))
					{
						for (int intCardCounter = 0; intCardCounter < cAnimateDealCards.lstCardsCurrentAnimation.Count; intCardCounter++)
						{
							classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[intCardCounter];
							if (bolInsertIntoTypeOrder)
							{
								switch (cThisCard.eType)
								{
									case enuCardType.room:
										//Array.Resize<classCard>(ref cAnimateDealCards.udrTypeOrder.cRooms, cAnimateDealCards.udrTypeOrder.cRooms.Length + 1);
										//cAnimateDealCards.udrTypeOrder.cRooms[cAnimateDealCards.udrTypeOrder.cRooms.Length - 1] = cThisCard;
										cAnimateDealCards.udrTypeOrder.lstRooms.Add(cThisCard);
                                        break;

									case enuCardType.weapon:
										//Array.Resize<classCard>(ref cAnimateDealCards.udrTypeOrder.cWeapons, cAnimateDealCards.udrTypeOrder.cWeapons.Length + 1);
										//cAnimateDealCards.udrTypeOrder.cWeapons[cAnimateDealCards.udrTypeOrder.cWeapons.Length - 1] = cThisCard;
										cAnimateDealCards.udrTypeOrder.lstWeapons.Add(cThisCard);
										break;

									case enuCardType.Suspect:
										//Array.Resize<classCard>(ref cAnimateDealCards.udrTypeOrder.cSuspects, cAnimateDealCards.udrTypeOrder.cSuspects.Length + 1);
										//cAnimateDealCards.udrTypeOrder.cSuspects[cAnimateDealCards.udrTypeOrder.cSuspects.Length - 1] = cThisCard;
										cAnimateDealCards.udrTypeOrder.lstSuspects.Add(cThisCard);

                                        break;
								}
							}
							cThisCard.cAnimationInfo.intStep++;
							if (cThisCard.cAnimationInfo.intStep == cThisCard.cAnimationInfo.intMaxSteps)
								bolGatherTopCardsAndExit = true;

							double dblFractionDistanceTravelled = ((double)cThisCard.cAnimationInfo.intStep / (double)cThisCard.cAnimationInfo.intMaxSteps) * cThisCard.cAnimationInfo.dblTravelDistance;
							cThisCard.cAnimationInfo.ptPos = new Point(cThisCard.cAnimationInfo.ptStart.X + (int)(dblFractionDistanceTravelled * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle)),
																		 cThisCard.cAnimationInfo.ptStart.Y + (int)(dblFractionDistanceTravelled * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle)));
							cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

							while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
								cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;
							while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
								cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;

							int intImageIndex = (bolGatherTopCardsAndExit ? 0 : getImageIndex (cThisCard.cAnimationInfo.dblAngleFacing));
							Bitmap bmp = cThisCard.cBmp.getImage(intImageIndex);
							Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
							g.DrawImage(bmp, ptTL);
						}
					}
					picBoard.Image = bmpDealAnimationBoard; picBoard.Refresh();
					if (bolGatherTopCardsAndExit)
					{
						cAnimateDealCards.lstCardsCurrentAnimation.Clear();// = new classCard[0];
						eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
					}
					break;

			}
			setDelayTimer(100);
		}

		void AnimateDealCards_SortCardsIntoTypes()
		{
			if (cAnimateDealCards.intAnimationCounter % 8 == 0 && cAnimateDealCards.strCards.Length > 0)
			{
				// throw new card across the table
				string strThisCard = cAnimateDealCards.strCards.Substring(0, 2);
				cAnimateDealCards.strCards = cAnimateDealCards.strCards.Substring(2);
				enuCards eCard = (enuCards)Convert.ToInt16(strThisCard);
				//Array.Resize<classCard>(ref cAnimateDealCards.cCardsCurrentAnimation, cAnimateDealCards.cCardsCurrentAnimation.Length + 1);
				//cAnimateDealCards.cCardsCurrentAnimation[cAnimateDealCards.cCardsCurrentAnimation.Length - 1] = cCards[(int)eCard];
				cAnimateDealCards.lstCardsCurrentAnimation.Add(cCards[(int)eCard]);

                classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[cAnimateDealCards.lstCardsCurrentAnimation.Count - 1];
				Point ptStart = new Point(-50, -50);
				Point ptEnd = new Point(1, 1);

				switch (cThisCard.eType)
				{
					case enuCardType.room:
						ptEnd = new Point((int)(bmpBoard.Width * .9), (int)(bmpBoard.Height * .25));
						break;

					case enuCardType.Suspect:
						ptEnd = new Point((int)(bmpBoard.Width * .85), (int)(bmpBoard.Height * .75));
						break;

					case enuCardType.weapon:
						ptEnd = new Point((int)(bmpBoard.Width * .25), (int)(bmpBoard.Height * .75));
						break;
				}
				int intRangeError = (int)(bmpBoard.Height * .1);
				ptEnd = new Point((int)(ptEnd.X + (int)(rnd.NextDouble() * 1000) % intRangeError * Math.Cos(rnd.NextDouble() * Math.PI * 2)),
								  (int)(ptEnd.Y + (int)(rnd.NextDouble() * 1000) % intRangeError * Math.Sin(rnd.NextDouble() * Math.PI * 2)));

				cThisCard.cAnimationInfo.ptStart = ptStart;
				cThisCard.cAnimationInfo.ptEnd = ptEnd;
				cThisCard.cAnimationInfo.dblTravelAcceleration = -15;
				cThisCard.cAnimationInfo.dblTravelAngle = classMath.arcTan(ptEnd, ptStart);
				cThisCard.cAnimationInfo.dblTravelDistance = classMath.distanceBetweenTwoPoints(ptEnd, ptStart);
				cThisCard.cAnimationInfo.intMaxSteps = (int)Math.Ceiling(Math.Sqrt(-2.0 * cThisCard.cAnimationInfo.dblTravelDistance / cThisCard.cAnimationInfo.dblTravelAcceleration));
				cThisCard.cAnimationInfo.dblTravelInitialVelocity = -cThisCard.cAnimationInfo.dblTravelAcceleration * cThisCard.cAnimationInfo.intMaxSteps;
				cThisCard.cAnimationInfo.dblAngleTurning = rnd.NextDouble() * Math.PI * (1.0 / 8.0);
				cThisCard.cAnimationInfo.intStep = 0;
				cThisCard.cAnimationInfo.dblAngleTurningAttenuation = 0.95;
			}

			cAnimateDealCards.intAnimationCounter++;

			bmpDealAnimationBoard = new Bitmap(bmpDealAnimationBoard_Base);
			bool bolEndSortCards = true;

			using (Graphics g = Graphics.FromImage(bmpDealAnimationBoard))
			{
				for (int intCardCounter = 0; intCardCounter < cAnimateDealCards.lstCardsCurrentAnimation.Count; intCardCounter++)
				{
					classCard cThisCard = cAnimateDealCards.lstCardsCurrentAnimation[intCardCounter];
					if (cThisCard.cAnimationInfo.intStep < cThisCard.cAnimationInfo.intMaxSteps)
					{
						bolEndSortCards = false;

						cThisCard.cAnimationInfo.intStep++;

						double dblDistanceTravelled = cThisCard.cAnimationInfo.dblTravelInitialVelocity * cThisCard.cAnimationInfo.intStep + .5 * cThisCard.cAnimationInfo.dblTravelAcceleration * cThisCard.cAnimationInfo.intStep * cThisCard.cAnimationInfo.intStep;
						cThisCard.cAnimationInfo.ptPos = new Point(cThisCard.cAnimationInfo.ptStart.X + (int)(dblDistanceTravelled * Math.Cos(cThisCard.cAnimationInfo.dblTravelAngle)),
																	 cThisCard.cAnimationInfo.ptStart.Y + (int)(dblDistanceTravelled * Math.Sin(cThisCard.cAnimationInfo.dblTravelAngle)));

						cThisCard.cAnimationInfo.dblAngleFacing += cThisCard.cAnimationInfo.dblAngleTurning;

						while (cThisCard.cAnimationInfo.dblAngleFacing >= dblTwoPi)
							cThisCard.cAnimationInfo.dblAngleFacing -= dblTwoPi;
						while (cThisCard.cAnimationInfo.dblAngleFacing < 0)
							cThisCard.cAnimationInfo.dblAngleFacing += dblTwoPi;

						cThisCard.cAnimationInfo.dblAngleTurning *= cThisCard.cAnimationInfo.dblAngleTurningAttenuation;
					}

					int intImageIndex = getImageIndex(cThisCard.cAnimationInfo.dblAngleFacing);
					Bitmap bmp = cThisCard.cBmp.getImage(intImageIndex);
					Point ptTL = new Point(cThisCard.cAnimationInfo.ptPos.X - bmp.Width / 2, cThisCard.cAnimationInfo.ptPos.Y - bmp.Height / 2);
					g.DrawImage(bmp, ptTL);
				}
			}

			picBoard.Image = bmpDealAnimationBoard; picBoard.Refresh();
			if (bolEndSortCards && cAnimateDealCards.strCards.Length == 0)
			{
				eDealMode = (enuDealCardsMode)((int)eDealMode + 1);
				cAnimateDealCards.intAnimationCounter = 0;
			}
			setDelayTimer(10);
		}
		#endregion

		#region "animate summonses"
		void initSummonWeapon()
		{
			if (cWeapons[(int)cSuggestion.eWeapon].eRoom == cSuspects[intSuspectTurn].eRoom)
			{
				cWeapons[(int)cSuggestion.eWeapon].eRoom = cSuspects[intSuspectTurn].eRoom;
				eMode = enuMode.respondToSuggestion;
				drawBoard();
				DrawSuggestingSuspect(); writeSuggestion();
				ProveSuggestion();
				return;
			}

			cAnimationSummonWeapon.ptStart = getWeaponGraphicPositionInRoom(cSuggestion.eWeapon, cWeapons[(int)cSuggestion.eWeapon].eRoom);
			cAnimationSummonWeapon.ptEnd = getWeaponGraphicPositionInRoom(cSuggestion.eWeapon, cSuspects[intSuspectTurn].eRoom);
			cAnimationSummonWeapon.intStepCounter = 0;
			cAnimationSummonWeapon.bolMoveToCenterOfScreen = true;
			cAnimationSummonWeapon.intMaxSteps = 12;
			cAnimationSummonWeapon.dblAngleBetweenPoints = classMath.arcTan((double)(cAnimationSummonWeapon.ptEnd.X - cAnimationSummonWeapon.ptStart.X), (double)(cAnimationSummonWeapon.ptEnd.Y - cAnimationSummonWeapon.ptStart.Y));
			cAnimationSummonWeapon.dblDistanceBetweenPoints = Math.Sqrt(Math.Pow(cAnimationSummonWeapon.ptEnd.X - cAnimationSummonWeapon.ptStart.X, 2) + Math.Pow(cAnimationSummonWeapon.ptEnd.Y - cAnimationSummonWeapon.ptStart.Y, 2)) / 2;

			cAnimationSummonWeapon.ptMidway = new Point((int)(cAnimationSummonWeapon.ptStart.X + cAnimationSummonWeapon.dblDistanceBetweenPoints * Math.Cos(cAnimationSummonWeapon.dblAngleBetweenPoints)),
												  (int)(cAnimationSummonWeapon.ptStart.Y + cAnimationSummonWeapon.dblDistanceBetweenPoints * Math.Sin(cAnimationSummonWeapon.dblAngleBetweenPoints)));
			drawBoard();
			bmpGameBoard = (Bitmap)picBoard.Image;
			setDelayTimer(40);
		}

		void animateSummonWeapon()
		{
			cAnimationSummonWeapon.intStepCounter++;
			if (cAnimationSummonWeapon.intStepCounter < cAnimationSummonWeapon.intMaxSteps)
			{
				Bitmap bmpTemp = new Bitmap(bmpGameBoard);

				using (Graphics g = Graphics.FromImage(bmpTemp))
				{
					double dblFractionDistance = ((double)cAnimationSummonWeapon.intStepCounter / (double)cAnimationSummonWeapon.intMaxSteps);
					double dblPartDistance = cAnimationSummonWeapon.dblDistanceBetweenPoints * dblFractionDistance;
					Point pt = new Point((int)(cAnimationSummonWeapon.ptStart.X + dblPartDistance * Math.Cos(cAnimationSummonWeapon.dblAngleBetweenPoints)),
										 (int)(cAnimationSummonWeapon.ptStart.Y + dblPartDistance * Math.Sin(cAnimationSummonWeapon.dblAngleBetweenPoints)));
					int intTotalSizeDifference = (bmpWeapons_Board[0].Width - 35);
					double dblFractionSize = ((double)cAnimationSummonWeapon.intStepCounter / (double)cAnimationSummonWeapon.intMaxSteps);
					if (!cAnimationSummonWeapon.bolMoveToCenterOfScreen)
					{
						dblFractionSize = ((double)(cAnimationSummonWeapon.intMaxSteps - cAnimationSummonWeapon.intStepCounter) / (double)cAnimationSummonWeapon.intMaxSteps);
					}
					Size sz = new Size((int)(intTotalSizeDifference * dblFractionSize) + 35, (int)(intTotalSizeDifference * dblFractionSize) + 35);

					Point ptTL = new Point(pt.X - sz.Width / 2, pt.Y - sz.Height / 2);

					Rectangle recDest = new Rectangle(ptTL, sz);
					Rectangle recSrc = new Rectangle(0, 0, bmpWeapons_Board[(int)cSuggestion.eWeapon].Width, bmpWeapons_Board[(int)cSuggestion.eWeapon].Height);

					g.DrawImage(bmpWeapons_Board[(int)cSuggestion.eWeapon], recDest, recSrc, GraphicsUnit.Pixel);

				}
				picBoard.Image = bmpTemp; picBoard.Refresh();
				setDelayTimer(40);
			}
			else
			{
				if (cAnimationSummonWeapon.bolMoveToCenterOfScreen)
				{
					cAnimationSummonWeapon.ptStart = cAnimationSummonWeapon.ptMidway;
					cAnimationSummonWeapon.intStepCounter = 0;
					cAnimationSummonWeapon.bolMoveToCenterOfScreen = false;
					cAnimationSummonWeapon.intMaxSteps = 12;
					setDelayTimer(40);
				}
				else
				{
					cWeapons[(int)cSuggestion.eWeapon].eRoom = cSuspects[intSuspectTurn].eRoom;
					eMode = enuMode.respondToSuggestion;
					drawBoard();
					DrawSuggestingSuspect(); writeSuggestion();
					ProveSuggestion();
				}
			}
		}

		void initSummonSuspect()
		{
			if (cSuspects[(int)cSuggestion.eSuspect].eRoom == cSuspects[intSuspectTurn].eRoom)
			{
				eMode = enuMode.animateSummonWeapon;
				return;
			}

			// set summoned suspect can suggest
			cSuspects[(int)cSuggestion.eSuspect].bolCanSuggest = true;
			cSuspects[(int)cSuggestion.eSuspect].bolHasNotYetMadeASuggestionThisTurn = false;

			if (cSuspects[(int)cSuggestion.eSuspect].eRoom == enuRooms.tiles)
				cAnimationSummonSuspect.ptStart = getTileCenter(cSuspects[(int)cSuggestion.eSuspect].ptTile);
			else if (cSuspects[(int)cSuggestion.eSuspect].eRoom == enuRooms.start)
				cAnimationSummonSuspect.ptStart = new Point(cSuspects[(int)cSuggestion.eSuspect].ptFirstTile.X * 28 + ptBoardTL.X, cSuspects[(int)cSuggestion.eSuspect].ptFirstTile.Y * 28 + ptBoardTL.Y);
			else
				cAnimationSummonSuspect.ptStart = getPieceGraphicPositionInRoom(cSuggestion.eSuspect, cSuspects[(int)cSuggestion.eSuspect].eRoom);

			cAnimationSummonSuspect.ptEnd = getPieceGraphicPositionInRoom(cSuggestion.eSuspect, cSuspects[intSuspectTurn].eRoom);

			cAnimationSummonSuspect.intStepCounter = 0;
			cAnimationSummonSuspect.bolMoveToCenterOfScreen = true;
			cAnimationSummonSuspect.intMaxSteps = 12;
			cAnimationSummonSuspect.dblAngleBetweenPoints = classMath.arcTan((double)(cAnimationSummonSuspect.ptEnd.X - cAnimationSummonSuspect.ptStart.X), (double)(cAnimationSummonSuspect.ptEnd.Y - cAnimationSummonSuspect.ptStart.Y));
			cAnimationSummonSuspect.dblDistanceBetweenPoints = Math.Sqrt(Math.Pow(cAnimationSummonSuspect.ptEnd.X - cAnimationSummonSuspect.ptStart.X, 2) + Math.Pow(cAnimationSummonSuspect.ptEnd.Y - cAnimationSummonSuspect.ptStart.Y, 2)) / 2;

			cAnimationSummonSuspect.ptMidway = new Point((int)(cAnimationSummonSuspect.ptStart.X + cAnimationSummonSuspect.dblDistanceBetweenPoints * Math.Cos(cAnimationSummonSuspect.dblAngleBetweenPoints)),
												   (int)(cAnimationSummonSuspect.ptStart.Y + cAnimationSummonSuspect.dblDistanceBetweenPoints * Math.Sin(cAnimationSummonSuspect.dblAngleBetweenPoints)));
			drawBoard();
			setDelayTimer(40);
		}

		void animateSummonSuspect()
		{
			cAnimationSummonSuspect.intStepCounter++;
			if (cAnimationSummonSuspect.intStepCounter < cAnimationSummonSuspect.intMaxSteps)
			{
				Bitmap bmpTemp = new Bitmap(bmpGameBoard);

				using (Graphics g = Graphics.FromImage(bmpTemp))
				{
					double dblFractionDistance = ((double)cAnimationSummonSuspect.intStepCounter / (double)cAnimationSummonSuspect.intMaxSteps);
					double dblPartDistance = cAnimationSummonSuspect.dblDistanceBetweenPoints * dblFractionDistance;
					Point pt = new Point((int)(cAnimationSummonSuspect.ptStart.X + dblPartDistance * Math.Cos(cAnimationSummonSuspect.dblAngleBetweenPoints)),
										 (int)(cAnimationSummonSuspect.ptStart.Y + dblPartDistance * Math.Sin(cAnimationSummonSuspect.dblAngleBetweenPoints)));
					int intTotalSizeDifference = (bmpSuspects[0].Width - 35);
					double dblFractionSize = ((double)cAnimationSummonSuspect.intStepCounter / (double)cAnimationSummonSuspect.intMaxSteps);
					if (!cAnimationSummonSuspect.bolMoveToCenterOfScreen)
					{
						dblFractionSize = ((double)(cAnimationSummonSuspect.intMaxSteps - cAnimationSummonSuspect.intStepCounter) / (double)cAnimationSummonSuspect.intMaxSteps);
					}
					Size sz = new Size((int)(intTotalSizeDifference * dblFractionSize) + 35, (int)(intTotalSizeDifference * dblFractionSize) + 35);

					Point ptTL = new Point(pt.X - sz.Width / 2, pt.Y - sz.Height / 2);

					Rectangle recDest = new Rectangle(ptTL, sz);
					Rectangle recSrc = new Rectangle(0, 0, bmpSuspects[(int)cSuggestion.eSuspect].Width, bmpSuspects[(int)cSuggestion.eSuspect].Height);

					g.DrawImage(bmpSuspects[(int)cSuggestion.eSuspect], recDest, recSrc, GraphicsUnit.Pixel);

				}
				picBoard.Image = bmpTemp; picBoard.Refresh();
				setDelayTimer(40);
			}
			else
			{
				if (cAnimationSummonSuspect.bolMoveToCenterOfScreen)
				{
					cAnimationSummonSuspect.ptStart = cAnimationSummonSuspect.ptMidway;
					cAnimationSummonSuspect.intStepCounter = 0;
					cAnimationSummonSuspect.bolMoveToCenterOfScreen = false;
					cAnimationSummonSuspect.intMaxSteps = 12;
					setDelayTimer(40);
				}
				else
				{
					cSuspects[(int)cSuggestion.eSuspect].eRoom = cSuspects[intSuspectTurn].eRoom;
					eMode = enuMode.animateSummonWeapon;
				}
			}
		}
		#endregion
			
		#region "debug"
		public void clearDebug()
		{
			System.IO.File.WriteAllText(strDebugFilename, "");
		}

		public void appendDebug(string strMessage)
		{
			strDebugFilename = strDebugFilename.ToUpper().Replace("DEBUG", "RELEASE");
			string strStatistics = "\r\n ----  statistics ---";
			string strOriginal = "";
			if (System.IO.File.Exists(strDebugFilename))
				strOriginal = System.IO.File.ReadAllText(strDebugFilename);
			int intCutChr = strOriginal.IndexOf(strStatistics);
			if (intCutChr >= 0)
				strOriginal = strOriginal.Substring(0, intCutChr - 1);
			strOriginal += "\r\n" + strMessage + "(" + DateTime.Now.ToString() + ")";

			string strCopy = strOriginal;
			string strCorrectlyIn = "Correctly in";
			intCutChr = strCopy.IndexOf(strCorrectlyIn);
			int[] intTurns = new int[100];
			int intNumGames = 0;
			while (intCutChr > 0)
			{
				intNumGames++;
				strCopy = strCopy.Substring(intCutChr + strCorrectlyIn.Length).Trim();
				intCutChr = strCopy.IndexOf(" ");
				if (intCutChr > 0)
				{
					int intThisNumTurn = Convert.ToInt16(strCopy.Substring(0, intCutChr));
					if (intThisNumTurn >= 0 && intThisNumTurn < intTurns.Length)
						intTurns[intThisNumTurn]++;
				}
				intCutChr = strCopy.IndexOf(strCorrectlyIn);
			}
			strOriginal += strStatistics;
			for (int intNumTurnsCounter = 0; intNumTurnsCounter < intTurns.Length; intNumTurnsCounter++)
			{
				if (intTurns[intNumTurnsCounter] > 0)
				{
					strOriginal += "\r\nsolved in " + intNumTurnsCounter.ToString() + " turns " + intTurns[intNumTurnsCounter].ToString() + " time" + (intTurns[intNumTurnsCounter] == 1 ? "" : "s") + " out of " + intNumGames.ToString() + " %" + ((double)intTurns[intNumTurnsCounter] / (double)intNumGames * 100.0).ToString("f2");
				}
			}

			System.IO.File.WriteAllText(strDebugFilename, strOriginal);
		}
		#endregion
				
		#region "helper functions"
		Point getTileCenter(Point ptTile)
		{
			return new Point(ptBoardTL.X + ptTile.X * 28 + 14, ptBoardTL.Y + ptTile.Y * 28 + 14);
		}

		public bool floorTileIsFree(Point pt)
		{
			foreach (classSuspect cS in cSuspects)
				if (cS.eRoom == enuRooms.tiles && cS.ptTile == pt)
					return false;
			return true;
		}

		bool validTile(Point pt)
		{
			return (pt.X >= 0 && pt.Y >= 0 && pt.X < sz.Width && pt.Y < sz.Height);
		}

		Point getPieceGraphicPositionInRoom(enuSuspects eSuspect) { return getPieceGraphicPositionInRoom(eSuspect, cSuspects[(int)eSuspect].eRoom); }
		Point getPieceGraphicPositionInRoom(enuSuspects eSuspect, enuRooms eRoom)
		{
			double dblAlpha = (-Math.PI / 2 + Math.PI / 3.0) - (double)(int)eSuspect * (Math.PI / 3.0);

			Point	ptRoomCenter =getRoomCenter(eRoom);
			double dblRadius = 40;
			Point ptPieceCenter = new Point(ptRoomCenter.X + (int)(dblRadius * Math.Cos(dblAlpha)), ptRoomCenter.Y + (int)(dblRadius * Math.Sin(dblAlpha)));
			return ptPieceCenter;
		}

		Point getWeaponGraphicPositionInRoom(enuWeapons eWeapon) { return getWeaponGraphicPositionInRoom(eWeapon, cWeapons[(int)eWeapon].eRoom); }
		Point getWeaponGraphicPositionInRoom(enuWeapons eWeapon, enuRooms eRoom)
		{
			double dblAlpha = (double)(int)eWeapon * (Math.PI / 3.0);
			Point ptRoomCenter = getRoomCenter(eRoom);
			double dblRadius = 40;
			Point ptWeaponCenter = new Point(ptRoomCenter.X + (int)(dblRadius * Math.Cos(dblAlpha)), ptRoomCenter.Y + (int)(dblRadius * Math.Sin(dblAlpha)));
			return ptWeaponCenter;
		}

		public Bitmap getTextImage(string strText, Font fnt)
		{ return getTextImage(strText, fnt, Color.Black); }
		public Bitmap getTextImage(string strText, Font fnt, Color clr)
		{
			// use lblSize's 'autosize' mode to measure required output bitmap size
			lblSizer.Text = strText;
			lblSizer.Font = fnt;

			Rectangle quoteRect = new Rectangle(0,
												0,
												lblSizer.Width
													+ (fnt.Italic ? (int)(fnt.Height * .3) : 0)
													+ (fnt.Bold ? (int)(fnt.Height * .2) : 0),
												lblSizer.Height + 5);

			// create a new bitmap that contains both the quote and the author text
			Bitmap bmpTemp = new Bitmap(quoteRect.Width, quoteRect.Height);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				// set the text rendering characteristics
				g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

				// draw the text
				TextRenderer.DrawText(g,
									  strText,
									  fnt,
									  new Point(quoteRect.X + 5,
												quoteRect.Y),
									  clr,
									  Color.White,
									  TextFormatFlags.Default | TextFormatFlags.NoPrefix);
			}
			bmpTemp.MakeTransparent(Color.White);
			int intLeftCut = 7;
			int intWidth = bmpTemp.Width - intLeftCut;
			if (intWidth <= 0)
				intWidth = 1;
			Bitmap bmpRetVal = new Bitmap(intWidth, bmpTemp.Height);
			using (Graphics g = Graphics.FromImage(bmpRetVal))
			{
				Rectangle rectDest = new Rectangle(0, 0, quoteRect.Width, bmpRetVal.Height);
				Rectangle rectSrc = new Rectangle(intLeftCut, 0, quoteRect.Width, bmpRetVal.Height);
				g.DrawImage(bmpTemp, rectDest, rectSrc, GraphicsUnit.Pixel);
			}

			return bmpRetVal;
		}
		Point getRoomCenter(enuRooms eRoom)
		{
			if (ptRoomCenters == null || true)
			{
				ptRoomCenters = new Point[(int)enuRooms._numRooms + 1];

				for (enuRooms eRoomCounter = (enuRooms)0; eRoomCounter <= enuRooms._numRooms; eRoomCounter++)
				{
					switch (eRoomCounter)
					{
						case enuRooms.Study:
							ptRoomCenters[(int)eRoomCounter] = new Point(110, 60);
							break;

						case enuRooms.Hall:
							ptRoomCenters[(int)eRoomCounter] = new Point(358, 100);
							break;

						case enuRooms.Lounge:
							ptRoomCenters[(int)eRoomCounter] = new Point(596, 82);
							break;

						case enuRooms.DiningRoom:
							ptRoomCenters[(int)eRoomCounter] = new Point(591, 332);
							break;

						case enuRooms.Kitchen:
							ptRoomCenters[(int)eRoomCounter] = new Point(610, 580);
							break;

						case enuRooms.BallRoom:
							ptRoomCenters[(int)eRoomCounter] = new Point(367, 564);
							break;

						case enuRooms.Conservatory:
							ptRoomCenters[(int)eRoomCounter] = new Point(103, 611);
							break;

						case enuRooms.BilliardRoom:
							ptRoomCenters[(int)eRoomCounter] = new Point(106, 409);
							break;

						case enuRooms.Library:
							ptRoomCenters[(int)eRoomCounter] = new Point(122, 242);
							break;

						case enuRooms._numRooms:
							ptRoomCenters[(int)eRoomCounter] = new Point(349, 328);
							break;
					}
				}
			}

			return ptRoomCenters[(int)eRoom];
		}

		public enuRooms getERoomFromCard(enuCards eRoomCard)
		{
			try
			{
				if (classCard.eCardIsARoom(eRoomCard))
					return (enuRooms)((int)eRoomCard - (int)enuSuspects._numSuspects - (int)enuWeapons._numWeapons);
			}
			catch (Exception)
			{

			}
			return enuRooms._numRooms;
		}

		public enuCards getCardFromERoom(enuRooms eRoom)
		{
			string strERoom = eRoom.ToString();
			for (enuCards eCardCounter = (enuCards)0; eCardCounter < enuCards._numCards; eCardCounter++)
				if (eCardCounter.ToString() == strERoom)
					return eCardCounter;
			return enuCards._numCards;
		}

		public enuSuspects getESuspectFromCard(enuCards eSuspectCard)
		{
			try
			{
				if (classCard.eCardIsASuspect(eSuspectCard))
					return (enuSuspects)((int)eSuspectCard);
			}
			catch (Exception)
			{

			}
			return enuSuspects._numSuspects;
		}

		public enuCards getCardFromESuspect(enuSuspects eSuspect)
		{
			string streSuspect = eSuspect.ToString();
			for (enuCards eCardCounter = (enuCards)0; eCardCounter < enuCards._numCards; eCardCounter++)
				if (eCardCounter.ToString() == streSuspect)
					return eCardCounter;
			return enuCards._numCards;
		}

		public enuWeapons getEWeaponFromCard(enuCards eWeaponCard)
		{
			try
			{
				if (classCard.eCardIsAWeapon(eWeaponCard))
					return (enuWeapons)((int)eWeaponCard - (int)enuSuspects._numSuspects);
			}
			catch (Exception) { }
			return enuWeapons._numWeapons;
		}

		public enuCards getCardFromEWeapon(enuWeapons eWeapon)
		{
			string streWeapon = eWeapon.ToString();
			for (enuCards eCardCounter = (enuCards)0; eCardCounter < enuCards._numCards; eCardCounter++)
				if (eCardCounter.ToString() == streWeapon)
					return eCardCounter;
			return enuCards._numCards;
		}

		public enuDir getOppDir(enuDir dirIn) { return (enuDir)(((int)dirIn + 2) % 4); }

		void appendCardList(ref enuCards[] eCardList, enuCards eCard)
		{
			if (eCardList == null)
				eCardList = new enuCards[0];

			Array.Resize<enuCards>(ref eCardList, eCardList.Length + 1);
			eCardList[eCardList.Length - 1] = eCard;
		}

		bool eCardIsInListeCards(ref classCard[] cCardList, enuCards eCard)
		{
			for (int intCardCounter = 0; intCardCounter < cCardList.Length; intCardCounter++)
				if (cCardList[intCardCounter].eCardName == eCard)
					return true;
			return false;
		}

		public Point movePoint(Point pt, enuDir dir)
		{
			switch (dir)
			{
				case enuDir.north:
					if (pt.Y < 1)
						return new Point(-1, -1);
					else
						return new Point(pt.X, pt.Y - 1);

				case enuDir.east:
					if (pt.X > sz.Width - 1)
						return new Point(-1, -1);
					else
						return new Point(pt.X + 1, pt.Y);

				case enuDir.south:
					if (pt.Y > sz.Height - 1)
						return new Point(-1, -1);
					else
						return new Point(pt.X, pt.Y + 1);

				case enuDir.west:
					if (pt.X < 1)
						return new Point(-1, -1);
					else
						return new Point(pt.X - 1, pt.Y);
			}
			return new Point(-1, -1);
		}

		bool RoomDoor(ref classRoom cRoom, Point pt)
		{
			for (int intDoorCounter = 0; intDoorCounter < cRoom.ptDoors.Length; intDoorCounter++)
			{
				if (cRoom.ptDoors[intDoorCounter] == pt)
					return true;
			}
			return false;
		}
		void setPtMouseTile(int intX, int intY)
		{
			ptMouseTile = new Point((intX - ptBoardTL.X) / 28, (intY - ptBoardTL.Y) / 28);
		}

		enuSuspects getMouseOverAISuspect(Point pt)
		{
			if (pt.Y > 39 && pt.Y < 64)
			{ // Col.Mustard
				return enuSuspects.ColMustard;
			}
			else if (pt.Y > 65 && pt.Y < 90)
			{ // Prof Plum
				return enuSuspects.ProfPlum;
			}
			else if (pt.Y > 91 && pt.Y < 118)
			{ // Rev.Green
				return enuSuspects.RevGreen;
			}
			else if (pt.Y > 119 && pt.Y < 144)
			{ // Mrs.Peacock
				return enuSuspects.MrsPeacock;
			}
			else if (pt.Y > 145 && pt.Y < 170)
			{ // Miss Scarlet
				return enuSuspects.MissScarlet;
			}
			else if (pt.Y > 171 && pt.Y < 196)
			{ // Mrs.White
				return enuSuspects.MrsWhite;
			}
			else
				return enuSuspects._numSuspects;
		}

		#endregion

		public enuMode eMode
		{
			get { return _eMode; }
			set
			{
				_eMode = value;
				switch (_eMode)
				{
					case enuMode.chooseCharacter:
						//pnlControls.Enabled = false;
						cLibPicTrayWeapons.Visible = false;
						break;

					case enuMode.Accuse:
						//pnlControls.Enabled = false;
						if (cSuspects[intSuspectTurn].bolPlayerControlled)
							ShowAccuseOptions();
						break;

					case enuMode.Suggest:
						//pnlControls.Enabled = false;
						Suggest();
						break;

					case enuMode.animateIntroduction:
						initAnimateIntroduction();
						break;
						
					case enuMode.animateSummonSuspect:
						initSummonSuspect();
						break;

					case enuMode.animateSummonWeapon:
						initSummonWeapon();
						break;

					case enuMode.respondToSuggestion:
						break;

					case enuMode.animateSecretPassage:
						initAnimateSecretPassage();
						break;

					case enuMode.warnPlayerNextTurn:
						btnChooseSuspect.Visible =
							cLibPicTraySuspects.Visible =
							cLibPicTrayWeapons.Visible = false;
                        //btnEndTurn.Enabled = false;
                        EndTurnButtonEnabled = true;
                        //btnSuggest.Enabled = cSuspects[intSuspectTurn].bolCanSuggest;
                        SuggestButtonEnabled = cSuspects[intSuspectTurn].bolCanSuggest;
                        grbControls.BackColor = clrSuspects[intSuspectTurn]; grbControls.Refresh();
						//pnlControls.Enabled = false;
						//btnRollDie.PulseColor
						//	= grbControls.ForeColor = Color.FromArgb((grbControls.BackColor.A + 126) % 255,
						//											 (grbControls.BackColor.R + 126) % 255,
						//											 (grbControls.BackColor.G + 126) % 255,
						//											 (grbControls.BackColor.B + 126) % 255);

						grbControls.Text = cSuspects[intSuspectTurn].eName.ToString();
						picBoard.SendToBack(); picBoard.Refresh();
						drawBoard();
						warnPlayerWhoseTurnItIs();

						setButtonsEnabled();
						break;

					case enuMode.beginTurn:
                        //btnRollDie.Enabled = true;
                        RollDieButtonEnabled = true;
						grbControls.Visible = true;
						eraseWarnPlayerWhoseTurnItIs();
						picBoard.SendToBack();
						picNotebook.Refresh();
						//pnlControls.Enabled = true;
						cSuspects[intSuspectTurn].allowSecretPassage();
						drawBoard();
						if (!cSuspects[intSuspectTurn].bolPlayerControlled)
						{
							cSuspects[intSuspectTurn].playTurn();
						}
						else
							eMode = enuMode.playerTurnIdle;
						break;

					case enuMode.endTurn:
						cSuspects[intSuspectTurn].bolCanSuggest = false;
						cSuspects[intSuspectTurn].resetAllowableMoves();
						if (!cSuspects[intSuspectTurn].bolPlayerControlled)
						{
							if (eMode != enuMode.respondToSuggestion && eMode != enuMode.Suggest)
							{
								drawBoard();
								nextPlayer();
							}
						}
						else
							nextPlayer();
						break;

					case enuMode.rollDie_animate:
						setDelayTimer(5);
						break;

					case enuMode.rollDie_end:
						rollDie_End();
						break;

					case enuMode.dealCards:
						btnChooseSuspect.Visible =
							cLibPicTraySuspects.Visible =
							cLibPicTrayWeapons.Visible = false;
						cAnimateDealCards.bolQuitAnimation = false;
						eDealMode = (enuDealCardsMode)0;
						eDealMode = (enuDealCardsMode)1;
						break;						
				}
			}
		}

		void setButtonsEnabled()
		{
			//grbControls.Enabled = true;
			//pnlControls.Enabled = true;
			_btnAccuse.Enabled = AccuseButtonEnabled;
			_btnEndTurn.Enabled = EndTurnButtonEnabled;
			_btnRollDie.Enabled = RollDieButtonEnabled;
			_btnSuggest.Enabled = SuggestButtonEnabled;
			
		}


        bool _bolSuggestButtonEnabled = false;
        public bool SuggestButtonEnabled
        {
            get { return _bolSuggestButtonEnabled; }
            set 
			{ 
				_bolSuggestButtonEnabled = value;
				_btnSuggest.Enabled = value;
			}
        }
        bool _bolAccuseButtonEnabled = false;
        public bool AccuseButtonEnabled
        {
            get { return _bolAccuseButtonEnabled; }
            set 
			{ 
				_bolAccuseButtonEnabled = value;
				_btnAccuse.Enabled = value;
			}
        }
        bool _bolEndTurnButtonEnabled = false;
        public bool EndTurnButtonEnabled
        {
            get { return _bolEndTurnButtonEnabled; }
            set 
			{
				_bolEndTurnButtonEnabled = value;
				_btnEndTurn.Enabled = value;
			}
        }
        bool _bolRollDieButtonEnabled = false;
        public bool RollDieButtonEnabled
        {
            get { return _bolRollDieButtonEnabled; }
            set 
			{ 
				_bolRollDieButtonEnabled = value;
				_btnRollDie.Enabled = value;
			}
        }


        void initResponseBubble()
		{
			bmpResponseBubble = new Bitmap(bmpSuggestionBubble, new Size(400, 120));
			bmpResponseBubble.RotateFlip(RotateFlipType.RotateNoneFlipX);
			bmpResponseBubble.MakeTransparent();
		}

		void PlayerChoosesCardToShowBannerClick()
		{
			autoProceedEnabled = false;

			picBoard.Image = bmpSuggestionBoard; picBoard.Refresh();

			eMode = enuMode.respondToSuggestion;
			ProveSuggestion_ReceiveResponse(getPlayerSuspect().eName, enuCards.NoCardShown);
		}

		public void btnMakeSuggestion_OK_click()
		{
			autoProceedEnabled = false;
			cLibPicTraySuspects.Visible = false;
			cLibPicTrayWeapons.Visible = false;
			eMode = enuMode.respondToSuggestion;
			cButtons[(int)enuButtons.MakeSuggestion_Cancel].erase();
			cButtons[(int)enuButtons.MakeSuggestion_Ok].erase();
			eMode = enuMode.animateSummonSuspect;
		}

		void btnMakeSuggestion_Cancel_click()
		{
			cSuspects[intSuspectTurn].bolCanSuggest = true;
			cLibPicTraySuspects.Visible = false;
			cLibPicTrayWeapons.Visible = false;
            //btnSuggest.Enabled = pnlControls.Enabled = true;
            SuggestButtonEnabled = true;
			eMode = enuMode.playerTurnIdle;
			drawBoard();
		}

		void btnRespondSuggestion_OK_click()
		{
			autoProceedEnabled = false;
			if (cSuggestionAnimation.intProveSuggestionCycleCounter < (int)enuSuspects._numSuspects)
				ProveSuggestion_CycleThroughSuspects();
			else
			{
				drawBoard();
				//pnlControls.Enabled = true;
				if (cSuspects[intSuspectTurn].bolPlayerControlled)
					eMode = enuMode.playerTurnIdle;
				else
				{
					if (cSuspects[intSuspectTurn].bolMustMove)
					{
						eMode = enuMode.AISuggestionComplete;
						cSuspects[intSuspectTurn].playTurn();
					}
					else
						eMode = enuMode.endTurn;
				}
			}
		}

		bool buttonPressed()
		{
			if (eMode == enuMode.playerChoosesCardToShow)
			{
				if (ptMousePos.X > recBannerButton.Left && ptMousePos.X < recBannerButton.Left + recBannerButton.Width)
					if (ptMousePos.Y > recBannerButton.Top && ptMousePos.Y < recBannerButton.Top + recBannerButton.Height)
					{
						if (btnPlayerResponse[0].Visible)
							return false; // there are cards to show ignore this click
						PlayerChoosesCardToShowBannerClick();
						return true;
					}
			}

			if (cButtons[(int)enuButtons.MouseOver] == null)
				return false;

			switch (eMode)
			{
				case enuMode.Suggest:
					if (cButtons[(int)enuButtons.MouseOver] == cButtons[(int)enuButtons.MakeSuggestion_Ok])
					{
						btnMakeSuggestion_OK_click();
						return true;
					}
					else if (cButtons[(int)enuButtons.MouseOver] == cButtons[(int)enuButtons.MakeSuggestion_Cancel]
							 && cSuspects[intSuspectTurn].bolPlayerControlled)
					{
						btnMakeSuggestion_Cancel_click();
						return true;
					}
					break;

				case enuMode.respondToSuggestion:
					if (cButtons[(int)enuButtons.MouseOver] == cButtons[(int)enuButtons.RespondToSuggestion_Ok])
					{
						btnRespondSuggestion_OK_click();
					}
					break;
			}

			return false;
		}		

		void pic_MouseClick(object sender, MouseEventArgs e)
		{ // this is the event-handler called when player clicks picBoard or picNote
			if ((eMode == enuMode.showAllowableMoves && !cSuspects[intSuspectTurn].bolPlayerControlled)
			 || (eMode == enuMode.showAllowableMoves && !validTile(ptMouseTile))
			 || bolDisableMouseClickBoard
				|| !bolInit)
				return;
			picMouseClick(sender, e);
		}

		public void picMouseClick(object sender, MouseEventArgs e)
		{ // this is the function which the AI calls to activate a move
			if (!bolInit)
				return;
			if (eMode == enuMode.dealCards || eMode == enuMode.idle)
			{
				cAnimateDealCards.bolQuitAnimation = true;
				return;
			}

			if (buttonPressed())
				return;

			setPtMouseTile(e.X, e.Y);

			if (!validTile(ptMouseTile))
				return;

			bolDisableMouseClickBoard = true;
			classSuspect cSus = cSuspects[intSuspectTurn];

			if (cSus.cSEAllowableMoves[ptMouseTile.X, ptMouseTile.Y] != null)
			{
				if (classSuspect.cFloor[ptMouseTile.X, ptMouseTile.Y].eType == enuFloor.door
					&& classSuspect.cFloor[ptMouseTile.X, ptMouseTile.Y].dirDoor == enuDir.secretPassage)
				{
					eMode = enuMode.animateSecretPassage;
					bolDisableMouseClickBoard = false;
					return;
				}
				else
				{
                    //btnRollDie.Enabled = false;
                    RollDieButtonEnabled= false;
                    //btnEndTurn.Enabled = true;
                    EndTurnButtonEnabled = true;
					if (cSus.eRoom == enuRooms.start)
					{
						cSus.eRoom = enuRooms.tiles;
						cSus.ptTile = cSus.ptFirstTile;
					}

					// animate suspect walking
					// calculate path from current tile to clicked-tile by working backwards
					cMoveAnimationInfo.strPath = "";
					classSearchElement cSE = cSus.cSEAllowableMoves[ptMouseTile.X, ptMouseTile.Y];
					classRoom cRoom = null;
					if (cSus.eRoom < enuRooms._numRooms)
						cRoom = cRooms[(int)cSus.eRoom];
					Point ptNext = cSus.ptTile;
					enuDir dirStep;
					while (cSE != null
						   && ((cSus.eRoom == enuRooms.tiles && cSE != cSus.cSEAllowableMoves[cSus.ptTile.X, cSus.ptTile.Y]) // suspect is on tile and tile has been reached
							  || (cSus.eRoom < enuRooms._numRooms && !RoomDoor(ref cRoom, cSE.pt)))) // suspect is in a room and one of the room's doors has been reached
					{
						dirStep = getOppDir(cSE.SrcDir);
						cMoveAnimationInfo.strPath = ((int)dirStep).ToString() + cMoveAnimationInfo.strPath;
						ptNext = movePoint(cSE.pt, cSE.SrcDir);
						cSE = cSus.cSEAllowableMoves[ptNext.X, ptNext.Y];
					}

					if (cSus.eRoom < enuRooms._numRooms) // suspect is in a room -> ptNext points to door (not included in allowable steps)
					{
						cSus.ptTile = ptNext;
						cSus.eRoom = enuRooms.tiles;
					}

					eMode = enuMode.animateMove;

					cSus.resetAllowableMoves();
					drawBoard();

					cMoveAnimationInfo.bmpAnimationBoard = new Bitmap(picBoard.Image);
					cMoveAnimationInfo.ptImage = new Point(ptBoardTL.X + cSus.ptTile.X * 28 + 2, ptBoardTL.Y + cSus.ptTile.Y * 28 + 2);
					cMoveAnimationInfo.recPiece = new Rectangle(cMoveAnimationInfo.ptImage.X, cMoveAnimationInfo.ptImage.Y, 28, 28);
					cMoveAnimationInfo.ptMouseTile = ptMouseTile;

					startMoveAnimation();
					return;
				}
				//drawBoard();
			}
			bolDisableMouseClickBoard = false;
		}

		void Pic_MouseMove(object sender, MouseEventArgs e)
		{
            if (!bolInit)
				return;
			if (bolDisableMouseClickBoard)
				return;
			ptMousePos = new Point(e.X, e.Y);
			setPtMouseTile(e.X, e.Y);
			cButtons[(int)enuButtons.MouseOver] = getMouseOverButton(new Point(e.X, e.Y));
		}
		void picBoard_MouseEnter(object sender, EventArgs e)
		{

			//btnWarnPlayerWhoseTurnItIs_Click((object)btnWarnPlayerWhoseTurnItIs, new EventArgs());
			//RollDieButtonEnabled = true;
			//setButtonsEnabled();
			if (!bolInit)
				return;
			hideOptions();
		}

		#region "animate Move"
		void startMoveAnimation()
		{
			cMoveAnimationInfo.intAnimationStep = 4;
			cMoveAnimationInfo.cSus = cSuspects[intSuspectTurn];
			eMode = enuMode.animateMove;
			moveStep();
		}

		void moveStep()
		{
			enuDir dirStep;

		startMoveStep:
			if (cMoveAnimationInfo.intAnimationStep < 4)
			{
				using (Graphics g = Graphics.FromImage(cMoveAnimationInfo.bmpAnimationBoard))
				{	// erase old image of suspect off game board	
					g.DrawImage(bmpBoard, cMoveAnimationInfo.recPiece, cMoveAnimationInfo.recPiece, GraphicsUnit.Pixel);
					// move ptImage
					cMoveAnimationInfo.ptImage = new Point(cMoveAnimationInfo.ptImage.X + cMoveAnimationInfo.ptAnimationMove.X, cMoveAnimationInfo.ptImage.Y + cMoveAnimationInfo.ptAnimationMove.Y);
					// create new rectangle for altered position
					cMoveAnimationInfo.recPiece = new Rectangle(cMoveAnimationInfo.ptImage.X, cMoveAnimationInfo.ptImage.Y, 28, 28);
					// draw new image of suspect onto game board
					g.DrawImage(bmpPieces[intSuspectTurn], cMoveAnimationInfo.recPiece, new Rectangle(0, 0, 28, 28), GraphicsUnit.Pixel);
					picBoard.Image = cMoveAnimationInfo.bmpAnimationBoard; picBoard.Refresh();
					cMoveAnimationInfo.intAnimationStep++;
					setDelayTimer(40);
					return;
				}
			}
			else if (cMoveAnimationInfo.strPath.Length > 0)
			{
				string strStep = cMoveAnimationInfo.strPath.Substring(0, 1);
				cMoveAnimationInfo.strPath = cMoveAnimationInfo.strPath.Substring(1);
				dirStep = (enuDir)(Convert.ToInt16(strStep));
				switch (dirStep)
				{
					case enuDir.north:
						cMoveAnimationInfo.ptAnimationMove = new Point(0, -7);
						break;

					case enuDir.east:
						cMoveAnimationInfo.ptAnimationMove = new Point(7, 0);
						break;

					case enuDir.south:
						cMoveAnimationInfo.ptAnimationMove = new Point(0, 7);
						break;

					default:
					case enuDir.west:
						cMoveAnimationInfo.ptAnimationMove = new Point(-7, 0);
						break;
				}
				cMoveAnimationInfo.intAnimationStep = 0;
				goto startMoveStep;
			}

			cMoveAnimationInfo.cSus.ptTile = cMoveAnimationInfo.ptMouseTile;
			if (classSuspect.cFloor[cMoveAnimationInfo.cSus.ptTile.X, cMoveAnimationInfo.cSus.ptTile.Y].eType == enuFloor.door)
			{
				cMoveAnimationInfo.cSus.eRoom = classSuspect.cFloor[cMoveAnimationInfo.cSus.ptTile.X, cMoveAnimationInfo.cSus.ptTile.Y].eRoom;
				cMoveAnimationInfo.cSus.bolCanSuggest = cSuspects[intSuspectTurn].bolHasNotYetMadeASuggestionThisTurn;
                //btnSuggest.Enabled = cSuspects[intSuspectTurn].bolHasNotYetMadeASuggestionThisTurn;
                SuggestButtonEnabled = cSuspects[intSuspectTurn].bolHasNotYetMadeASuggestionThisTurn;
			}
			else
			{
				cMoveAnimationInfo.cSus.eRoom = enuRooms.tiles;
                //btnSuggest.Enabled = cSuspects[intSuspectTurn].bolCanSuggest = false;
                SuggestButtonEnabled = cSuspects[intSuspectTurn].bolCanSuggest = false;
			}

			drawBoard();

			bolDisableMouseClickBoard = false;
			if (!cMoveAnimationInfo.cSus.bolPlayerControlled)
				cMoveAnimationInfo.cSus.playTurnAfterMove();
			else
			{
				//pnlControls.Enabled = true;
                AccuseButtonEnabled
					= EndTurnButtonEnabled
                    = true;
				eMode = enuMode.playerTurnIdle;
			}
		}

		#endregion

		void initAnimateSecretPassage()
		{
			//grbControls.Enabled 
				//= btnRollDie.Enabled =
				RollDieButtonEnabled = false;
			cAnimationSecretPassage.eRoom_End = cRooms[(int) cSuspects[intSuspectTurn].eRoom].oppositeCornerRoom();
			cAnimationSecretPassage.eRoom_Start = cSuspects[intSuspectTurn].eRoom;

			cAnimationSecretPassage.ptStart = getPieceGraphicPositionInRoom((enuSuspects)intSuspectTurn, cSuspects[intSuspectTurn].eRoom);
			cAnimationSecretPassage.ptEnd = getPieceGraphicPositionInRoom((enuSuspects)intSuspectTurn, cAnimationSecretPassage.eRoom_End);

			cAnimationSecretPassage.intStepCounter = 0;
			cAnimationSecretPassage.bolMoveToCenterOfScreen = true;
			cAnimationSecretPassage.intMaxSteps = 12;
			cAnimationSecretPassage.dblAngleBetweenPoints = classMath.arcTan((double)(cAnimationSecretPassage.ptEnd.X - cAnimationSecretPassage.ptStart.X), (double)(cAnimationSecretPassage.ptEnd.Y - cAnimationSecretPassage.ptStart.Y));
			cAnimationSecretPassage.dblDistanceBetweenPoints = Math.Sqrt(Math.Pow(cAnimationSecretPassage.ptEnd.X - cAnimationSecretPassage.ptStart.X, 2) + Math.Pow(cAnimationSecretPassage.ptEnd.Y - cAnimationSecretPassage.ptStart.Y, 2)) / 2;

			cAnimationSecretPassage.ptMidway = new Point((int)(cAnimationSecretPassage.ptStart.X + cAnimationSecretPassage.dblDistanceBetweenPoints * Math.Cos(cAnimationSecretPassage.dblAngleBetweenPoints)),
												   (int)(cAnimationSecretPassage.ptStart.Y + cAnimationSecretPassage.dblDistanceBetweenPoints * Math.Sin(cAnimationSecretPassage.dblAngleBetweenPoints)));

			cSuspects[intSuspectTurn].resetAllowableMoves(); drawBoard();
			
			setDelayTimer(40);
		}

		void AnimateSecretPassage()
		{

            SuggestButtonEnabled = true;
            cAnimationSecretPassage.intStepCounter++;
			if (cAnimationSecretPassage.intStepCounter < cAnimationSecretPassage.intMaxSteps)
			{
				Bitmap bmpTemp = new Bitmap(bmpGameBoard);

				using (Graphics g = Graphics.FromImage(bmpTemp))
				{
					double dblFractionDistance = ((double)cAnimationSecretPassage.intStepCounter / (double)cAnimationSecretPassage.intMaxSteps);
					double dblPartDistance = cAnimationSecretPassage.dblDistanceBetweenPoints * dblFractionDistance;
					Point pt = new Point((int)(cAnimationSecretPassage.ptStart.X + dblPartDistance * Math.Cos(cAnimationSecretPassage.dblAngleBetweenPoints)),
										 (int)(cAnimationSecretPassage.ptStart.Y + dblPartDistance * Math.Sin(cAnimationSecretPassage.dblAngleBetweenPoints)));
					int intTotalSizeDifference = (bmpSuspects[0].Width - 35);
					double dblFractionSize = ((double)cAnimationSecretPassage.intStepCounter / (double)cAnimationSecretPassage.intMaxSteps);
					if (!cAnimationSecretPassage.bolMoveToCenterOfScreen)
					{
						dblFractionSize = ((double)(cAnimationSecretPassage.intMaxSteps - cAnimationSecretPassage.intStepCounter) / (double)cAnimationSecretPassage.intMaxSteps);
					}
					Size sz = new Size((int)(intTotalSizeDifference * dblFractionSize) + 35, (int)(intTotalSizeDifference * dblFractionSize) + 35);

					Point ptTL = new Point(pt.X - sz.Width / 2, pt.Y - sz.Height / 2);

					Rectangle recDest = new Rectangle(ptTL, sz);
					Rectangle recSrc = new Rectangle(0, 0, bmpSuspects[(int)intSuspectTurn].Width, bmpSuspects[(int)intSuspectTurn].Height);

					g.DrawImage(bmpSuspects[(int)intSuspectTurn], recDest, recSrc, GraphicsUnit.Pixel);
				}
				picBoard.Image = bmpTemp; picBoard.Refresh();
				setDelayTimer(40);
			}
			else
			{
				if (cAnimationSecretPassage.bolMoveToCenterOfScreen)
				{
					cAnimationSecretPassage.ptStart = cAnimationSecretPassage.ptMidway;
					cAnimationSecretPassage.intStepCounter = 0;
					cAnimationSecretPassage.bolMoveToCenterOfScreen = false;
					cAnimationSecretPassage.intMaxSteps = 12;
					setDelayTimer(40);
				}
				else
				{
					cSuspects[intSuspectTurn].eRoom = cAnimationSecretPassage.eRoom_End;
                    //btnRollDie.Enabled = false;
                    RollDieButtonEnabled = false;
					//grbControls.Enabled
						//= btnEndTurn.Enabled
						//= 
						EndTurnButtonEnabled
                        //= btnSuggest.Enabled
                        = SuggestButtonEnabled
                        = cSuspects[intSuspectTurn].bolCanSuggest = true;
					bolDisableMouseClickBoard = false;
					eMode = enuMode.playerTurnIdle;
					if (!cSuspects[intSuspectTurn].bolPlayerControlled)
					{
						cSuspects[intSuspectTurn].bolMustMove = false;
						cSuspects[intSuspectTurn].makeSuggestion();
					}
					drawBoard();
				}
			}
		}

		classButton getMouseOverButton(Point ptMouse)
		{
			for (enuButtons eButtonCounter = 0; eButtonCounter < enuButtons._numButtons; eButtonCounter++)
			{
				if (cButtons[(int)eButtonCounter] != null)
				{
					classButton cThisButton = cButtons[(int)eButtonCounter];
					if (ptMouse.X > cThisButton.pt.X && ptMouse.X < cThisButton.pt.X + cThisButton.sz.Width)
						if (ptMouse.Y > cThisButton.pt.Y && ptMouse.Y < cThisButton.pt.Y + cThisButton.sz.Height)
						{
							if (cThisButton.eMode == enuMode.any
								|| cThisButton.eMode == eMode)
							{
								if (cButtons[(int)enuButtons.MouseOver] != cThisButton)
								{
									if (cButtons[(int)enuButtons.MouseOver] != null)
										cButtons[(int)enuButtons.MouseOver].draw();
									cThisButton.highlight();
								}
								return cThisButton;
							}
						}
				}
			}

			if (cButtons[(int)enuButtons.MouseOver] != null)
				cButtons[(int)enuButtons.MouseOver].draw();

			return null;
		}

		void PlaceControls()
		{
			Controls.Add(picBoard);
			picBoard.SizeMode = PictureBoxSizeMode.Normal;
			Bitmap bmpTemp = new Bitmap(bmpBoard.Width + 5 + bmpNotebook.Width, bmpBoard.Height);
			Bitmap bmpLogo = new Bitmap(Resources.clue_logo);
			bmpLogo.MakeTransparent();
				
			Point ptTLLogo = new Point((bmpTemp.Width - bmpLogo.Width) / 2, (bmpTemp.Height - bmpLogo.Height) / 2);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				g.DrawImage(bmpBoard, new Point(0, 0));
				g.DrawImage(bmpNotebook, new Point(bmpBoard.Width + 5, 0));
				g.DrawImage(bmpLogo, ptTLLogo );
			}
			picBoard.Image = bmpTemp;
			picBoard.Location = new Point(0, 25);
			picBoard.Controls.Add(btnAccuse_Ok);

			pnlNotebook.Left = picBoard.Left + Resources.ClueBoardMarble.Width + 5;
			pnlNotebook.Top = picBoard.Top;

			grbControls.Location = new Point(pnlNotebook.Left + pnlNotebook.Width + 5, picNotebook.Top);
			grbControls.Width = Screen.PrimaryScreen.WorkingArea.Width - grbControls.Left - 10;
			grbControls.Height = picNotebook.Height;
			grbControls.Top = picBoard.Top;

			picBoard.Width = pnlNotebook.Left + 240;
			picBoard.Height = Screen.PrimaryScreen.WorkingArea.Height;

			picNotebook.BringToFront();
			bringControlsUpFront();

			picDieBox.Left = 5;
			picDieBox.Width = grbControls.Width - 10;			

			pnlControls.Top = 25;
			pnlControls.Left = 5;
			pnlControls.Width = grbControls.Width-10;

			_btnEndTurn.Left 
				= _btnRollDie.Left 
				= _btnAccuse.Left 
				= _btnSuggest.Left = 5;
			_btnEndTurn.Width 
				= _btnRollDie.Width 
				= _btnSuggest.Width 
				= pnlControls.Width - 10;

			_btnSuggest.Top = 0;
			_btnRollDie.Top 
				= _btnSuggest.Top + _btnSuggest.Height + 5;
			_btnEndTurn.Top 
				= _btnRollDie.Top + _btnRollDie.Height + 5;

			pnlControls.Height = _btnEndTurn.Top + _btnEndTurn.Height + 5;

			_btnAccuse.Top = grbControls.Height - _btnAccuse.Height - 5;
			_btnAccuse.Width = grbControls.Width - 10;
			_btnAccuse.Left = 5;

			picDieBox.Top = pnlControls.Top + pnlControls.Height + 5;
			picDieBox.Height = _btnAccuse.Top - picDieBox.Top - 5;
			picDieBox.Visible = true;

			btnChooseSuspect.BackColor = Color.Transparent;
			btnChooseSuspect.Click += new EventHandler(btnChooseSuspect_Click);
			btnChooseSuspect.Visible = false;

			lblSizer.AutoSize = true;
			Controls.Add(lblSizer);
			lblSizer.Top = Screen.PrimaryScreen.WorkingArea.Height + 10;
			lblSizer.Visible = true;

			picBoard.MouseLeave += new EventHandler(picBoard_MouseLeave);
			picBoard.MouseMove += new MouseEventHandler(Pic_MouseMove);
			picBoard.MouseClick += new MouseEventHandler(pic_MouseClick);
			picBoard.MouseEnter += new EventHandler(picBoard_MouseEnter);

			picNotebook.MouseLeave += new EventHandler(picNotebook_MouseLeave);
			picNotebook.MouseMove += new MouseEventHandler(picNotebook_MouseMove);
			picNotebook.MouseClick += new MouseEventHandler(picNotebook_MouseClick);
			picNotebook.MouseWheel += new MouseEventHandler(picNotebook_MouseWheel);

			grbSetAI.Left = (Screen.PrimaryScreen.WorkingArea.Width - grbSetAI.Width) / 2;
			grbSetAI.Top = (Screen.PrimaryScreen.WorkingArea.Height - grbSetAI.Height) / 2;
			grbSetAI.MouseClick += new MouseEventHandler(grbSetAI_MouseClick);
			grbSetAI.MouseEnter += new EventHandler(grbSetAI_MouseEnter);

			grbSpeed.Left = (Screen.PrimaryScreen.WorkingArea.Width - grbSpeed.Width) / 2;
			grbSpeed.Top = (Screen.PrimaryScreen.WorkingArea.Height - grbSpeed.Height) / 2;
			grbSpeed.MouseEnter += new EventHandler(grbSpeed_MouseEnter);
			chkSpeed_AutoProceed.CheckedChanged += new EventHandler(chkSpeed_AutoProceed_CheckedChanged);
			chkSpeed_AutoProceed.Checked = true;
			hsbSpeed.ValueChanged += new EventHandler(hsbSpeed_ValueChanged);

			Controls.Add(proBar);
			proBar.Top = ptTLLogo.Y + bmpLogo.Height + 35;
			proBar.Width = (int)(Screen.PrimaryScreen.WorkingArea.Width * .3);
			proBar.Left = (Screen.PrimaryScreen.WorkingArea.Width - proBar.Width) / 2;
			proBar.BringToFront();
			proBar.Visible = false;

			for (int intPlayerResponseButtonCounter = 0; intPlayerResponseButtonCounter < btnPlayerResponse.Length; intPlayerResponseButtonCounter++)
			{
				btnPlayerResponse[intPlayerResponseButtonCounter] = new Button();
				picBoard.Controls.Add(btnPlayerResponse[intPlayerResponseButtonCounter]);
				btnPlayerResponse[intPlayerResponseButtonCounter].Visible = false;
				btnPlayerResponse[intPlayerResponseButtonCounter].Text = "";
				btnPlayerResponse[intPlayerResponseButtonCounter].FlatStyle = FlatStyle.Flat;
				btnPlayerResponse[intPlayerResponseButtonCounter].MouseClick += new MouseEventHandler(btnPlayerResponse_Click);
			}

			Controls.Add(lblInitializing);
			lblInitializing.Text = "Initializing data";
			lblInitializing.BackColor = Color.Yellow;
			lblInitializing.AutoSize = true;
			lblInitializing.Left = (Screen.PrimaryScreen.WorkingArea.Width - lblInitializing.Width) / 2;
			lblInitializing.Top = proBar.Top + proBar.Height + 5;
			lblInitializing.Visible = true;
			lblInitializing.BringToFront();


			picBoard.BringToFront();
			proBar.BringToFront();
			lblInitializing.BringToFront();

			if (cEventTicket_AutoProceed == null)
			{
				//tmrAutoProceed.Interval = intBaseAutoProceedInterval;
				//tmrAutoProceed.Tick += new EventHandler(tmrAutoProceed_Tick);
				cEventTicket_AutoProceed = cEC.Ticket("AutoProceed", intBaseAutoProceedInterval, tmrAutoProceed_Tick);
				cEventTicket_AutoProceed.quit();
			}
		
		}

		bool autoProceedEnabled
		{
			get { return cEventTicket_AutoProceed.AutoRepeat; }
			set
			{
				cEventTicket_AutoProceed.AutoRepeat = value;
			}
			//get { return tmrAutoProceed.Enabled; }
			//set 
			//{
			//	tmrAutoProceed.Enabled = false;
				
			//	tmrAutoProceed.Enabled = value; 
			//}
		}
	
		void grbSpeed_MouseEnter(object sender, EventArgs e)
		{
			bolHideOptions = true;
		}

		void grbSetAI_MouseEnter(object sender, EventArgs e)
		{
			bolHideOptions = true;
		}

		void hsbSpeed_ValueChanged(object sender, EventArgs e)
		{
			double dblMaxFactor = 10;
			double dblMinFactor = 0.1;
			double dblSlope = (dblMaxFactor - dblMinFactor) / (-(double)hsbSpeed.Maximum);
			dblSpeedFactor = dblSlope * (double)hsbSpeed.Value + dblMaxFactor;
			//tmrAutoProceed.Interval = (int)((double)intBaseAutoProceedInterval * dblSpeedFactor);
			cEventTicket_AutoProceed.Milliseconds_ConditionTestDelay = (int)((double)intBaseAutoProceedInterval * dblSpeedFactor);
        }

		void chkSpeed_AutoProceed_CheckedChanged(object sender, EventArgs e)
		{
			bolAutoProceed = chkSpeed_AutoProceed.Checked;
		}
		
		void grbSetAI_MouseClick(object sender, MouseEventArgs e)
		{
			enuSuspects eSuspectMouseOver = getMouseOverAISuspect(new Point(e.X, e.Y));
			if (eSuspectMouseOver != enuSuspects._numSuspects)
			{
				classSuspect cSus = cSuspects[(int)eSuspectMouseOver];
				cSus.eAILevel = (enuAILevel)(((int)cSus.eAILevel + 1) % (int)enuAILevel._numAILevels);
				drawSuspectAILevel();
			}
		}
		
		void picNotebook_MouseWheel(object sender, MouseEventArgs e)
		{
			if (!bolInit)
				return;
			if (cButtons[(int)enuButtons.MouseOver] != null)
			{
				if (e.Delta > 0)
					cButtons[(int)enuButtons.MouseOver].cNote.Note = (enuNote)(((int)cButtons[(int)enuButtons.MouseOver].cNote.Note - 1 + (int)enuNote._numNotes) % (int)(enuNote._numNotes));
				else
					cButtons[(int)enuButtons.MouseOver].cNote.Note = (enuNote)(((int)cButtons[(int)enuButtons.MouseOver].cNote.Note + 1) % (int)(enuNote._numNotes));
			}
		}

		void picNotebook_MouseMove(object sender, MouseEventArgs e)
		{
			if (!bolInit)
				return;
			Point ptMouse = new Point(e.X, e.Y);
			for (enuCards eCardCounter = (enuCards)0; eCardCounter < enuCards._numCards; eCardCounter++)
			{
				if (ptMouse.Y > cPlayerNotes[0, (int)eCardCounter].pt.Y && ptMouse.Y < cPlayerNotes[0, (int)eCardCounter].pt.Y + 25)
				{
					for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
					{
						if (ptMouse.X > cPlayerNotes[(int)eSuspectCounter, (int)eCardCounter].pt.X
							&& ptMouse.X < cPlayerNotes[(int)eSuspectCounter, (int)eCardCounter].pt.X + 25)
						{
							classNote cThisNote = cPlayerNotes[(int)eSuspectCounter, (int)eCardCounter];
							if (cMouseOverNote != cThisNote)
							{
								if (cMouseOverNote != null)
									cMouseOverNote.draw();
								cThisNote.highlight();
								cMouseOverNote = cThisNote;
							}
							return;
						}
					}
				}
			}
			if (cMouseOverNote != null)
				cMouseOverNote.draw();
			cMouseOverNote = null;
		}

		void picNotebook_MouseClick(object sender, MouseEventArgs e)
		{
			if (!bolInit)
				return;
			if (cMouseOverNote != null)
			{
				if (e.Button == System.Windows.Forms.MouseButtons.Left)
					cMouseOverNote.Note = (enuNote)(((int)cMouseOverNote.Note + 1) % (int)(enuNote._numNotes));
				else if (e.Button == System.Windows.Forms.MouseButtons.Right)
					cMouseOverNote.Note = (enuNote)(((int)cMouseOverNote.Note - 1 + (int)enuNote._numNotes) % (int)(enuNote._numNotes));
				cMouseOverNote.highlight();
			}
		}

		void picNotebook_MouseLeave(object sender, EventArgs e)
		{
			if (!bolInit)
				return;
			if (cButtons[(int)enuButtons.MouseOver] != null)
				cButtons[(int)enuButtons.MouseOver].draw();
		}

		void picBoard_MouseLeave(object sender, EventArgs e)
		{
			if (!bolInit)
				return;
			if (cButtons[(int)enuButtons.MouseOver] != null)
				cButtons[(int)enuButtons.MouseOver].draw();
		}

		void hideOptions()
		{
			if (bolHideOptions)
			{
				grbSetAI.Visible = grbSpeed.Visible = false;
				bolHideOptions = false;
			}
		}
	
		void drawSuspectAILevel()
		{
			Font fnt = new System.Drawing.Font("Blackadder itc", 18);

			Bitmap bmpTemp = new Bitmap(Resources.setAI);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				{
					Bitmap bmpAILevel = getTextImage(cSuspects[(int)eSuspectCounter].eAILevel.ToString(),
													 fnt,
													 Color.Black);
					bmpAILevel.MakeTransparent();
					g.DrawImage(bmpAILevel, ptSetAI[(int)eSuspectCounter]);
				}
			}
			grbSetAI.BackgroundImage = bmpTemp;
		}

		#region "init objects & classes"

		void initSuspects()
		{
			bmpSuspects[(int)enuSuspects.MissScarlet] = new Bitmap(Resources.SuspectMissScarlet); bmpSuspects[(int)enuSuspects.MissScarlet].MakeTransparent();
			bmpSuspects[(int)enuSuspects.ColMustard] = new Bitmap(Resources.SuspectColMustard); bmpSuspects[(int)enuSuspects.ColMustard].MakeTransparent();
			bmpSuspects[(int)enuSuspects.MrsWhite] = new Bitmap(Resources.SuspectMrsWhite); bmpSuspects[(int)enuSuspects.MrsWhite].MakeTransparent();
			bmpSuspects[(int)enuSuspects.RevGreen] = new Bitmap(Resources.SuspectRevGreen); bmpSuspects[(int)enuSuspects.RevGreen].MakeTransparent();
			bmpSuspects[(int)enuSuspects.MrsPeacock] = new Bitmap(Resources.SuspectMrsPeacock); bmpSuspects[(int)enuSuspects.MrsPeacock].MakeTransparent();
			bmpSuspects[(int)enuSuspects.ProfPlum] = new Bitmap(Resources.SuspectProfPlum); bmpSuspects[(int)enuSuspects.ProfPlum].MakeTransparent();

			cSuspects = new classSuspect[(int)enuSuspects._numSuspects];
			for (enuSuspects SuspectCounter = (enuSuspects)0; SuspectCounter < enuSuspects._numSuspects; SuspectCounter++)
				cSuspects[(int)SuspectCounter] = new classSuspect(SuspectCounter, this);
		}

		void initSetAIGroupBox()
		{
			ptSetAI = new Point[(int)enuSuspects._numSuspects];
			ptSetAI[(int)enuSuspects.ColMustard] = new Point(240, 33);
			ptSetAI[(int)enuSuspects.ProfPlum] = new Point(240, 59);
			ptSetAI[(int)enuSuspects.RevGreen] = new Point(240, 85);
			ptSetAI[(int)enuSuspects.MrsPeacock] = new Point(240, 112);
			ptSetAI[(int)enuSuspects.MissScarlet] = new Point(240, 138);
			ptSetAI[(int)enuSuspects.MrsWhite] = new Point(240, 164);
			drawSuspectAILevel();
		}

		void initWeapons()
		{
			bmpWeapons_PicTray[(int)enuWeapons.Candlestick] = new Bitmap(Resources.WeaponCandlestick);
			bmpWeapons_PicTray[(int)enuWeapons.Knife] = new Bitmap(Resources.WeaponKnife);
			bmpWeapons_PicTray[(int)enuWeapons.LeadPipe] = new Bitmap(Resources.WeaponLeadPipe);
			bmpWeapons_PicTray[(int)enuWeapons.Revolver] = new Bitmap(Resources.WeaponRevolver);
			bmpWeapons_PicTray[(int)enuWeapons.Rope] = new Bitmap(Resources.WeaponRope);
			bmpWeapons_PicTray[(int)enuWeapons.Wrench] = new Bitmap(Resources.WeaponWrench);

			cWeapons = new classWeapon[(int)enuWeapons._numWeapons];
			for (enuWeapons eWeaponCounter = (enuWeapons)0; eWeaponCounter < enuWeapons._numWeapons; eWeaponCounter++)
				cWeapons[(int)eWeaponCounter] = new classWeapon(eWeaponCounter);

			bmpWeapons_Board = new Bitmap[(int)enuWeapons._numWeapons];
			bmpWeapons_Board[(int)enuWeapons.Candlestick] = new Bitmap(Resources.WeaponBoard_Candlestick); bmpWeapons_Board[(int)enuWeapons.Candlestick].MakeTransparent(bmpWeapons_Board[(int)enuWeapons.Candlestick].GetPixel(0, 0));
			bmpWeapons_Board[(int)enuWeapons.Knife] = new Bitmap(Resources.WeaponBoard_Knife); bmpWeapons_Board[(int)enuWeapons.Knife].MakeTransparent(bmpWeapons_Board[(int)enuWeapons.Knife].GetPixel(0, 0));
			bmpWeapons_Board[(int)enuWeapons.LeadPipe] = new Bitmap(Resources.WeaponBoard_LeadPipe); bmpWeapons_Board[(int)enuWeapons.LeadPipe].MakeTransparent(bmpWeapons_Board[(int)enuWeapons.LeadPipe].GetPixel(0, 0));
			bmpWeapons_Board[(int)enuWeapons.Revolver] = new Bitmap(Resources.WeaponBoard_Revolver); bmpWeapons_Board[(int)enuWeapons.Revolver].MakeTransparent(bmpWeapons_Board[(int)enuWeapons.Revolver].GetPixel(0, 0));
			bmpWeapons_Board[(int)enuWeapons.Rope] = new Bitmap(Resources.WeaponBoard_Rope); bmpWeapons_Board[(int)enuWeapons.Rope].MakeTransparent(bmpWeapons_Board[(int)enuWeapons.Rope].GetPixel(0, 0));
			bmpWeapons_Board[(int)enuWeapons.Wrench] = new Bitmap(Resources.WeaponBoard_Wrench); bmpWeapons_Board[(int)enuWeapons.Wrench].MakeTransparent(bmpWeapons_Board[(int)enuWeapons.Wrench].GetPixel(0, 0));
		}

		void initRooms()
		{
			cRooms = new classRoom[(int)enuRooms._numRooms];
			for (enuRooms eRoomCounter = (enuRooms)0; eRoomCounter < enuRooms._numRooms; eRoomCounter++)
				cRooms[(int)eRoomCounter] = new classRoom(eRoomCounter, this);

			bmpRooms[(int)enuRooms.BallRoom] = Resources.CrimeSceneBallRoom;
			bmpRooms[(int)enuRooms.BilliardRoom] = Resources.CrimeSceneBilliardRoom;
			bmpRooms[(int)enuRooms.Conservatory] = Resources.CrimeSceneConservatory;
			bmpRooms[(int)enuRooms.DiningRoom] = Resources.CrimeSceneDiningRoom;
			bmpRooms[(int)enuRooms.Hall] = Resources.CrimeSceneHall;
			bmpRooms[(int)enuRooms.Kitchen] = Resources.CrimeSceneKitchen;
			bmpRooms[(int)enuRooms.Library] = Resources.CrimeSceneLibrary;
			bmpRooms[(int)enuRooms.Lounge] = Resources.CrimeSceneLounge;
			bmpRooms[(int)enuRooms.Study] = Resources.CrimeSceneStudy;
		}

		void initColors()
		{
			clrSuspects = new Color[(int)enuSuspects._numSuspects];
			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				clrSuspects[(int)eSuspectCounter] = bmpPieces[(int)eSuspectCounter].GetPixel(5, 5);
		}

		void initPieces()
		{
			bmpPieces[(int)enuSuspects.MissScarlet] = new Bitmap(Resources.Piece_MissScarlet); bmpPieces[(int)enuSuspects.MissScarlet].MakeTransparent();
			bmpPieces[(int)enuSuspects.ColMustard] = new Bitmap(Resources.Piece_ColMustard); bmpPieces[(int)enuSuspects.ColMustard].MakeTransparent();
			bmpPieces[(int)enuSuspects.MrsWhite] = new Bitmap(Resources.Piece_MrsWhite); bmpPieces[(int)enuSuspects.MrsWhite].MakeTransparent();
			bmpPieces[(int)enuSuspects.RevGreen] = new Bitmap(Resources.Piece_RevGreen); bmpPieces[(int)enuSuspects.RevGreen].MakeTransparent();
			bmpPieces[(int)enuSuspects.MrsPeacock] = new Bitmap(Resources.Piece_MrsPeacock); bmpPieces[(int)enuSuspects.MrsPeacock].MakeTransparent();
			bmpPieces[(int)enuSuspects.ProfPlum] = new Bitmap(Resources.Piece_ProfPlum); bmpPieces[(int)enuSuspects.ProfPlum].MakeTransparent();
		}

		void initIntroMice()
		{
			cBmpDie = new classRotatedImage[3];

			string strDirectoryAndBaseDieFilename = System.IO.Directory.GetCurrentDirectory() + "\\mouse";
			for (int intMouseTailCounter = 0; intMouseTailCounter < 3; intMouseTailCounter++)
			{
				cBmpDie[intMouseTailCounter] = new classRotatedImage();
				string strThisDieFilename = strDirectoryAndBaseDieFilename + intMouseTailCounter.ToString() + ".rBMP";
				if (System.IO.File.Exists(strThisDieFilename))
				{
					cBmpDie[intMouseTailCounter].loadBaseImages(strThisDieFilename);
				}
				else
				{
					Pen pWhite = new Pen(Color.White, 2);
					Bitmap bmpOriginal = Resources.Mouse00;

					switch (intMouseTailCounter)
					{
						case 1:
							bmpOriginal = Resources.Mouse01;
							break;
						case 2:
							bmpOriginal = Resources.Mouse02;
							break;
					}

					cBmpDie[intMouseTailCounter].createBaseImage(bmpOriginal);
					cBmpDie[intMouseTailCounter].saveBaseImages(strThisDieFilename);
				}
			}
		}

		void initDieImages()
		{
			cBmpDie = new classRotatedImage[7];

			string strDirectoryAndBaseDieFilename = System.IO.Directory.GetCurrentDirectory() + "\\die";
			for (int intDieValueCounter = 1; intDieValueCounter < 7; intDieValueCounter++)
			{
				cBmpDie[intDieValueCounter] = new classRotatedImage();
				string strThisDieFilename = strDirectoryAndBaseDieFilename + intDieValueCounter.ToString() + ".rBMP";
				if (System.IO.File.Exists(strThisDieFilename))
				{
					cBmpDie[intDieValueCounter].loadBaseImages(strThisDieFilename);
				}
				else
				{
					Pen pWhite = new Pen(Color.White, 2);
					Bitmap bmpOriginal = Resources.die1;

					switch (intDieValueCounter)
					{
						case 2:
							bmpOriginal = Resources.die2;
							break;
						case 3:
							bmpOriginal =Resources.die3;
							break;
						case 4:
							bmpOriginal =Resources.die4;
							break;
						case 5:
							bmpOriginal =Resources.die5;
							break;
						case 6:
							bmpOriginal =Resources.die6;
							break;
					}

				
					cBmpDie[intDieValueCounter].createBaseImage(bmpOriginal);
					cBmpDie[intDieValueCounter].saveBaseImages(strThisDieFilename);
				}
			}
		}

		void initCards()
		{
			cCards = new classCard[(int)enuCards._numCards];
			for (enuCards cardCounter = (enuCards)0; cardCounter < enuCards._numCards; cardCounter++)
			{
				cCards[(int)cardCounter] = new classCard(this, cardCounter);
			}
			cCardUnknown = new classCard(this, enuCards.Unknown);
		}

		void initMenu()
		{
			ToolStripMenuItem mnuFile = new ToolStripMenuItem();
			mnuFile.Text = "&File";
			mnuFile.DropDownItems.Add("&New Game", null, NewGame);
			mnuFile.DropDownItems.Add("E&xit", null, Exit);
			mnu.Items.Add(mnuFile);
			Controls.Add(mnu);

			ToolStripMenuItem mnuOptions = new ToolStripMenuItem();
			mnuOptions.Text = "&Options";
			mnuOptions.DropDownItems.Add("set &AI", null, SetAI);
			mnuOptions.DropDownItems.Add("&Speed", null, SetSpeed);
			mnu.Items.Add(mnuOptions);
			Controls.Add(mnu);

			ToolStripMenuItem mnuHelp = new ToolStripMenuItem();
			mnuHelp.Text = "&Help";
			mnuHelp.Click +=new EventHandler(Instructions);
			mnu.Items.Add(mnuHelp);
			Controls.Add(mnu);

			ToolStripMenuItem mnuDebugger = new ToolStripMenuItem();
			mnuDebugger.Text = "&Developer";
            mnuDebugger.Click += MnuDebugger_Click;
			mnu.Items.Add(mnuDebugger);

			mnu.BackColor = Color.Black;
			mnu.ForeColor = Color.White;
			mnu.Visible = true;
		}

        private void MnuDebugger_Click(object sender, EventArgs e)
        {
			formCodeUpdateJournal.instance.Text = cMurder.eSuspect.ToString() + " in the " + cMurder.eRoom.ToString() + " with the " + cMurder.eWeapon.ToString();
			formCodeUpdateJournal.instance.Show();
        }

        #endregion

        void Instructions(object sender, EventArgs e)
		{
			if (frmInstructions == null)
				frmInstructions = new formInstructions();
			frmInstructions.ShowDialog();
			frmInstructions.Width = (int)(Screen.PrimaryScreen.WorkingArea.Width * .7);
			frmInstructions.Height = (int)(Screen.PrimaryScreen.WorkingArea.Height * .7);
			frmInstructions.Left = (Screen.PrimaryScreen.WorkingArea.Width - frmInstructions.Width) / 2;
			frmInstructions.Top = (Screen.PrimaryScreen.WorkingArea.Height - frmInstructions.Height) / 2;
		}

		void SetSpeed(object sender, EventArgs e)
		{
			grbSpeed.Visible = !grbSpeed.Visible;
		}

		void SetAI(object sender, EventArgs e)
		{
			grbSetAI.Visible = !grbSetAI.Visible;
		}

		void Exit(object sender, EventArgs e)
		{
			Dispose();
		}

		public void setUpCLibPicTrayChooseWeapon()
		{			
			setPicTrayBackgroundImage(ref cLibPicTrayWeapons);
			cLibPicTrayWeapons.Visible = true;
			cLibPicTrayWeapons.BringToFront();
			cLibPicTrayWeapons.RefreshTrayImage();
			bringControlsUpFront();
		}

		void bringControlsUpFront()
		{
			grbSetAI.BringToFront();
			grbSpeed.BringToFront();
		}

		void setUpCLibPicTrayChooseSuspect()
		{
			setPicTrayBackgroundImage(ref cLibPicTraySuspects);
			cLibPicTraySuspects.Visible = true;
			cLibPicTraySuspects.BringToFront();
			cLibPicTraySuspects.RefreshTrayImage();
			bringControlsUpFront();
		}

		public void NewGame(object sender, EventArgs e)
		{
			eMode = enuMode.chooseCharacter; eDealMode = (enuDealCardsMode)0;
			_btnAccuse.Text = "Accuse";
            //btnAccuse.Enabled = false;
            AccuseButtonEnabled = false;
			intNumTurns = 1;
			cLibPicTrayRooms.Visible =
				cLibPicTrayWeapons.Visible = false;
			bolDisableMouseClickBoard = false;
			btnChooseSuspect.Location = new Point(260, 530);

			bmpDealAnimationBoard_Base = AnimateDealCards_getBlankDealCardsImage();

			picBoard.Size = bmpDealAnimationBoard_Base.Size;
			picBoard.Image = bmpDealAnimationBoard_Base;
			picBoard.BringToFront();

			//Bitmap bmpChooseSuspect = new Bitmap(btnChooseSuspect.Width, btnChooseSuspect.Height);
			//using (Graphics g = Graphics.FromImage(bmpChooseSuspect))
			//{
			//	Rectangle recSrc = new Rectangle(btnChooseSuspect.Location.X, btnChooseSuspect.Location.Y - 25, btnChooseSuspect.Size.Width, btnChooseSuspect.Size.Height);
			//	Rectangle recDest = new Rectangle(0, 0, btnChooseSuspect.Width, btnChooseSuspect.Height);
			//	g.DrawImage(new Bitmap(bmpBoard), recDest, recSrc, GraphicsUnit.Pixel);
			//}
			//btnChooseSuspect.BackgroundImage = bmpChooseSuspect;

			#region "cLibPicTraySuspects Choose Player Character"
			cLibPicTraySuspects.Location = new Point(0, 0);
			cLibPicTraySuspects.Options.Mirror = PicTray.enuMirror.none;
			cLibPicTraySuspects.Options.makeImagesTransparent = true;
			cLibPicTraySuspects.Options.PopUpClickPic = false;
			cLibPicTraySuspects.Options.SelectionMode = PicTray.enuSelectionMode.click;
			cLibPicTraySuspects.Options.TrayCenter = new Point(351, 182);
			cLibPicTraySuspects.Options.Width = 711;
			cLibPicTraySuspects.Options.Height = 491;
			cLibPicTraySuspects.Options.Rotation.StepSize = 0.119380520836412;
			cLibPicTraySuspects.Options.Rotation.Interval = 27;
			cLibPicTraySuspects.Options.Rotation.Mode = PicTray.enuRotationMode.toSelected;
			cLibPicTraySuspects.Options.Ellipse.Angle = 0;
			cLibPicTraySuspects.Options.Ellipse.Radius_Height = 124;
			cLibPicTraySuspects.Options.Ellipse.Radius_Width = 280;
			cLibPicTraySuspects.Options.Front.Angle = 1.56765473414131;
			cLibPicTraySuspects.Options.Front.UserSet = PicTray.enuFrontUserSet.none;
			cLibPicTraySuspects.Options.ImageSize.Height_MinMax = new PicTray.classMinMax(35, 343);
			cLibPicTraySuspects.Options.ImageSize.Width_MinMax = new PicTray.classMinMax(35, 300);
			cLibPicTraySuspects.Options.Caption.Show = false;
			cLibPicTraySuspects.Options.Caption.Font = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular);
			cLibPicTraySuspects.Options.Caption.ForeColor = Color.FromArgb(255, 255, 255, 0);
			cLibPicTraySuspects.Options.Caption.BackColor = Color.FromArgb(255, 0, 0, 0);

			#endregion

			resetSuspects(enuSuspects.MissScarlet);
			resetPlayerNotes();
			btnWarnPlayerWhoseTurnItIs.Visible = false;
			setBtnChooseSuspectColorAndText();
			setUpCLibPicTrayChooseSuspect();
			btnChooseSuspect.Visible = true;
			btnChooseSuspect.BringToFront();
			bringControlsUpFront();

		}

		void resetPlayerNotes()
		{
			bmpNotebook = new Bitmap(Resources.notebook);
			for (enuCards eCardCounter = (enuCards)0; eCardCounter < enuCards._numCards; eCardCounter++)
				for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				{
					if (cPlayerNotes[(int)eSuspectCounter, (int)eCardCounter] == null)
						cPlayerNotes[(int)eSuspectCounter, (int)eCardCounter] = new classNote(	  this,
																							  ref picNotebook,
																								  enuMode.any,
																								  eSuspectCounter,
																								  eCardCounter);
					cPlayerNotes[(int)eSuspectCounter, (int)eCardCounter].Note = enuNote.blank;
					cPlayerNotes[(int)eSuspectCounter, (int)eCardCounter].setMyImages();
				}
			picNotebook.Image = bmpNotebook;
			picNotebook.Refresh();
		}

		void setAccusation()
		{
			cSuggestion.eRoom = (enuRooms)cLibPicTrayRooms.SelectedImage.Index;
			cSuggestion.eSuspect = cSuspects[cLibPicTraySuspects.SelectedImage.Index].eName;
			cSuggestion.eWeapon = (enuWeapons)cLibPicTrayWeapons.SelectedImage.Index;

			btnAccuse_Ok.Text = "I accuse " + cSuggestion.eSuspect.ToString()
							  + "\r\n" + "    in the " + cSuggestion.eRoom.ToString()
							  + "\r\n" + "  with the " + cSuggestion.eWeapon.ToString();			

			//Bitmap bmpAccuseButton = new Bitmap(btnAccuse_Ok.Width, btnAccuse_Ok.Height);
			//using (Graphics g = Graphics.FromImage(bmpAccuseButton))
			//{
			//	// draw suspects' tray image top-left corner of button
			//	Rectangle recSrc = new Rectangle(btnAccuse_Ok.Location.X, btnAccuse_Ok.Location.Y, cLibPicTraySuspects.Width - btnAccuse_Ok.Left, cLibPicTraySuspects.Height - btnAccuse_Ok.Top);
			//	Rectangle recDest = new Rectangle(0, 0, recSrc.Width, recSrc.Height);
			//	g.DrawImage(new Bitmap(cLibPicTraySuspects.Image), recDest, recSrc, GraphicsUnit.Pixel);

			//	// draw weapons' tray image top-right corner of button
			//	recSrc = new Rectangle(0, btnAccuse_Ok.Location.Y, btnAccuse_Ok.Width + btnAccuse_Ok.Left - cLibPicTrayWeapons.Left, cLibPicTrayWeapons.Height - btnAccuse_Ok.Top);
			//	recDest = new Rectangle(cLibPicTrayWeapons.Left - btnAccuse_Ok.Left, 0, recSrc.Width , recSrc.Height);
			//	g.DrawImage(new Bitmap(cLibPicTrayWeapons.Image), recDest, recSrc, GraphicsUnit.Pixel);

			//	// draw rooms' tray image bottom half of button
			//	recSrc = new Rectangle(btnAccuse_Ok.Left, 0, btnAccuse_Ok.Width, btnAccuse_Ok.Top + btnAccuse_Ok.Height - cLibPicTrayRooms.Top);
			//	recDest = new Rectangle(0, cLibPicTrayRooms.Top - btnAccuse_Ok.Top, recSrc.Width, recSrc.Height);
			//	g.DrawImage(new Bitmap(cLibPicTrayRooms.Image), recDest, recSrc, GraphicsUnit.Pixel);
			//}
		
			//btnAccuse_Ok.BackgroundImage = bmpAccuseButton;
			btnAccuse_Ok.BringToFront();
			btnAccuse_Ok.Visible = true;
		}

		void setSuggestion()
		{
			bool bolRefreshSuggestionImage = false;

			if (cSuggestion.eRoom != cSuspects[intSuspectTurn].eRoom)
			{
				cSuggestion.eRoom = cSuspects[intSuspectTurn].eRoom;
				bolRefreshSuggestionImage = true;
			}
			if (cSuggestion.eSuspect != cSuspects[cLibPicTraySuspects.SelectedImage.Index].eName)
			{
				cSuggestion.eSuspect = cSuspects[cLibPicTraySuspects.SelectedImage.Index].eName;
				bolRefreshSuggestionImage = true;
			}
			if (cSuggestion.eWeapon != (enuWeapons)cLibPicTrayWeapons.SelectedImage.Index)
			{
				cSuggestion.eWeapon = (enuWeapons)cLibPicTrayWeapons.SelectedImage.Index;
				bolRefreshSuggestionImage = true;
			}
			if (bolRefreshSuggestionImage)
				writeSuggestion();
		}

		void writeResponse(enuCards eCard_response, enuSuspects eSuspect_responding)
		{
			Bitmap bmpNewBoard = new Bitmap(picBoard.Image);

			using (Graphics g = Graphics.FromImage(bmpNewBoard))
			{
				g.FillRectangle(new SolidBrush(Color.White), new Rectangle(ptResponseBubbleTL.X + 14, ptResponseBubbleTL.Y + 9, 330, 55));

				Bitmap bmpText;
				Font fnt = new System.Drawing.Font("blackadder itc", 36);
				Rectangle recDest, recSrc;

				if (eCard_response == enuCards.NoCardShown)
				{
					bmpText = getTextImage("Sorry, no card", fnt, Color.Black);
					recDest = new Rectangle(ptResponseBubbleTL.X + 25, ptResponseBubbleTL.Y + 15, bmpText.Width, bmpText.Height);
					recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
					g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);
				}
				else
				{
					bmpText = getTextImage("I have a card", fnt, Color.Black);
					recDest = new Rectangle(ptResponseBubbleTL.X + 25, ptResponseBubbleTL.Y + 15, bmpText.Width, bmpText.Height);
					recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
					g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

					Bitmap bmpCardShow = bmpCardBack;
					if (cSuspects[intSuspectTurn].bolPlayerControlled || eSuspect_responding == getPlayerSuspect().eName)
					{
						bmpCardShow = cCards[(int)eCard_response].cBmp.getImage(0);
					}
					int intWidth = 120;
					recDest = new Rectangle(287, ptResponseBubbleTL.Y + bmpResponseBubble.Height, intWidth, (int)((double)bmpCardShow.Height / (double)bmpCardShow.Width * intWidth));
					recSrc = new Rectangle(0, 0, bmpCardShow.Width, bmpCardShow.Height);
					g.DrawImage(bmpCardShow, recDest, recSrc, GraphicsUnit.Pixel);
				}
			}
			picBoard.Image = bmpNewBoard; picBoard.Refresh();
		}

		void writeSuggestion()
		{
		
			Bitmap bmpNewBoard = new Bitmap(picBoard.Image);
			using (Graphics g = Graphics.FromImage(bmpNewBoard))
			{
				g.FillRectangle(new SolidBrush(Color.White), new Rectangle(ptSuggestionBubbleTL.X + 54, ptSuggestionBubbleTL.Y + 9, 335, 280));

				Bitmap bmpText;
				Font fnt = new System.Drawing.Font("blackadder itc", 36);
				Rectangle recDest, recSrc;

				int intTop = 0;
				int intVLineSpacine = 45;
				int intLeftText = 50;
				int intTabText = 140;

				bmpText = getTextImage("I suggest", fnt);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);


				Rectangle recSuggestionBubble = new Rectangle(ptSuggestionBubbleTL, bmpSuggestionBubble.Size);

				bmpText = getTextImage(cSuggestion.eSuspect.ToString(), fnt, cSuggestion.eSuspect == enuSuspects.MrsWhite ? Color.Gray : clrSuspects[(int)cSuggestion.eSuspect]);
				//recDest = new Rectangle(ptSuggestionBubbleTL.X + intTabText, ptSuggestionBubbleTL.Y + intTop + intVLineSpacine + 10, bmpText.Width, bmpText.Height);
				recDest = new Rectangle(recSuggestionBubble.Right - bmpText.Width , ptSuggestionBubbleTL.Y + intTop + intVLineSpacine + 10, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage("in the", fnt);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop + 2 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage(cSuggestion.eRoom.ToString(), fnt);
				//recDest = new Rectangle(ptSuggestionBubbleTL.X + intTabText, ptSuggestionBubbleTL.Y + intTop + 3 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recDest = new Rectangle(recSuggestionBubble.Right - bmpText.Width , ptSuggestionBubbleTL.Y + intTop + 3 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage("with the", fnt);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop + 4 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage(cSuggestion.eWeapon.ToString(), fnt);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intTabText, ptSuggestionBubbleTL.Y + intTop + 5 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);
			}
			picBoard.Image = bmpNewBoard;
		}

		void setBtnChooseSuspectColorAndText()
		{
			//btnChooseSuspect.PulseColor =
			//btnChooseSuspect.ButtonColorTop = clrSuspects[cLibPicTraySuspects.SelectedImage.Index];
			//btnChooseSuspect.ButtonColorBottom = Color.FromArgb((btnChooseSuspect.ButtonColorTop.A + 127) % 255,
			//													(btnChooseSuspect.ButtonColorTop.R + 127) % 255,
			//													(btnChooseSuspect.ButtonColorTop.G + 127) % 255,
			//													(btnChooseSuspect.ButtonColorTop.B + 127) % 255);

			btnChooseSuspect.Text = "Play as " + cLibPicTraySuspects.SelectedImage.caption;
		}

		void btnChooseSuspect_Click(object sender, EventArgs e)
		{
			int intPlayerCharacter = cLibPicTraySuspects.SelectedImage.Index;
			resetSuspects(cSuspects[intPlayerCharacter].eName);
			resetWeapons();

			commitMurder();
			dealCards();
			eMode = enuMode.dealCards;
			
		}

		void setSuspectsAI()
		{
			for (int intSuspectCounter = 0; intSuspectCounter < cSuspects.Length; intSuspectCounter++)
			{
				if (!cSuspects[intSuspectCounter].bolPlayerControlled)
				{
					cSuspects[intSuspectCounter].setAI();
				}
			}
		}

		void eraseDie()
		{
			picDieBox.Image = new Bitmap(bmpBaize);
		}

		public void nextPlayer()
		{
			//tmrNextPlayer.Enabled = true;
			cEventTicket_NextPLayer.AutoRepeat = true;
		}

		void tmrNextPlayer_Tick(object sender, EventArgs e)
		{
			//tmrNextPlayer.Enabled = false;
			cEventTicket_NextPLayer.AutoRepeat = false;
			_nextPlayer();
		}

		void _nextPlayer()
		{
			//btnEndTurn.Enabled = false;
            EndTurnButtonEnabled = true;
			_btnAccuse.Text = "Accuse";
            //btnRollDie.Enabled = true;
            RollDieButtonEnabled = true;

			eraseDie();

			cSuspects[intSuspectTurn].resetAllowableMoves();
			drawBoard();
			do
			{
				intSuspectTurn = (intSuspectTurn + 1) % 6;
			} while (cSuspects[intSuspectTurn].bolEliminated);

			cSuspects[intSuspectTurn].bolMustMove = true;
			
			if (intSuspectTurn == 0)
			{
				intNumTurns++;
			}
            //btnRollDie.Enabled = true;
            RollDieButtonEnabled = true;
            //btnSuggest.Enabled = cSuspects[intSuspectTurn].bolCanSuggest;
            SuggestButtonEnabled = cSuspects[intSuspectTurn].bolCanSuggest;
			cSuspects[intSuspectTurn].bolHasNotYetMadeASuggestionThisTurn = true;
			cSuspects[intSuspectTurn].resetAllowableMoves();

			eMode = enuMode.warnPlayerNextTurn;
		}

		void eraseWarnPlayerWhoseTurnItIs()
		{
			Bitmap bmpTemp = new Bitmap(picBoard.Width, picBoard.Height);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				g.DrawImage(bmpGameBoard, new Point(0, 0));
				g.DrawImage(new Bitmap(picNotebook.Image), new Point(bmpBoard.Width + 5, 0));
			}
			picBoard.Image = bmpTemp; picBoard.Refresh();
		}

		void warnPlayerWhoseTurnItIs()
		{
            //btnAccuse.Enabled = false; 
            AccuseButtonEnabled = false; 
			
			double dblSizeDifference = 1.5;
			Size szNewPicFrame = new System.Drawing.Size((int)(Resources.picture_frame_oval.Width * dblSizeDifference),
												 (int)(Resources.picture_frame_oval.Height * dblSizeDifference));
			Bitmap bmpPicFrame = new Bitmap(Resources.picture_frame_oval, szNewPicFrame);

			Color clrBack = bmpPicFrame.GetPixel(0, 0);
			Color clrMirror = bmpPicFrame.GetPixel(bmpPicFrame.Width / 2, bmpPicFrame.Height / 2);

			bmpPicFrame.MakeTransparent(clrMirror);

			Bitmap bmpSuspectImage = new Bitmap(bmpPicFrame.Width, bmpPicFrame.Height);

			using (Graphics g = Graphics.FromImage(bmpSuspectImage))
			{
				int intHeight = (int)(.8 * bmpPicFrame.Height); // controls the size of the output image relative to original

				Rectangle recDest = new Rectangle((bmpPicFrame.Width - intHeight) / 2, (int)((bmpPicFrame.Height - intHeight) * .6), intHeight, intHeight);
				Rectangle recSrc = new Rectangle(0, 0, bmpSuspects[intSuspectTurn].Width, bmpSuspects[intSuspectTurn].Height);
				g.DrawImage(bmpSuspects[intSuspectTurn], recDest, recSrc, GraphicsUnit.Pixel);
				g.DrawImage(bmpPicFrame, new Point(0, 0));
			}

			bmpSuspectImage.MakeTransparent(clrBack);

			Bitmap bmpTemp = new Bitmap(picBoard.Width, picBoard.Height);

			Point ptLocPicFrame = new Point((Screen.PrimaryScreen.WorkingArea.Width - bmpSuspectImage.Width) / 2, 100);

			// if screen is so wide that mid-screen off the bitmap, adjust
			if (ptLocPicFrame.X > bmpTemp.Width - bmpSuspectImage.Width / 2)
				ptLocPicFrame.X = bmpTemp.Width - bmpSuspectImage.Width / 2;

			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				g.DrawImage(new Bitmap(picBoard.Image), new Point(0, 0));

				g.DrawImage(new Bitmap(picNotebook.Image), new Point(pnlNotebook.Left, 0));

				g.DrawImage(bmpSuspectImage, new Rectangle(ptLocPicFrame, szNewPicFrame), new Rectangle(new Point(0, 0), new Size(szNewPicFrame.Width - 1, szNewPicFrame.Height - 1)), GraphicsUnit.Pixel);
			}

			picBoard.BringToFront();
			picBoard.Image = bmpTemp; picBoard.Refresh();
			picBoard.Width = ptLocPicFrame.X + szNewPicFrame.Width + 10;

			if (cSuspects[intSuspectTurn].bolPlayerControlled)
			{
				btnWarnPlayerWhoseTurnItIs.AutoSize = true;
				btnWarnPlayerWhoseTurnItIs.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
				btnWarnPlayerWhoseTurnItIs.Text = "Your turn " + cSuspects[intSuspectTurn].eName.ToString();
				btnWarnPlayerWhoseTurnItIs.Location = new Point(ptLocPicFrame.X + bmpPicFrame.Width / 2 - btnWarnPlayerWhoseTurnItIs.Width / 2,
																ptLocPicFrame.Y + bmpPicFrame.Height + 50);
				btnWarnPlayerWhoseTurnItIs.BackgroundImage = null;
				btnWarnPlayerWhoseTurnItIs.Visible = true; btnWarnPlayerWhoseTurnItIs.BringToFront();
			}
			else
				setDelayTimer(3000);
			bringControlsUpFront();
		}

		string shuffleCards() { return shuffleCards(true); }

		string shuffleCards(bool bolExcludeMurderCards)
		{
			string strCards = "";
			int intNumSuspects = (int)enuSuspects._numSuspects;			
			int intNumSuspectsAndWeapons = intNumSuspects + (int)enuWeapons._numWeapons;

			enuCards  eWeapon = classCard.getECardFromEWeapon( cMurder.eWeapon);
			enuCards eSuspect = classCard.getECardFromESuspect(cMurder.eSuspect);
			enuCards eRoom = classCard.getECardFromERoom(cMurder.eRoom);

			// gather cards in string
			for (enuCards eCardCounter = 0; eCardCounter < enuCards._numCards; eCardCounter++)
			{
				// Suspects + weapons + rooms

				if (bolExcludeMurderCards
					&& 
					(eCardCounter == eWeapon 
					|| eCardCounter == eSuspect 
					|| eCardCounter == eRoom))
				{
					goto skipAddCard;
				}

				// add card to string
				strCards += ((int)eCardCounter).ToString("d2");

			skipAddCard: ;
			}

			// shuffle cards
			int intNumCards = strCards.Length / 2;
			for (int intShuffleCounter = 0; intShuffleCounter < 10000; intShuffleCounter++)
			{
				int intA = 0, intB = 0;
				while (intA >= intB)
				{
					intA = (int)(rnd.NextDouble() * 1000) % intNumCards;
					intB = (int)(rnd.NextDouble() * 1000) % intNumCards;
				}

				string strA = strCards.Substring(0, intA * 2);
				string strB = strCards.Substring(strA.Length, (intB - intA) * 2);
				string strC = strCards.Substring(strA.Length + strB.Length);

				strCards = strC + strB + strA;
			}
			return strCards;
		}

		void dealCards()
		{
			string strCards = strCardsDealt = shuffleCards();

			// deal cards
			enuSuspects eSuspectCounter = (enuSuspects)0;
			while (strCards.Length > 0)
			{
				string strThisCard = strCards.Substring(0, 2);
				strCards = strCards.Substring(2);
				int intThisCard = Convert.ToInt16(strThisCard);
				classCard thisCard = cCards[intThisCard];
				cSuspects[(int)eSuspectCounter].receiveCard(ref thisCard);
				eSuspectCounter = (enuSuspects)(((int)eSuspectCounter + 1) % (int)enuSuspects._numSuspects);
			}
		}

		void setPlayerNoteBook()
		{
			classSuspect cPlayer = getPlayerSuspect();
			for (int intCardCounter = 0; intCardCounter < cPlayer.cCards.Length; intCardCounter++)
			{
				for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				{
					enuNote eNewNote = enuNote.X;
					if (cSuspects[(int)eSuspectCounter] == cPlayer)
						eNewNote = enuNote.check;

					if (cPlayerNotes[(int)cSuspects[(int)eSuspectCounter].eName, (int)cPlayer.cCards[intCardCounter].eCardName].Note != eNewNote)
					{
						cPlayerNotes[(int)cSuspects[(int)eSuspectCounter].eName, (int)cPlayer.cCards[intCardCounter].eCardName].Note = eNewNote;
					}
					cPlayerNotes[(int)cSuspects[(int)eSuspectCounter].eName, (int)cPlayer.cCards[intCardCounter].eCardName].draw();
				}
			}

			for (enuCards eCardCounter = (enuCards)0; eCardCounter < enuCards._numCards; eCardCounter++)
			{
				if (cPlayerNotes[(int)cPlayer.eName, (int)eCardCounter].Note != enuNote.check)				
					cPlayerNotes[(int)cPlayer.eName, (int)eCardCounter].Note = enuNote.X;
				cPlayerNotes[(int)cSuspects[(int)cPlayer.eName].eName, (int)eCardCounter].draw();
			}
		}

		void commitMurder()
		{
			cMurder.eSuspect = (enuSuspects)((int)(rnd.NextDouble() * 10000) % (int)enuSuspects._numSuspects);
			cMurder.eRoom = (enuRooms)((int)(rnd.NextDouble() * 10000) % (int)enuRooms._numRooms);
			cMurder.eWeapon = (enuWeapons)((int)(rnd.NextDouble() * 10000) % (int)enuWeapons._numWeapons);
		}

		void resetWeapons()
		{
			for (enuWeapons eWeaponsCounter = (enuWeapons)0; eWeaponsCounter < enuWeapons._numWeapons; eWeaponsCounter++)
				cWeapons[(int)eWeaponsCounter].eRoom = enuRooms._numRooms;
		}

		void resetSuspects(enuSuspects ePlayerCharacter)
		{
			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
			{
				cSuspects[(int)eSuspectCounter].bolCanSuggest = false;
				cSuspects[(int)eSuspectCounter].bolEliminated = false;
				cSuspects[(int)eSuspectCounter].bolMustMove = true;
				cSuspects[(int)eSuspectCounter].bolPlayerControlled = (eSuspectCounter == ePlayerCharacter);

				cSuspects[(int)eSuspectCounter].cCards = new classCard[0];
				cSuspects[(int)eSuspectCounter].eRoom = enuRooms.start;
				cSuspects[(int)eSuspectCounter].resetAllowableMoves();
				cSuspects[(int)eSuspectCounter].initNotes();
			}
		}
		
		#region "Accusation"

		private void btnAccuse_Click(object sender, EventArgs e)
		{
			if (cSuspects[intSuspectTurn].bolPlayerControlled && !cSuspects[intSuspectTurn].bolEliminated)
			{
				if (eMode != enuMode.Accuse)
				{
					cAnimationAccusation.eRestoreMode = eMode;
					eMode = enuMode.Accuse;

					_btnAccuse.Text = "cancel Accuse";
					
				}
				else
				{
					eMode = cAnimationAccusation.eRestoreMode;
					btnAccuse_Ok.Visible =
						cLibPicTrayWeapons.Visible =
						cLibPicTrayRooms.Visible =
						cLibPicTraySuspects.Visible = false;
					_btnAccuse.Text = "Accuse";
					//pnlControls.Enabled = true;
				}
			}
		}

		public void btnAccuse_Ok_Click(object sender, EventArgs e)
		{
			classMurder  cAccusation = new classMurder();
			cAccusation.eWeapon = (enuWeapons)cLibPicTrayWeapons.SelectedImage.Index;
			cAccusation.eSuspect = (enuSuspects)cLibPicTraySuspects.SelectedImage.Index;
			cAccusation.eRoom = (enuRooms)cLibPicTrayRooms.SelectedImage.Index;


            //btnAccuse.Enabled 
            AccuseButtonEnabled
                = cLibPicTrayRooms.Visible 
				= cLibPicTrayRooms.tmrRotate.Enabled 
				= cLibPicTrayWeapons.Visible 
				= cLibPicTrayWeapons.tmrRotate.Enabled 
				= cLibPicTraySuspects.Visible 
				= cLibPicTraySuspects.tmrRotate.Enabled 
				= btnAccuse_Ok.Visible 
				= false;
			setButtonsEnabled();

			Accuse(getPlayerSuspect().eName, cAccusation);
		}
		
		void animateAccusation()
		{			
			switch (cAnimationAccusation._eMode)
			{
				case  enuAccuseAnimationMode.drawAccusation:
					AnimateAccusation_drawAccusation();
					break;

				case enuAccuseAnimationMode.prepareToShowCards:
					AnimateAccusation_PrepareToShowCards();
					break;

				case enuAccuseAnimationMode.showCards:
					AnimateAccusation_ShowCards();
					break;

				case enuAccuseAnimationMode.hideCards:
					AnimateAccusation_HideCards();
					break;

				case enuAccuseAnimationMode.retractCards:
					AnimateAccusation_RetractCards();
					break;

				case enuAccuseAnimationMode.withdrawAccusingSuspect:
					AnimateAccusation_WithdrawAccusingSuspect();
					break;

				case enuAccuseAnimationMode.showNewspaper:
					AnimateAccusation_ShowNewspaper();
					break;
			}
		}

		void AnimateAccusation_ShowNewspaper()
		{
			if (!cAnimationAccusation.bolInit)
			{
				cAnimationAccusation.intAnimationStep = 0;

				cAnimationAccusation.lstElements.Clear();// = new classAnimationInfo[2];
				cAnimationAccusation.lstElements.Add(new classAnimationInfo());
				cAnimationAccusation.lstElements.Add(new classAnimationInfo());

				//						Murderer's face (index = 0)
				cAnimationAccusation.lstElements[0].bmp = new Bitmap(bmpSuspects[(int)cMurder.eSuspect].Width, bmpSuspects[(int)cMurder.eSuspect].Height);

				// need to remove trim color around circular image
				Color clrTransparent = bmpSuspects[(int)cMurder.eSuspect].GetPixel(bmpSuspects[(int)cMurder.eSuspect].Width / 2, 0);
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[0].bmp))
				{
					g.FillRectangle(new SolidBrush(clrTransparent), new Rectangle(0, 0, cAnimationAccusation.lstElements[0].bmp.Width, cAnimationAccusation.lstElements[0].bmp.Height));
					g.DrawImage(bmpSuspects[(int)cMurder.eSuspect], new Point(0, 0));
				}

				cAnimationAccusation.lstElements[0].bmp.MakeTransparent(cAnimationAccusation.lstElements[0].bmp.GetPixel(0,0));

				int intImageSize = 200;
				cAnimationAccusation.lstElements[0].dblSizeFactor = (double)intImageSize / (double)cAnimationAccusation.lstElements[0].bmp.Width;
				
				int intStartTop = (int)(intImageSize * .55);
				cAnimationAccusation.lstElements[0].ptPos=
					cAnimationAccusation.lstElements[0].ptStart = new Point((int)(bmpBoard.Width * .5), intStartTop + 20);
				cAnimationAccusation.lstElements[0].ptEnd = new Point((int)(bmpBoard.Width *.5), (int)(bmpBoard.Height *.5));

				cAnimationAccusation.lstElements[0].intMaxSteps = 30;
				cAnimationAccusation.lstElements[0].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[0].ptEnd, cAnimationAccusation.lstElements[0].ptStart);
				cAnimationAccusation.lstElements[0].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[0].ptEnd, cAnimationAccusation.lstElements[0].ptStart);
				cAnimationAccusation.lstElements[0].intStep = 0;


				//						prison bars (index = 1)
				cAnimationAccusation.lstElements[1].bmp = new Bitmap(Resources.prison_bars_large);
				cAnimationAccusation.lstElements[1].bmp.MakeTransparent(Color.White);
				cAnimationAccusation.lstElements[1].ptPos =
					cAnimationAccusation.lstElements[1].ptStart = new Point((int)(bmpBoard.Width *.2), (int)(bmpBoard.Height * .5));
				cAnimationAccusation.lstElements[1].ptEnd = new Point((int)(bmpBoard.Width * .5), (int)(bmpBoard.Height * .5));
				cAnimationAccusation.lstElements[1].intMaxSteps = 30;
				cAnimationAccusation.lstElements[1].dblSizeFactor = 17.5;
				cAnimationAccusation.lstElements[1].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[1].ptEnd, cAnimationAccusation.lstElements[1].ptStart);
				cAnimationAccusation.lstElements[1].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[1].ptEnd, cAnimationAccusation.lstElements[1].ptStart);
				cAnimationAccusation.lstElements[1].intStep = 0;

				cAnimationAccusation.bolInit = true;
			}

			switch (cAnimationAccusation.intAnimationStep)
			{
				case 0: 
						// move murderer image to center & zoom 
						// AND move large color bars from ultra-zoom into focus
					bool bolQuitUltraZoom = true;
					Bitmap bmpTemp = new Bitmap(cAnimationAccusation.bmpAccusationBoard);
					using (Graphics g = Graphics.FromImage(bmpTemp))
					{
						for (int intEleCounter = 0; intEleCounter < cAnimationAccusation.lstElements.Count; intEleCounter++)
						{
							if (cAnimationAccusation.lstElements[intEleCounter].intStep < cAnimationAccusation.lstElements[intEleCounter].intMaxSteps)
							{
								cAnimationAccusation.lstElements[intEleCounter].intStep++;
								cAnimationAccusation.lstElements[intEleCounter].ptPos.X = cAnimationAccusation.lstElements[intEleCounter].ptStart.X + (int)((double)cAnimationAccusation.lstElements[intEleCounter].intStep / (double)cAnimationAccusation.lstElements[intEleCounter].intMaxSteps * cAnimationAccusation.lstElements[intEleCounter].dblTravelDistance * Math.Cos(cAnimationAccusation.lstElements[intEleCounter].dblTravelAngle));
								cAnimationAccusation.lstElements[intEleCounter].ptPos.Y = cAnimationAccusation.lstElements[intEleCounter].ptStart.Y + (int)((double)cAnimationAccusation.lstElements[intEleCounter].intStep / (double)cAnimationAccusation.lstElements[intEleCounter].intMaxSteps * cAnimationAccusation.lstElements[intEleCounter].dblTravelDistance * Math.Sin(cAnimationAccusation.lstElements[intEleCounter].dblTravelAngle));
								bolQuitUltraZoom = false;
							}

							switch (intEleCounter)
							{
								case 0:
									double dblSFFace_Start = 1.0;
									double dblSFFace_End = 2;
									cAnimationAccusation.lstElements[intEleCounter].dblSizeFactor = dblSFFace_Start + (dblSFFace_End - dblSFFace_Start) * ((double)cAnimationAccusation.lstElements[intEleCounter].intStep / (double)cAnimationAccusation.lstElements[intEleCounter].intMaxSteps);
									break;

								case 1:
									// set size factor of bars
									double dblSFBars_Start = 17.5;
									double dblSFBars_End = 1.0;
									cAnimationAccusation.lstElements[intEleCounter].dblSizeFactor = dblSFBars_Start + (dblSFBars_End - dblSFBars_Start) * ((double)cAnimationAccusation.lstElements[intEleCounter].intStep / (double)cAnimationAccusation.lstElements[intEleCounter].intMaxSteps);
									break;
							}
							
							Size sz = new Size((int)((double)cAnimationAccusation.lstElements[intEleCounter].bmp.Width * cAnimationAccusation.lstElements[intEleCounter].dblSizeFactor),
											   (int)((double)cAnimationAccusation.lstElements[intEleCounter].bmp.Height * cAnimationAccusation.lstElements[intEleCounter].dblSizeFactor));
							Point ptTL = new Point(cAnimationAccusation.lstElements[intEleCounter].ptPos.X - sz.Width/2, cAnimationAccusation.lstElements[intEleCounter].ptPos.Y - sz.Height / 2);
							g.DrawImage(cAnimationAccusation.lstElements[intEleCounter].bmp, new Rectangle(ptTL, sz));
						}
					}
					picBoard.Image = bmpTemp; picBoard.Refresh();
					if (bolQuitUltraZoom)
					{
						// join face & bars into one image
						// convert image to black & white
						// introduce newspaper behind it

						// create b/w prison photo (index 0)
						Bitmap bmpBarsAndFace_Color = new Bitmap(cAnimationAccusation.lstElements[1].bmp.Width, cAnimationAccusation.lstElements[1].bmp.Height);
						using (Graphics g = Graphics.FromImage(bmpBarsAndFace_Color))
						{
							g.FillRectangle(new SolidBrush(Color.Brown), new Rectangle(0, 0, bmpBarsAndFace_Color.Width, bmpBarsAndFace_Color.Height));
						
							Size szFace = new Size((int)((double)cAnimationAccusation.lstElements[0].bmp.Width * cAnimationAccusation.lstElements[0].dblSizeFactor),
											   (int)((double)cAnimationAccusation.lstElements[0].bmp.Height * cAnimationAccusation.lstElements[0].dblSizeFactor));
							Point ptTLFace = new Point((bmpBarsAndFace_Color.Width - szFace.Width) / 2, (bmpBarsAndFace_Color.Height - szFace.Height) / 2);
							g.DrawImage(cAnimationAccusation.lstElements[0].bmp, new Rectangle(ptTLFace, szFace));

							Size szBars = new Size((int)((double)cAnimationAccusation.lstElements[1].bmp.Width * cAnimationAccusation.lstElements[1].dblSizeFactor),
											   (int)((double)cAnimationAccusation.lstElements[1].bmp.Height * cAnimationAccusation.lstElements[1].dblSizeFactor));
							Point ptTLBars = new Point(0, 0);
							g.DrawImage(cAnimationAccusation.lstElements[1].bmp, new Rectangle(ptTLBars, szBars));
						}
						cAnimationAccusation.lstElements[1].bmp = MakeGrayscale3(bmpBarsAndFace_Color);
						
						// set up newspaper background
						cAnimationAccusation.lstElements[0].bmp = new Bitmap(Resources.newsprint);
						using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[0].bmp))
						{
							Bitmap bmpText;
							Font fnt = new System.Drawing.Font("Franklin Gothic Demi", 12);
							Rectangle recDest, recSrc;
							Point ptTL = new Point(9, 167);

							bmpText = getTextImage(cMurder.eSuspect.ToString() + " in the " + cMurder.eRoom.ToString(), fnt);
							recDest = new Rectangle(ptTL.X, ptTL.Y, bmpText.Width / 2, bmpText.Height / 2);
							recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
							g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);


							bmpText = getTextImage("with the " + cMurder.eWeapon.ToString(), fnt);
							recDest = new Rectangle(ptTL.X, ptTL.Y + 6, bmpText.Width / 2, bmpText.Height / 2);
							recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
							g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);
						}
					
						cAnimationAccusation.lstElements[0].ptStart =
							cAnimationAccusation.lstElements[0].ptPos =
							cAnimationAccusation.lstElements[0].ptEnd = new Point(bmpBoard.Width / 2, bmpBoard.Height / 2);
						cAnimationAccusation.lstElements[0].dblSizeFactor = 1.0;
						cAnimationAccusation.lstElements[0].intStep =
							cAnimationAccusation.lstElements[0].intMaxSteps = 0;

						// set up prison-picture motion
						cAnimationAccusation.lstElements[1].ptStart = cAnimationAccusation.lstElements[1].ptPos;
						cAnimationAccusation.lstElements[1].ptEnd = new Point(cAnimationAccusation.lstElements[0].ptEnd.X - cAnimationAccusation.lstElements[0].bmp.Width/2 + 9 +75,
																		  cAnimationAccusation.lstElements[0].ptEnd.Y - cAnimationAccusation.lstElements[0].bmp.Height/2 + 82 + 40);
						cAnimationAccusation.lstElements[1].dblSizeFactor = 1.0;
						cAnimationAccusation.lstElements[1].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[1].ptEnd, cAnimationAccusation.lstElements[1].ptStart);
						cAnimationAccusation.lstElements[1].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[1].ptEnd, cAnimationAccusation.lstElements[1].ptStart);
						cAnimationAccusation.lstElements[1].intStep = 0;
						cAnimationAccusation.lstElements[1].intMaxSteps = 20;

						cAnimationAccusation.intAnimationStep++;
					}
					break;

				case 1:
						// move b/w face/bars onto newspaper
					bool bolQuitPutToPrint = true;
					Bitmap bmpTempPutToPrint = new Bitmap(cAnimationAccusation.bmpAccusationBoard);
					using (Graphics g = Graphics.FromImage(bmpTempPutToPrint))
					{
						for (int intEleCounter = 0; intEleCounter < cAnimationAccusation.lstElements.Count; intEleCounter++)
						{
							switch (intEleCounter)
							{
								case 0:
									g.DrawImage(cAnimationAccusation.lstElements[intEleCounter].bmp, cAnimationAccusation.lstElements[intEleCounter].ptPos.X - cAnimationAccusation.lstElements[intEleCounter].bmp.Width / 2, cAnimationAccusation.lstElements[intEleCounter].ptPos.Y - cAnimationAccusation.lstElements[intEleCounter].bmp.Height / 2);
									break;

								case 1:
									if (cAnimationAccusation.lstElements[intEleCounter].intStep < cAnimationAccusation.lstElements[1].intMaxSteps)
									{
										cAnimationAccusation.lstElements[intEleCounter].intStep++;
										cAnimationAccusation.lstElements[intEleCounter].ptPos.X = cAnimationAccusation.lstElements[intEleCounter].ptStart.X + (int)((double)cAnimationAccusation.lstElements[intEleCounter].intStep / (double)cAnimationAccusation.lstElements[intEleCounter].intMaxSteps * cAnimationAccusation.lstElements[intEleCounter].dblTravelDistance * Math.Cos(cAnimationAccusation.lstElements[intEleCounter].dblTravelAngle));
										cAnimationAccusation.lstElements[intEleCounter].ptPos.Y = cAnimationAccusation.lstElements[intEleCounter].ptStart.Y + (int)((double)cAnimationAccusation.lstElements[intEleCounter].intStep / (double)cAnimationAccusation.lstElements[intEleCounter].intMaxSteps * cAnimationAccusation.lstElements[intEleCounter].dblTravelDistance * Math.Sin(cAnimationAccusation.lstElements[intEleCounter].dblTravelAngle));
										bolQuitPutToPrint = false;
									}

									double dblSFFaceAndBars_Start = 1.0;
									double dblSFFaceAndBars_End = 150.0 / (double)cAnimationAccusation.lstElements[intEleCounter].bmp.Width;
									/// = F + (F' - F)(n/N)
									cAnimationAccusation.lstElements[intEleCounter].dblSizeFactor = dblSFFaceAndBars_Start + (dblSFFaceAndBars_End - dblSFFaceAndBars_Start) * ((double)cAnimationAccusation.lstElements[intEleCounter].intStep / (double)cAnimationAccusation.lstElements[intEleCounter].intMaxSteps);
									Size sz = new Size((int)((double)cAnimationAccusation.lstElements[intEleCounter].bmp.Width * cAnimationAccusation.lstElements[intEleCounter].dblSizeFactor),
														   (int)((double)cAnimationAccusation.lstElements[intEleCounter].bmp.Height * cAnimationAccusation.lstElements[intEleCounter].dblSizeFactor));
									Point ptTL = new Point(cAnimationAccusation.lstElements[intEleCounter].ptPos.X - sz.Width / 2, cAnimationAccusation.lstElements[intEleCounter].ptPos.Y - sz.Height / 2);
									g.DrawImage(cAnimationAccusation.lstElements[intEleCounter].bmp, new Rectangle(ptTL, sz));
									break;
							}
						}
					}
					picBoard.Image = bmpTempPutToPrint; picBoard.Refresh();
					if (bolQuitPutToPrint)
					{
						// create four base rotated images during pause						
						Bitmap bmpNewsPaper = new Bitmap(cAnimationAccusation.lstElements[0].bmp.Width, cAnimationAccusation.lstElements[0].bmp.Height);
						using (Graphics g = Graphics.FromImage(bmpNewsPaper))
						{
							g.DrawImage(cAnimationAccusation.lstElements[0].bmp, 0, 0);

							double dblSFFaceAndBars_Start = 1.0;
							double dblSFFaceAndBars_End = 150.0 / (double)cAnimationAccusation.lstElements[1].bmp.Width;
							/// = F + (F' - F)(n/N)
							cAnimationAccusation.lstElements[1].dblSizeFactor = dblSFFaceAndBars_Start + (dblSFFaceAndBars_End - dblSFFaceAndBars_Start) * ((double)cAnimationAccusation.lstElements[1].intStep / (double)cAnimationAccusation.lstElements[1].intMaxSteps);
							Size sz = new Size((int)((double)cAnimationAccusation.lstElements[1].bmp.Width * cAnimationAccusation.lstElements[1].dblSizeFactor),
												   (int)((double)cAnimationAccusation.lstElements[1].bmp.Height * cAnimationAccusation.lstElements[1].dblSizeFactor));
							Point ptTL = new Point(9, 82);
							g.DrawImage(cAnimationAccusation.lstElements[1].bmp, new Rectangle(ptTL, sz));
						}
						cAnimationAccusation.cNewspaper.cBmp = new classRotatedImage();

						double dblAspectRatioXOverY = (double)bmpNewsPaper.Width / (double)bmpNewsPaper.Height;
						cAnimationAccusation.cNewspaper.dblSizeFactor = 2.0;
						double dblReducedSizeFactor = 1.0 / cAnimationAccusation.cNewspaper.dblSizeFactor;
						int intNewWidth = (int)((double)bmpNewsPaper.Width * dblReducedSizeFactor);
						int intNewHeight = (int)((double)intNewWidth / dblAspectRatioXOverY);

						cAnimationAccusation.cNewspaper.cBmp.createBaseImage(new Bitmap( bmpNewsPaper, intNewWidth, intNewHeight));
						cAnimationAccusation.cNewspaper.cBmp.getImage(classRotatedImage.enuFlipRotateType.rotate270);
						cAnimationAccusation.cNewspaper.cBmp.getImage(classRotatedImage.enuFlipRotateType.rotate180);
						cAnimationAccusation.cNewspaper.cBmp.getImage(classRotatedImage.enuFlipRotateType.rotate90);

						cAnimationAccusation.cNewspaper.ptPos = new Point(bmpBoard.Width / 2, bmpBoard.Height / 2);
						
						cAnimationAccusation.intAnimationStep++;
					}
					break;

				default:
						// zoom out newspaper in quick rotation
					cAnimationAccusation.intAnimationStep++;
					Bitmap bmpTempSpinningNewspaper = new Bitmap(cAnimationAccusation.bmpAccusationBoard);
					using (Graphics g = Graphics.FromImage(bmpTempSpinningNewspaper))
					{
						cAnimationAccusation.cNewspaper.dblSizeFactor *= 1.1;
						cAnimationAccusation.cNewspaper.intImage = (cAnimationAccusation.cNewspaper.intImage + 1) % 16;

						Bitmap bmpCurrentNewspaper = cAnimationAccusation.cNewspaper.cBmp.getImage(cAnimationAccusation.cNewspaper.intImage);
						Size szCurrentNewspaper = new Size((int)(bmpCurrentNewspaper.Width * cAnimationAccusation.cNewspaper.dblSizeFactor),
														   (int)(bmpCurrentNewspaper.Height * cAnimationAccusation.cNewspaper.dblSizeFactor));
						Point ptTLCurrentNewspaper = new Point(cAnimationAccusation.cNewspaper.ptPos.X - szCurrentNewspaper.Width / 2,
															   cAnimationAccusation.cNewspaper.ptPos.Y - szCurrentNewspaper.Height / 2);
						g.DrawImage(bmpCurrentNewspaper, new Rectangle(ptTLCurrentNewspaper, szCurrentNewspaper));
					}
					picBoard.Image = bmpTempSpinningNewspaper;picBoard.Refresh();

					if (cAnimationAccusation.cNewspaper.dblSizeFactor > 15)
					{
						GameOver();
						return;
					}
					break;
			}
			setDelayTimer(10);
		}

		void AnimateAccusation_WithdrawAccusingSuspect()
		{
			if (!cAnimationAccusation.bolInit)
			{
				cAnimationAccusation.bolInit = true;

				cAnimationAccusation.lstElements.Clear();// = new classAnimationInfo[1];
				Point ptSuspectTL = new Point(15, 420);

				cAnimationAccusation.lstElements[0].dblSizeFactor = 1.3;
			
				cAnimationAccusation.lstElements[0].bmp = new Bitmap(bmpSuspects[intSuspectTurn]);
				cAnimationAccusation.lstElements[0].ptPos = //Point ptSuspectTL = new Point(15, 420);				
					cAnimationAccusation.lstElements[0].ptStart = new Point(15 + cAnimationAccusation.lstElements[0].bmp.Width / 2, 420 + cAnimationAccusation.lstElements[0].bmp.Height / 2);
				cAnimationAccusation.lstElements[0].ptEnd = getRoomCenter(enuRooms._numRooms);

				cAnimationAccusation.lstElements[0].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[0].ptEnd, cAnimationAccusation.lstElements[0].ptStart);
				cAnimationAccusation.lstElements[0].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[0].ptEnd, cAnimationAccusation.lstElements[0].ptStart);

				cAnimationAccusation.lstElements[0].intMaxSteps = 20;
				cAnimationAccusation.lstElements[0].intStep = 0;


				cAnimationAccusation.intAnimationStep = 0;
			}

			switch (cAnimationAccusation.intAnimationStep)
			{
				case 0: // move suspect head to center of screen
					if (cAnimationAccusation.lstElements[0].intStep < cAnimationAccusation.lstElements[0].intMaxSteps)
					{
						Bitmap bmpTemp = new Bitmap(bmpGameBoard);
						using (Graphics g = Graphics.FromImage(bmpTemp))
						{
							cAnimationAccusation.lstElements[0].intStep++;
							double dblPercentageDistanceTravelled = (double)cAnimationAccusation.lstElements[0].intStep / (double)cAnimationAccusation.lstElements[0].intMaxSteps;
							cAnimationAccusation.lstElements[0].ptPos.X = cAnimationAccusation.lstElements[0].ptStart.X + (int)(cAnimationAccusation.lstElements[0].dblTravelDistance * dblPercentageDistanceTravelled * Math.Cos(cAnimationAccusation.lstElements[0].dblTravelAngle));
							cAnimationAccusation.lstElements[0].ptPos.Y = cAnimationAccusation.lstElements[0].ptStart.Y + (int)(cAnimationAccusation.lstElements[0].dblTravelDistance * dblPercentageDistanceTravelled * Math.Sin(cAnimationAccusation.lstElements[0].dblTravelAngle));

							int intImageSize = (int)(cAnimationAccusation.lstElements[0].bmp.Width * cAnimationAccusation.lstElements[0].dblSizeFactor);
							Rectangle recDest = new Rectangle(cAnimationAccusation.lstElements[0].ptPos.X - intImageSize / 2, cAnimationAccusation.lstElements[0].ptPos.Y - intImageSize / 2, intImageSize, intImageSize);
							Rectangle recSrc = new Rectangle(0, 0, cAnimationAccusation.lstElements[0].bmp.Width, cAnimationAccusation.lstElements[0].bmp.Height);
							g.DrawImage(cAnimationAccusation.lstElements[0].bmp, recDest, recSrc, GraphicsUnit.Pixel);
							cAnimationAccusation.lstElements[0].dblSizeFactor *= 1.05;
						}

						picBoard.Image = bmpTemp; picBoard.Refresh();


					}
					else
					{
						cAnimationAccusation.intAnimationStep++;
						cAnimationAccusation.bmpAccusationForeground = new Bitmap(bmpBoard.Width, bmpBoard.Height);
						using (Graphics g = Graphics.FromImage(cAnimationAccusation.bmpAccusationForeground))
						{
							Rectangle recDest, recSrc;

							g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, cAnimationAccusation.bmpAccusationForeground.Width, cAnimationAccusation.bmpAccusationForeground.Height));

							Bitmap bmpBubble = new Bitmap(Resources.SuggestionBubble, 300, 500);

							bmpBubble.MakeTransparent(Color.White);
							bmpBubble.RotateFlip(RotateFlipType.Rotate270FlipY);

							bmpBubble.MakeTransparent(Color.White);
							Point ptTL = new Point((cAnimationAccusation.bmpAccusationForeground.Width - bmpBubble.Width) / 2, cAnimationAccusation.bmpAccusationForeground.Height - bmpBubble.Height);
							recDest = new Rectangle(ptTL, bmpBubble.Size);
							recSrc = new Rectangle(1, 1, bmpBubble.Width - 2, bmpBubble.Height - 2);
							g.DrawImage(bmpBubble, recDest, recSrc, GraphicsUnit.Pixel);

							Bitmap bmpText;
							Font fnt = new System.Drawing.Font("blackadder itc", 36);

							int intTop = 50;
							int intVLineSpacine = 50;
							int intLeftText = 5;

							bmpText = getTextImage("Forgive my indiscretion", fnt);
							recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop, bmpText.Width, bmpText.Height);
							recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
							g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

							bmpText = getTextImage("I shall remove ", fnt);
							recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop + 2 * intVLineSpacine, bmpText.Width, bmpText.Height);
							recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
							g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

							bmpText = getTextImage("      myself from the game.", fnt);
							recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop + 3 * intVLineSpacine, bmpText.Width, bmpText.Height);
							recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
							g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);
						}

						cAnimationAccusation.lstElements[0].intStep = 0;
						cAnimationAccusation.lstElements[0].intMaxSteps = 80;

						cAnimationAccusation.bmpAccusationForeground.MakeTransparent(Color.White);
					}

					break;

				case 1: // write report that accusing suspect has been eliminated & shrink accusing suspect's image
					Bitmap bmpTemp_WriteReport = new Bitmap(bmpGameBoard);
					using (Graphics g = Graphics.FromImage(bmpTemp_WriteReport))
					{
						cAnimationAccusation.lstElements[0].intStep++;
						cAnimationAccusation.lstElements[0].dblSizeFactor *= .95;

						int intImageSize = (int)(cAnimationAccusation.lstElements[0].bmp.Width * cAnimationAccusation.lstElements[0].dblSizeFactor);
						if (intImageSize < 1)
							intImageSize = 1;
						Rectangle recDest = new Rectangle(cAnimationAccusation.lstElements[0].ptPos.X - intImageSize / 2, cAnimationAccusation.lstElements[0].ptPos.Y - intImageSize / 2, intImageSize, intImageSize);
						Rectangle recSrc = new Rectangle(0, 0, cAnimationAccusation.lstElements[0].bmp.Width, cAnimationAccusation.lstElements[0].bmp.Height);
						g.DrawImage(cAnimationAccusation.lstElements[0].bmp, recDest, recSrc, GraphicsUnit.Pixel);

						g.DrawImage(cAnimationAccusation.bmpAccusationForeground, new Point(0, 0));
					}
					picBoard.Image = bmpTemp_WriteReport;

					if (cAnimationAccusation.lstElements[0].intStep > cAnimationAccusation.lstElements[0].intMaxSteps)
					{
						cAnimationAccusation.intAnimationStep++;
					}
					break;

				case 2: // quit
					cSuspects[intSuspectTurn].bolEliminated = true;
					cSuspects[intSuspectTurn].removeSuspectFromDoorways();
					eMode = enuMode.endTurn;
					break;
			}

		

			setDelayTimer(10);
		}

		void AnimateAccusation_RetractCards()
		{
			int intMaxSteps = 15;

			if (!cAnimationAccusation.bolInit)
			{
				/// room
				cAnimationAccusation.lstElements[(int)enuCardType.room].bmp = cCards[(int)classCard.getECardFromERoom(cMurder.eRoom)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart = cAnimationAccusation.lstElements[(int)enuCardType.room].ptPos;
				cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd = getRoomCenter(enuRooms._numRooms);

				cAnimationAccusation.lstElements[(int)enuCardType.room].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.room].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity = cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelDistance / cAnimationAccusation.lstElements[(int)enuCardType.room].intMaxSteps;

				cAnimationAccusation.lstElements[(int)enuCardType.room].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.room].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle));

				/// weapon
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp = cCards[(int)classCard.getECardFromEWeapon(cMurder.eWeapon)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart = cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptPos;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd = getRoomCenter(enuRooms._numRooms);

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity = cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelDistance / cAnimationAccusation.lstElements[(int)enuCardType.weapon].intMaxSteps;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle));

				/// Suspect
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp = cCards[(int)classCard.getECardFromESuspect(cMurder.eSuspect)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart = cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptPos;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd = getRoomCenter(enuRooms._numRooms);

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity = cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelDistance / cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intMaxSteps;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle));

				cAnimationAccusation.intAnimationStep = 0;
				cAnimationAccusation.bolInit = true;
			}

			Bitmap bmpCard = cCardUnknown.cBmp.getImage(0);
			Bitmap bmpShadeCard = MakeGrayscale3(new Bitmap(cCardUnknown.cBmp.getImage(0)));
			Bitmap bmpTempShade = new Bitmap(cAnimationAccusation.bmpShadedAccusationBoard);
			Bitmap bmpTemp = new Bitmap(cAnimationAccusation.bmpAccusationBoard);
			bool bolQuit = true;

			using (Graphics gGray = Graphics.FromImage(bmpTempShade))  // draw everything in gray-scale
			{
				using (Graphics gForeground = Graphics.FromImage(bmpTemp)) // used to draw the animated cards in color onto a foreground image of 3 elements (3 ele + 3 cards in color)
				{
					gForeground.DrawImage(cAnimationAccusation.bmpAccusationForeground, new Point(0, 0));
					for (enuCardType eTypeCounter = (enuCardType)0; eTypeCounter < enuCardType._numCardTypes; eTypeCounter++)
					{
						cAnimationAccusation.lstElements[(int)eTypeCounter].intStep++;
						if (cAnimationAccusation.lstElements[(int)eTypeCounter].intStep >= cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps)
						{
							cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos = cAnimationAccusation.lstElements[(int)eTypeCounter].ptEnd;
						}
						else
						{
							cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X += cAnimationAccusation.lstElements[(int)eTypeCounter].velTravel.X;
							cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y += cAnimationAccusation.lstElements[(int)eTypeCounter].velTravel.Y;
							bolQuit = false;
						}

						gGray.DrawImage(bmpShadeCard, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height / 2);
						gForeground.DrawImage(bmpCard, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height / 2);
					}
					gGray.DrawImage(cAnimationAccusation.bmpAccusationForegroundGray, new Point(0, 0));
				}

				/// we now have 
				///		- a gray scale foreground drawn onto the gray-scale background (3 gray cards + 3 gray elements)
				///		- a color foreground w/ 3 elements + 3 cards
				///	we need to generate a mask for the floodlights
				Point ptFinalFloodLightPos = getRoomCenter(enuRooms._numRooms);
				Bitmap bmpFloodLights_copy = new Bitmap(bmpFloodlights);
				
				using (Graphics g = Graphics.FromImage(bmpFloodLights_copy))
				{
					bool bolMoveToEnd = (cAnimationAccusation.intAnimationStep > intMaxSteps * 4);
					for (int intFloodlightCounter = 0; intFloodlightCounter < cAnimationAccusation.lstUdrFloodlights.Count; intFloodlightCounter++)
					{
						g.FillEllipse(br, new Rectangle(cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptPos.X - intSizeFloodlights, cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptPos.Y - intSizeFloodlights, 2 * intSizeFloodlights, 2 * intSizeFloodlights));
					}
				}

			endFloodLight:
				bmpFloodLights_copy.MakeTransparent(clrFloordlights);
				// now we also have a blue image with three red circles
				// make red circles transparent
				// superimpose this blue mask on top of colored foreground
				Bitmap bmpMaskedColouredForeground = new Bitmap(bmpTemp);
				using (Graphics g = Graphics.FromImage(bmpMaskedColouredForeground))
					g.DrawImage(bmpFloodLights_copy, new Point(0, 0));

				// make blue transparent (keep colored image only where the transparent red-circles were)
				bmpMaskedColouredForeground.MakeTransparent(clrField);
				// copy these colored circles on top of final output image
				gGray.DrawImage(bmpMaskedColouredForeground, new Point(0, 0));
			}

			picBoard.Image = bmpTempShade;
			cAnimationAccusation.intAnimationStep++;
			if (bolQuit)
			{
				eAccusationMode = enuAccuseAnimationMode.withdrawAccusingSuspect;
			}
			setDelayTimer(10);
		}

		void AnimateAccusation_HideCards()
		{
			if (!cAnimationAccusation.bolInit)
			{
				for (int intCardCounter = 0; intCardCounter < cAnimationAccusation.lstElements.Count; intCardCounter++)
					cAnimationAccusation.lstElements[intCardCounter].intStep = 0;
				cAnimationAccusation.bolInit = true;
			}

			Bitmap bmpCard = cCardUnknown.cBmp.getImage(0);
			Bitmap bmpTemp = new Bitmap(cAnimationAccusation.bmpAccusationBoard);
			bool bolQuit = true;

			using (Graphics gForeground = Graphics.FromImage(bmpTemp)) // used to draw the animated cards in color onto a foreground image of 3 elements (3 ele + 3 cards in color)
			{
				gForeground.DrawImage(cAnimationAccusation.bmpAccusationForeground, new Point(0, 0));
				for (enuCardType eTypeCounter = (enuCardType)0; eTypeCounter < enuCardType._numCardTypes; eTypeCounter++)
				{
					cAnimationAccusation.lstElements[(int)eTypeCounter].intStep++;
					int intMidway = cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps / 2;
					if (cAnimationAccusation.lstElements[(int)eTypeCounter].intStep > intMidway)
					{
						int intStepsPastMid = cAnimationAccusation.lstElements[(int)eTypeCounter].intStep - intMidway;
						double dblPercentageLeft = ((double)intStepsPastMid / (double)intMidway);
						int intWidth = (int)(dblPercentageLeft * (double)cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width);
						if (intWidth < 1)
							intWidth = 1;
						Bitmap bmpFacedown = new Bitmap(cCardUnknown.cBmp.getImage(0), intWidth, cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height);
						gForeground.DrawImage(bmpFacedown, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - bmpFacedown.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - bmpFacedown.Height / 2);
					}
					else
					{
						double dblPercentageLeft = ((double)(intMidway - cAnimationAccusation.lstElements[(int)eTypeCounter].intStep) / (double)intMidway);
						int intWidth = (int)(dblPercentageLeft * (double)cCardUnknown.cBmp.getImage(0).Width);
						if (intWidth < 1)
							intWidth = 1;
						Bitmap bmpFaceup = new Bitmap(cAnimationAccusation.lstElements[(int)eTypeCounter].bmp, intWidth, cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height);
						gForeground.DrawImage(bmpFaceup, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - bmpFaceup.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - bmpFaceup.Height / 2);
					}
					if (cAnimationAccusation.lstElements[(int)eTypeCounter].intStep < cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps)
						bolQuit = false;
				}
			}

			/// we now have 
			///		- a gray scale foreground drawn onto the gray-scale background ( 3 gray elements)
			///		- a color foreground w/ 3 elements + 3 cards
			///	we need to generate a mask for the floodlights
			Point ptFinalFloodLightPos = getRoomCenter(enuRooms._numRooms);
			Bitmap bmpFloodLights_copy = new Bitmap(bmpFloodlights);
			using (Graphics g = Graphics.FromImage(bmpFloodLights_copy))
				g.FillEllipse(br, new Rectangle(cAnimationAccusation.lstUdrFloodlights[0].ptPos.X - intSizeFloodlights, cAnimationAccusation.lstUdrFloodlights[0].ptPos.Y - intSizeFloodlights, 2 * intSizeFloodlights, 2 * intSizeFloodlights));

			bmpFloodLights_copy.MakeTransparent(clrFloordlights);
			// now we also have a blue image with three red circles
			// make red circles transparent
			// superimpose this blue mask on top of colored foreground
			Bitmap bmpMaskedColouredForeground = new Bitmap(bmpTemp);
			using (Graphics g = Graphics.FromImage(bmpMaskedColouredForeground))
				g.DrawImage(bmpFloodLights_copy, new Point(0, 0));

			// make blue transparent (keep colored image only where the transparent red-circles were)
			bmpMaskedColouredForeground.MakeTransparent(clrField);

			// copy the circle of colored image (flood light) on top of final output image
			Bitmap bmpTempShade = new Bitmap(cAnimationAccusation.bmpShadedAccusationBoard);
			using (Graphics gGray = Graphics.FromImage(bmpTempShade))  // draw everything in gray-scale
				gGray.DrawImage(bmpMaskedColouredForeground, new Point(0, 0));

			picBoard.Image = bmpTempShade; picBoard.Refresh();
			cAnimationAccusation.intAnimationStep++;
			if (bolQuit)
			{
				eAccusationMode = enuAccuseAnimationMode.retractCards;
			}
			setDelayTimer(10);
		}		

		void AnimateAccusation_ShowCards()
		{
			int intMaxSteps = 30;

			if (!cAnimationAccusation.bolInit)
			{
				cAnimationAccusation.bolInit = true;
				/// room
				cAnimationAccusation.lstElements[(int)enuCardType.room].bmp = cCards[(int)classCard.getECardFromERoom(cMurder.eRoom)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart =
					cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd =
					cAnimationAccusation.lstElements[(int)enuCardType.room].ptPos;

				cAnimationAccusation.lstElements[(int)enuCardType.room].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.room].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAcceleration =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelDistance =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.room].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.room].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle));

				/// Suspect
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp = cCards[(int)classCard.getECardFromESuspect(cMurder.eSuspect)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptPos;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAcceleration =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelDistance =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle));

				/// weapon
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp = cCards[(int)classCard.getECardFromEWeapon(cMurder.eWeapon)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptPos;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAcceleration =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelDistance =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle));

				cAnimationAccusation.intAnimationStep = 0;
				cAnimationAccusation.bolInit = true;

				// prepare shaded accusation board
				cAnimationAccusation.bmpShadedAccusationBoard = MakeGrayscale3(bmpGameBoard);
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.bmpShadedAccusationBoard))
				{
					g.DrawImage(cAnimationAccusation.bmpAccusationForegroundGray, new Point(0, 0));

					// draw center rectangle w/o cards
					Rectangle recDest = new Rectangle(279, 231, 418 - 279, 426 - 231);
					g.FillRectangle(new SolidBrush(bmpBoard.GetPixel(bmpBoard.Width / 2, bmpBoard.Height / 2)), recDest);

					Bitmap bmpAccusingSuspectAndBubble = getAccusingSuspectAndBubbleImage((enuSuspects)intSuspectTurn, cAnimationAccusation.udrAccusation);
					bmpAccusingSuspectAndBubble.MakeTransparent(Color.White);
					g.DrawImage(bmpAccusingSuspectAndBubble, new Point(0, 0));
				}

				// prepare accusation board
				cAnimationAccusation.bmpAccusationBoard = new Bitmap (bmpGameBoard);
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.bmpAccusationBoard))
				{
					g.DrawImage(cAnimationAccusation.bmpAccusationForeground, new Point(0, 0));

					// draw center rectangle w/o cards
					Rectangle recDest = new Rectangle(279, 231, 418 - 279, 426 - 231);
					g.FillRectangle(new SolidBrush(bmpBoard.GetPixel(bmpBoard.Width / 2, bmpBoard.Height / 2)), recDest);

					Bitmap bmpAccusingSuspectAndBubble = getAccusingSuspectAndBubbleImage((enuSuspects)intSuspectTurn, cAnimationAccusation.udrAccusation);
					bmpAccusingSuspectAndBubble.MakeTransparent(Color.White);
					g.DrawImage(bmpAccusingSuspectAndBubble, new Point(0, 0));
				}
			}

			Bitmap bmpCard = cCardUnknown.cBmp.getImage(0);
			Bitmap bmpTemp = new Bitmap(cAnimationAccusation.bmpAccusationBoard);
			bool bolQuit = true;
			List<Point> lstCardCenters = new List<Point>();
			
			using (Graphics gForeground = Graphics.FromImage(bmpTemp)) // used to draw the animated cards in color onto a foreground image of 3 elements (3 ele + 3 cards in color)
			{
				gForeground.DrawImage(cAnimationAccusation.bmpAccusationForeground, new Point(0, 0));
				for (enuCardType eTypeCounter = (enuCardType)0; eTypeCounter < enuCardType._numCardTypes; eTypeCounter++)
				{
					cAnimationAccusation.lstElements[(int)eTypeCounter].intStep++;
					int intMidway = cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps / 2;
					if (cAnimationAccusation.lstElements[(int)eTypeCounter].intStep > intMidway)
					{
						int intStepsPastMid = cAnimationAccusation.lstElements[(int)eTypeCounter].intStep - intMidway;
						double dblPercentageLeft = ((double)intStepsPastMid / (double)intMidway);
						int intWidth = (int)(dblPercentageLeft * (double)cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width);
						if (intWidth<1)
							intWidth = 1;
						Bitmap bmpFaceup = new Bitmap(cAnimationAccusation.lstElements[(int)eTypeCounter].bmp, intWidth, cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height);
						gForeground.DrawImage(bmpFaceup, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - bmpFaceup.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - bmpFaceup.Height / 2);
						Point ptCardCenter = cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos;
						lstCardCenters.Add(ptCardCenter);
                    }
					else
					{
						double dblPercentageLeft = ((double)(intMidway - cAnimationAccusation.lstElements[(int)eTypeCounter].intStep) / (double)intMidway);
						int intWidth = (int)(dblPercentageLeft * (double)cCardUnknown.cBmp.getImage(0).Width);
						if (intWidth < 1)
							intWidth = 1;
						Bitmap bmpFacedown = new Bitmap(cCardUnknown.cBmp.getImage(0), intWidth, cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height);
						gForeground.DrawImage(bmpFacedown, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - bmpFacedown.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - bmpFacedown.Height / 2);
						Point ptCardCenter = cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos;
						lstCardCenters.Add(ptCardCenter);
					}
					if (cAnimationAccusation.lstElements[(int)eTypeCounter].intStep < cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps)
						bolQuit = false;
				}
			}

			/// we now have 
			///		- a gray scale foreground drawn onto the gray-scale background ( 3 gray elements)
			///		- a color foreground w/ 3 elements + 3 cards
			///	we need to generate a mask for the floodlights
			Point ptFinalFloodLightPos = getRoomCenter(enuRooms._numRooms);
			Bitmap bmpFloodLights_copy = new Bitmap(bmpFloodlights);

			using (Graphics g = Graphics.FromImage(bmpFloodLights_copy))
			{
				for (int intFloodlightCounter = 0; intFloodlightCounter < cAnimationAccusation.lstUdrFloodlights.Count; intFloodlightCounter++)
				{
					classAnimationInfo udrAniAccusationItem = cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter];
					if (cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].intStep >= cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].intMaxSteps)
					{
						Point ptCardCenter = lstCardCenters[intFloodlightCounter % lstCardCenters.Count];
						g.FillEllipse(br, new Rectangle(ptCardCenter.X - intSizeFloodlights, ptCardCenter.Y - intSizeFloodlights, 2 * intSizeFloodlights, 2 * intSizeFloodlights));
					}
				}



                g.FillEllipse(br, new Rectangle(cAnimationAccusation.lstUdrFloodlights[0].ptPos.X - intSizeFloodlights, cAnimationAccusation.lstUdrFloodlights[0].ptPos.Y - intSizeFloodlights, 2 * intSizeFloodlights, 2 * intSizeFloodlights));
			}
			bmpFloodLights_copy.MakeTransparent(clrFloordlights);
			// now we also have a blue image with three red circles
			// make red circles transparent
			// superimpose this blue mask on top of colored foreground
			Bitmap bmpMaskedColouredForeground = new Bitmap(bmpTemp);
			using (Graphics g = Graphics.FromImage(bmpMaskedColouredForeground))
				g.DrawImage(bmpFloodLights_copy, new Point(0, 0));

			// make blue transparent (keep colored image only where the transparent red-circles were)
			bmpMaskedColouredForeground.MakeTransparent(clrField);

			// copy the circle of colored image (flood light) on top of final output image
			Bitmap bmpTempShade = new Bitmap(cAnimationAccusation.bmpShadedAccusationBoard);
			using (Graphics gGray = Graphics.FromImage(bmpTempShade))  // draw everything in gray-scale
				gGray.DrawImage(bmpMaskedColouredForeground, new Point(0, 0));

			picBoard.Image = bmpTempShade; picBoard.Refresh();
			cAnimationAccusation.intAnimationStep++;
			if (bolQuit)
			{
				if (compareTwoMurderScenes(cAnimationAccusation.udrAccusation, cMurder))
				{ // accusation is correct
					eAccusationMode = enuAccuseAnimationMode.showNewspaper;
					cAnimationAccusation.bmpAccusationBoard = new Bitmap(picBoard.Image);
				}
				else 
				{ // accusation is false
					eAccusationMode = enuAccuseAnimationMode.hideCards;
				}
			}
			setDelayTimer(10);
		}

		bool compareTwoMurderScenes(classMurder  udrMurderA, classMurder  udrMurderB)
		{
			return (udrMurderA.eSuspect == udrMurderB.eSuspect
					&& udrMurderA.eRoom == udrMurderB.eRoom
					&& udrMurderA.eWeapon == udrMurderB.eWeapon);
		}
        
		int _intSizeFloodlights = 40;
        int intSizeFloodlights
		{
			get {return _intSizeFloodlights; }
			set {_intSizeFloodlights = value; }
		}

        void AnimateAccusation_PrepareToShowCards()
		{
			intSizeFloodlights += 2;
			int intMaxSteps = 15;

			if (!cAnimationAccusation.bolInit)
			{
				/// room
				cAnimationAccusation.lstElements[(int)enuCardType.room].bmp = cCards[(int)classCard.getECardFromERoom(cMurder.eRoom)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.room].ptPos =
					cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart = getRoomCenter(enuRooms._numRooms);
				cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd = new Point(cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart.X - cAnimationAccusation.lstElements[(int)enuCardType.room].bmp.Width, getRoomCenter(enuRooms._numRooms).Y);

				cAnimationAccusation.lstElements[(int)enuCardType.room].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.room].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity = cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelDistance / cAnimationAccusation.lstElements[(int)enuCardType.room].intMaxSteps;

				cAnimationAccusation.lstElements[(int)enuCardType.room].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.room].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle));

				/// weapon
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp = cCards[(int)classCard.getECardFromEWeapon(cMurder.eWeapon)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptPos =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart = getRoomCenter(enuRooms._numRooms);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd = new Point(cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart.X + cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp.Width, getRoomCenter(enuRooms._numRooms).Y);

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity = cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelDistance / cAnimationAccusation.lstElements[(int)enuCardType.weapon].intMaxSteps;

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle));

				/// Suspect
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp = cCards[(int)classCard.getECardFromESuspect(cMurder.eSuspect)].cBmp.getImage(0);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptPos =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart = getRoomCenter(enuRooms._numRooms);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd = new Point(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart.X, getRoomCenter(enuRooms._numRooms).Y);

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intStep = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurning =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleFacing =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurningAttenuation = 0;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity = cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelDistance / cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intMaxSteps;

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].velTravel.X = (int)(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity * Math.Cos(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle));
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].velTravel.Y = (int)(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelInitialVelocity * Math.Sin(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle));

				cAnimationAccusation.lstUdrFloodlights = new List<classAnimationInfo>();
				int intNumFloodLights = 3;
				for (int intFloodlightCounter = 0; intFloodlightCounter < intNumFloodLights; intFloodlightCounter++)
				{
					cAnimationAccusation.lstUdrFloodlights.Add(new classAnimationInfo());
					classAnimationInfo udrAnimationInfo = cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter];

                    udrAnimationInfo.ptStart 
						= new Point(((int)rnd.NextDouble() * 1000) % 2 == 0 ? bmpBoard.Width + 50 : -50, 
									 (int)rnd.NextDouble() * bmpBoard.Height);
					udrAnimationInfo.intMaxSteps = udrAnimationInfo.intStep = 0;
				}

				cAnimationAccusation.intAnimationStep = 0;
				cAnimationAccusation.bolInit = true;	
			}

			Bitmap bmpCard = cCardUnknown.cBmp.getImage(0);
			Bitmap bmpShadeCard = MakeGrayscale3(new Bitmap(cCardUnknown.cBmp.getImage(0)));
			Bitmap bmpTempShade = new Bitmap(cAnimationAccusation.bmpShadedAccusationBoard);
			Bitmap bmpTemp = new Bitmap(cAnimationAccusation.bmpAccusationBoard);
			bool bolQuit = false;
				
			using (Graphics gGray = Graphics.FromImage(bmpTempShade))  // draw everything in gray-scale
			{
				using (Graphics gForeground = Graphics.FromImage(bmpTemp)) // used to draw the animated cards in color onto a foreground image of 3 elements (3 ele + 3 cards in color)
				{
					gForeground.DrawImage(cAnimationAccusation.bmpAccusationForeground, new Point(0, 0));
					for (enuCardType eTypeCounter = (enuCardType)0; eTypeCounter < enuCardType._numCardTypes; eTypeCounter++)
					{
						if (cAnimationAccusation.intAnimationStep > 20)
						{
							cAnimationAccusation.lstElements[(int)eTypeCounter].intStep++;
							if (cAnimationAccusation.lstElements[(int)eTypeCounter].intStep >= cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps)
							{
								cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos = cAnimationAccusation.lstElements[(int)eTypeCounter].ptEnd;
							}
							else
							{
								cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X += cAnimationAccusation.lstElements[(int)eTypeCounter].velTravel.X;
								cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y += cAnimationAccusation.lstElements[(int)eTypeCounter].velTravel.Y;
							}
						}

						gGray.DrawImage(bmpShadeCard, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height / 2);
						gForeground.DrawImage(bmpCard, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height / 2);
					}
					gGray.DrawImage(cAnimationAccusation.bmpAccusationForegroundGray, new Point(0, 0));
				}

				/// we now have 
				///		- a gray scale foreground drawn onto the gray-scale background (3 gray cards + 3 gray elements)
				///		- a color foreground w/ 3 elements + 3 cards
				///	we need to generate a mask for the floodlights
				Point ptFinalFloodLightPos = getRoomCenter(enuRooms._numRooms);
				Bitmap bmpFloodLights_copy = new Bitmap(bmpFloodlights);
				using (Graphics g = Graphics.FromImage(bmpFloodLights_copy))
				{
					bool bolMoveToEnd = (cAnimationAccusation.intAnimationStep > intMaxSteps* 4);
					for (int intFloodlightCounter = 0; intFloodlightCounter < cAnimationAccusation.lstUdrFloodlights.Count; intFloodlightCounter++)
					{
							classAnimationInfo udrAniAccusationItem = cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter];
						if (cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].intStep >= cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].intMaxSteps)
						{

                            udrAniAccusationItem.dblTravelDistance = 0;
                            udrAniAccusationItem.ptPos = cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptEnd;
							if ((bolMoveToEnd && cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptPos == ptFinalFloodLightPos))
							{
								g.FillEllipse(br, new Rectangle(cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptPos.X - intSizeFloodlights, cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptPos.Y - intSizeFloodlights, 2 * intSizeFloodlights, 2 * intSizeFloodlights));
								bolQuit = true;
								goto endFloodLight;
							}
							bool bolLoop = true;
							while (cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].dblTravelDistance < 200 && bolLoop)
							{
								udrAniAccusationItem.intStep = 0;
								udrAniAccusationItem.ptStart = udrAniAccusationItem.ptPos;
								if (bolMoveToEnd)
									udrAniAccusationItem.ptEnd = ptFinalFloodLightPos;
								else
									udrAniAccusationItem.ptEnd = new Point((int)(rnd.NextDouble() * 10000) % (int)(bmpBoard.Width*2.0/3.0) + (int)(bmpBaize.Width * 1.0/6.0), (int)(rnd.NextDouble() * 10000) % (int)(bmpBoard.Height * .4) + (int)(bmpBoard.Height * .1));
								udrAniAccusationItem.dblAngleFacing =
									udrAniAccusationItem.dblAngleTurning =
									udrAniAccusationItem.dblAngleTurningAttenuation = 0;
								udrAniAccusationItem.dblTravelAngle = classMath.arcTan(udrAniAccusationItem.ptEnd, udrAniAccusationItem.ptStart);
								udrAniAccusationItem.dblTravelDistance = classMath.distanceBetweenTwoPoints(udrAniAccusationItem.ptEnd, udrAniAccusationItem.ptStart);
								int intStepSize = 20;
								if (udrAniAccusationItem.dblTravelDistance < intStepSize)
								{
									udrAniAccusationItem.ptPos = udrAniAccusationItem.ptEnd;
									bolLoop = false;
								}
								else
								{
									udrAniAccusationItem.intMaxSteps = (int)(udrAniAccusationItem.dblTravelDistance / 20);
									udrAniAccusationItem.dblTravelInitialVelocity = udrAniAccusationItem.dblTravelDistance / udrAniAccusationItem.intMaxSteps;

									udrAniAccusationItem.velTravel.X = (int)(udrAniAccusationItem.dblTravelInitialVelocity * Math.Cos(udrAniAccusationItem.dblTravelAngle));
									udrAniAccusationItem.velTravel.Y = (int)(udrAniAccusationItem.dblTravelInitialVelocity * Math.Sin(udrAniAccusationItem.dblTravelAngle));
									bolLoop = false;
								}
							}
						}
						udrAniAccusationItem.ptPos.X += udrAniAccusationItem.velTravel.X;
						udrAniAccusationItem.ptPos.Y += udrAniAccusationItem.velTravel.Y;
						udrAniAccusationItem.intStep++;

						g.FillEllipse(br, new Rectangle(cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptPos.X - intSizeFloodlights, cAnimationAccusation.lstUdrFloodlights[intFloodlightCounter].ptPos.Y - intSizeFloodlights, 2 * intSizeFloodlights, 2 * intSizeFloodlights));
					}
				}

			endFloodLight:
				//bmpFloodLights_copy.Save(@"c:\debug\FloodLights_Copy.png");
				bmpFloodLights_copy.MakeTransparent(clrFloordlights);
				// now we also have a blue image with three red circles
				// make red circles transparent
				// superimpose this blue mask on top of colored foreground
				Bitmap bmpMaskedColouredForeground = new Bitmap(bmpTemp);
				using (Graphics g = Graphics.FromImage(bmpMaskedColouredForeground))
					g.DrawImage(bmpFloodLights_copy, new Point (0,0));

				// make blue transparent (keep colored image only where the transparent red-circles were)
				bmpMaskedColouredForeground.MakeTransparent(clrField);
				// copy these colored circles on top of final output image
				gGray.DrawImage(bmpMaskedColouredForeground, new Point(0, 0));
			}

			picBoard.Image = bmpTempShade;
			cAnimationAccusation.intAnimationStep++;
			if (bolQuit)
			{
				if (cSuspects[intSuspectTurn].bolPlayerControlled
					|| compareTwoMurderScenes(cAnimationAccusation.udrAccusation, cMurder))
				{
					eAccusationMode = enuAccuseAnimationMode.showCards;
				}
				else
				{
					eAccusationMode = enuAccuseAnimationMode.withdrawAccusingSuspect;
				}
			}
			setDelayTimer(10);
		}

		/// <summary>
		///  copied from http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale
		/// </summary>
		/// <param name="original"></param>
		/// <returns></returns>
		public Bitmap MakeGrayscale3(Bitmap original)
		{
			//create a blank bitmap the same size as original
			Bitmap newBitmap = new Bitmap(original.Width, original.Height);

			//get a graphics object from the new image
			Graphics g = Graphics.FromImage(newBitmap);

			//create the grayscale ColorMatrix
			ColorMatrix colorMatrix = new ColorMatrix(new float[][] {
																	new float[] {.3f, .3f, .3f, 0, 0},
																	new float[] {.59f, .59f, .59f, 0, 0},
																	new float[] {.11f, .11f, .11f, 0, 0},
																	new float[] {0, 0, 0, 1, 0},
																	new float[] {0, 0, 0, 0, 1}
																	}
													 );

			//create some image attributes
			ImageAttributes attributes = new ImageAttributes();

			//set the color matrix attribute
			attributes.SetColorMatrix(colorMatrix);

			//draw the original image on the new image
			//using the grayscale color matrix
			g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
			   0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);

			//dispose the Graphics object
			g.Dispose();
			return newBitmap;
		}

		void AnimateAccusation_drawAccusation()
        {
            intSizeFloodlights = 40;
            if (!cAnimationAccusation.bolInit)
			{
                cAnimationAccusation.bolInit = true;

				btnAccuse_Ok.Visible = false;
				cLibPicTrayRooms.Visible =
					cLibPicTrayRooms.tmrRotate.Enabled = false;
				cLibPicTrayWeapons.Visible =
					cLibPicTrayWeapons.tmrRotate.Enabled = false;
				cLibPicTraySuspects.Visible =
					cLibPicTraySuspects.tmrRotate.Enabled = false;

				cAnimationAccusation.bmpAccusationBoard = new Bitmap(picBoard.Image);
				cAnimationAccusation.bmpShadedAccusationBoard = MakeGrayscale3(cAnimationAccusation.bmpAccusationBoard);

				/// draw accusing suspect and bubble onto base image
				Bitmap bmpAccusingSuspectImageAndBubble = getAccusingSuspectAndBubbleImage((enuSuspects)intSuspectTurn, cAnimationAccusation.udrAccusation);
				bmpAccusingSuspectImageAndBubble.MakeTransparent(Color.White);

				using (Graphics g = Graphics.FromImage(cAnimationAccusation.bmpAccusationBoard))
					g.DrawImage(bmpAccusingSuspectImageAndBubble, new Point(0, 0));

				using (Graphics g = Graphics.FromImage(cAnimationAccusation.bmpShadedAccusationBoard))
					g.DrawImage(bmpAccusingSuspectImageAndBubble, new Point(0, 0));

				int intImageSize = 200;
				int intSpaceBetweenRestingImages = (int)(intImageSize * .84);
				int intEndTop = (int)(intImageSize * .55);
				int intMaxSteps = 20;


				cAnimationAccusation.lstElements.Clear();// = new classAnimationInfo[3];
				for (int intCardTypeCounter = 0; intCardTypeCounter < (int)enuCardType._numCardTypes; intCardTypeCounter++)
					cAnimationAccusation.lstElements.Add(new classAnimationInfo());
				// room
				cAnimationAccusation.lstElements[(int)enuCardType.room].ptPos =
					cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart = new Point(-50, -50);
				cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd = new Point((int)(bmpBoard.Width * .5) -intSpaceBetweenRestingImages , intEndTop);
				cAnimationAccusation.lstElements[(int)enuCardType.room].intMaxSteps = (int)(intMaxSteps*1.5);
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleFacing = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurning = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblAngleTurningAttenuation = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.room].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.room].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.room].ptStart);
				
				cAnimationAccusation.lstElements[(int)enuCardType.room].bmpGray =MakeGrayscale3( new Bitmap(bmpRooms[(int)cAnimationAccusation.udrAccusation.eRoom], intImageSize, intImageSize));
				// this rectangle corrects any errors generated in resizing image that would leave a trailing line on the edges
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[(int)enuCardType.room].bmpGray))
					g.DrawRectangle(new Pen(cAnimationAccusation.lstElements[(int)enuCardType.room].bmpGray.GetPixel(0, 0), 2), new Rectangle(0, 0, intImageSize - 1, intImageSize - 1));
				cAnimationAccusation.lstElements[(int)enuCardType.room].bmpGray.MakeTransparent(cAnimationAccusation.lstElements[(int)enuCardType.room].bmpGray.GetPixel(0, 0));

				cAnimationAccusation.lstElements[(int)enuCardType.room].bmp = new Bitmap(bmpRooms[(int)cAnimationAccusation.udrAccusation.eRoom], intImageSize, intImageSize);
				// this rectangle corrects any errors generated in resizing image that would leave a trailing line on the edges
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[(int)enuCardType.room].bmp))
					g.DrawRectangle(new Pen(cAnimationAccusation.lstElements[(int)enuCardType.room].bmp.GetPixel(0, 0), 2), new Rectangle(0, 0, intImageSize - 1, intImageSize - 1));
				cAnimationAccusation.lstElements[(int)enuCardType.room].bmp.MakeTransparent(cAnimationAccusation.lstElements[(int)enuCardType.room].bmp.GetPixel(0, 0));
				
				cAnimationAccusation.lstElements[(int)enuCardType.room].intStep = 0;

				// suspect
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptPos =
					cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart = new Point(bmpBoard.Width/2, -50);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd = new Point((int)(bmpBoard.Width * .5), intEndTop+20);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intMaxSteps = intMaxSteps;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleFacing = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurning = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblAngleTurningAttenuation = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.Suspect].ptStart);
					
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmpGray =MakeGrayscale3( new Bitmap(bmpSuspects[(int)cAnimationAccusation.udrAccusation.eSuspect], intImageSize, intImageSize));
				// this rectangle corrects any errors generated in resizing image that would leave a trailing line on the edges
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmpGray))
					g.DrawRectangle(new Pen(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmpGray.GetPixel(0, 0),2), new Rectangle(0, 0, intImageSize-1, intImageSize-1));
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmpGray.MakeTransparent(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmpGray.GetPixel(0, 0));

				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp = new Bitmap(bmpSuspects[(int)cAnimationAccusation.udrAccusation.eSuspect], intImageSize, intImageSize);
				// this rectangle corrects any errors generated in resizing image that would leave a trailing line on the edges
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp))
					g.DrawRectangle(new Pen(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp.GetPixel(0, 0), 2), new Rectangle(0, 0, intImageSize - 1, intImageSize - 1));
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp.MakeTransparent(cAnimationAccusation.lstElements[(int)enuCardType.Suspect].bmp.GetPixel(0, 0));
				
				cAnimationAccusation.lstElements[(int)enuCardType.Suspect].intStep = 0;

				// weapon
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptPos =
					cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart = new Point(bmpBoard.Width +50, -50);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd = new Point((int)(bmpBoard.Width * .5) + intSpaceBetweenRestingImages , intEndTop);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intMaxSteps = (int)(intMaxSteps*1.5);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleFacing = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurning = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblAngleTurningAttenuation = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAcceleration = 0;
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelAngle = classMath.arcTan(cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart);
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].dblTravelDistance = classMath.distanceBetweenTwoPoints(cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptEnd, cAnimationAccusation.lstElements[(int)enuCardType.weapon].ptStart);
				
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmpGray =MakeGrayscale3( new Bitmap(bmpWeapons_PicTray[(int)cAnimationAccusation.udrAccusation.eWeapon], intImageSize, intImageSize));
				// this rectangle corrects any errors generated in resizing image that would leave a trailing line on the edges
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmpGray))
					g.DrawRectangle(new Pen(cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmpGray.GetPixel(0, 0), 2), new Rectangle(0, 0, intImageSize - 1, intImageSize - 1));
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmpGray.MakeTransparent(cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmpGray.GetPixel(0, 0));

				cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp = new Bitmap(bmpWeapons_PicTray[(int)cAnimationAccusation.udrAccusation.eWeapon], intImageSize, intImageSize);
				// this rectangle corrects any errors generated in resizing image that would leave a trailing line on the edges
				using (Graphics g = Graphics.FromImage(cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp))
					g.DrawRectangle(new Pen(cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp.GetPixel(0, 0), 2), new Rectangle(0, 0, intImageSize - 1, intImageSize - 1));
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp.MakeTransparent(cAnimationAccusation.lstElements[(int)enuCardType.weapon].bmp.GetPixel(0, 0));
				
				cAnimationAccusation.lstElements[(int)enuCardType.weapon].intStep = 0;
			}

			Bitmap bmpTemp = new Bitmap(cAnimationAccusation.bmpShadedAccusationBoard);
			bool bolQuitDraw = true;
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				for (enuCardType eTypeCounter = (enuCardType)0; eTypeCounter < enuCardType._numCardTypes; eTypeCounter++)
				{
					cAnimationAccusation.lstElements[(int)eTypeCounter].intStep++;
					if (cAnimationAccusation.lstElements[(int)eTypeCounter].intStep < cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps)
						bolQuitDraw = false;
					else
						cAnimationAccusation.lstElements[(int)eTypeCounter].intStep = cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps;
					cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X = cAnimationAccusation.lstElements[(int)eTypeCounter].ptStart.X + (int)(cAnimationAccusation.lstElements[(int)eTypeCounter].dblTravelDistance * ((double)cAnimationAccusation.lstElements[(int)eTypeCounter].intStep / (double)cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps) * Math.Cos(cAnimationAccusation.lstElements[(int)eTypeCounter].dblTravelAngle));
					cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y = cAnimationAccusation.lstElements[(int)eTypeCounter].ptStart.Y + (int)(cAnimationAccusation.lstElements[(int)eTypeCounter].dblTravelDistance * ((double)cAnimationAccusation.lstElements[(int)eTypeCounter].intStep / (double)cAnimationAccusation.lstElements[(int)eTypeCounter].intMaxSteps) * Math.Sin(cAnimationAccusation.lstElements[(int)eTypeCounter].dblTravelAngle));

					Point ptTL = new Point(cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height / 2);
					g.DrawImage(cAnimationAccusation.lstElements[(int)eTypeCounter].bmpGray, ptTL.X, ptTL.Y);
				}
			}

			picBoard.Image = bmpTemp; picBoard.Refresh();

			if (bolQuitDraw)
			{
				// draw the three elements in the foreground (base Accusation image has accusing-suspect & bubble)
				// gray foreground
				cAnimationAccusation.bmpAccusationForegroundGray = new Bitmap(cAnimationAccusation.bmpAccusationBoard.Width, cAnimationAccusation.bmpAccusationBoard.Height);

				using (Graphics g = Graphics.FromImage(cAnimationAccusation.bmpAccusationForegroundGray))
				{
					g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, cAnimationAccusation.bmpAccusationForegroundGray.Width, cAnimationAccusation.bmpAccusationForegroundGray.Height));


					for (enuCardType eTypeCounter = (enuCardType)0; eTypeCounter < enuCardType._numCardTypes; eTypeCounter++)
						g.DrawImage(cAnimationAccusation.lstElements[(int)eTypeCounter].bmpGray, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height / 2);
				}

				cAnimationAccusation.bmpAccusationForegroundGray.MakeTransparent(Color.White);

				// colored foreground
				cAnimationAccusation.bmpAccusationForeground = new Bitmap(cAnimationAccusation.bmpAccusationBoard.Width, cAnimationAccusation.bmpAccusationBoard.Height);

				using (Graphics g = Graphics.FromImage(cAnimationAccusation.bmpAccusationForeground))
				{
					g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, cAnimationAccusation.bmpAccusationForeground.Width, cAnimationAccusation.bmpAccusationForeground.Height));

					for (enuCardType eTypeCounter = (enuCardType)0; eTypeCounter < enuCardType._numCardTypes; eTypeCounter++)
						g.DrawImage(cAnimationAccusation.lstElements[(int)eTypeCounter].bmp, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.X - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Width / 2, cAnimationAccusation.lstElements[(int)eTypeCounter].ptPos.Y - cAnimationAccusation.lstElements[(int)eTypeCounter].bmp.Height / 2);
				}
				cAnimationAccusation.bmpAccusationForeground.MakeTransparent(Color.White);

				eAccusationMode = enuAccuseAnimationMode.prepareToShowCards;
			}
			setDelayTimer(100);
		}

		Bitmap getAccusingSuspectAndBubbleImage(enuSuspects eSuspectMakingAccusation, classMurder  udrAccusation)
		{
			Bitmap bmpRetVal = new Bitmap(cAnimationAccusation.bmpAccusationBoard.Width, cAnimationAccusation.bmpAccusationBoard.Height);
						
			using (Graphics g = Graphics.FromImage(bmpRetVal))
			{
				g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, bmpRetVal.Width, bmpRetVal.Height));

				Rectangle recDest = new Rectangle(279, 252, 139, 100);
				Rectangle recSrc = new Rectangle(0, 0, 139, 100);
							
				Point ptSuspectTL = new Point(15, 420);
				double dblSuspectImageFactor = 1.3;
				int intSuspectImageSize = (int)(bmpSuspects[(int)eSuspectMakingAccusation].Width * dblSuspectImageFactor);
				ptSuggestionBubbleTL = new Point(ptSuspectTL.X + intSuspectImageSize-50, 405);
				recDest = new Rectangle(ptSuspectTL.X, ptSuspectTL.Y, intSuspectImageSize, intSuspectImageSize);
				recSrc = new Rectangle(0, 0, bmpSuspects[(int)eSuspectMakingAccusation].Width, bmpSuspects[(int)eSuspectMakingAccusation].Height);
				g.DrawImage(bmpSuspects[(int)eSuspectMakingAccusation], recDest, recSrc, GraphicsUnit.Pixel);

				recDest = new Rectangle(ptSuggestionBubbleTL.X, ptSuggestionBubbleTL.Y, bmpSuggestionBubble.Width+50, bmpSuggestionBubble.Height-60);
				recSrc = new Rectangle(0, 0, bmpSuggestionBubble.Width, bmpSuggestionBubble.Height);
				g.DrawImage(bmpSuggestionBubble, recDest, recSrc, GraphicsUnit.Pixel);

				Bitmap bmpText;
				Font fnt = new System.Drawing.Font("blackadder itc", 36);
				
				int intTop = 0;
				int intVLineSpacine = 45;
				int intLeftText = 75;
				int intTabText = 190;

				bmpText = getTextImage("I accuse",fnt);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage(udrAccusation.eSuspect.ToString(), new Font(fnt.Name, fnt.Size, FontStyle.Italic | FontStyle.Underline), udrAccusation.eSuspect == enuSuspects.MrsWhite ? Color.Gray : clrSuspects[(int)udrAccusation.eSuspect]);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intTabText, ptSuggestionBubbleTL.Y + intTop + intVLineSpacine + 10, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage("in the", fnt);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop + 2 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage(udrAccusation.eRoom.ToString(), new Font(fnt.Name, fnt.Size, FontStyle.Italic | FontStyle.Underline));
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intTabText, ptSuggestionBubbleTL.Y + intTop + 3 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage("with the", fnt);
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intLeftText, ptSuggestionBubbleTL.Y + intTop + 4 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);

				bmpText = getTextImage(udrAccusation.eWeapon.ToString(), new Font(fnt.Name, fnt.Size, FontStyle.Italic | FontStyle.Underline));
				recDest = new Rectangle(ptSuggestionBubbleTL.X + intTabText, ptSuggestionBubbleTL.Y + intTop + 5 * intVLineSpacine, bmpText.Width, bmpText.Height);
				recSrc = new Rectangle(0, 0, bmpText.Width, bmpText.Height);
				g.DrawImage(bmpText, recDest, recSrc, GraphicsUnit.Pixel);
			}

			return bmpRetVal;
		}

		public void Accuse(enuSuspects eSuspectAccusing, classMurder  udrAccusation)
		{
			if (eMode != enuMode.Accuse)
			{
				cAnimationAccusation.eRestoreMode = eMode;
				eMode = enuMode.Accuse;
			}
            //btnAccuse.Enabled = pnlControls.Enabled = true;
            AccuseButtonEnabled = false;

			cAnimationAccusation.udrAccusation.eRoom = udrAccusation.eRoom;
			cAnimationAccusation.udrAccusation.eWeapon = udrAccusation.eWeapon;
			cAnimationAccusation.udrAccusation.eSuspect= udrAccusation.eSuspect;

			eAccusationMode = enuAccuseAnimationMode.drawAccusation;
		}

		enuAccuseAnimationMode eAccusationMode
		{
			get { return cAnimationAccusation._eMode; }
			set
			{
				if (cAnimationAccusation._eMode != value)
				{
					cAnimationAccusation._eMode = value;
					switch (cAnimationAccusation._eMode)
					{
						case enuAccuseAnimationMode.drawAccusation:
							cAnimationAccusation.bolInit = false;
							setDelayTimer(10);
							break;

						case enuAccuseAnimationMode.prepareToShowCards:
							cAnimationAccusation.bolInit = false;
							setDelayTimer(10);
							break;

						case enuAccuseAnimationMode.showCards:
							cAnimationAccusation.bolInit = false;
							break;

						case enuAccuseAnimationMode.hideCards:
							cAnimationAccusation.bolInit = false;
							break;

						case enuAccuseAnimationMode.retractCards:
							cAnimationAccusation.bolInit = false;
							break;

						case enuAccuseAnimationMode.withdrawAccusingSuspect:
							cAnimationAccusation.bolInit = false;
							break;

						case enuAccuseAnimationMode.showNewspaper:
							cAnimationAccusation.bolInit = false;
							setDelayTimer(10);
							break;
					}
				}
			}
		}

		void ShowAccuseOptions()
		{
			#region "init tray : cLibPicTraySuspects"
			{
				cLibPicTraySuspects.Options.Mirror = PicTray.enuMirror.none;
				cLibPicTraySuspects.Options.makeImagesTransparent = true;
				cLibPicTraySuspects.Options.PopUpClickPic = false;
				cLibPicTraySuspects.Options.SelectionMode = PicTray.enuSelectionMode.click;
				cLibPicTraySuspects.Options.TrayCenter = new Point(-3, 144);
				cLibPicTraySuspects.Options.Width = 355;
				cLibPicTraySuspects.Options.Height = 422;
				cLibPicTraySuspects.Options.Rotation.StepSize = 0.120951317163207;
				cLibPicTraySuspects.Options.Rotation.Interval = 27;
				cLibPicTraySuspects.Options.Rotation.Mode = PicTray.enuRotationMode.toSelected;
				cLibPicTraySuspects.Options.Ellipse.Angle = 1.77499984927823;
				cLibPicTraySuspects.Options.Ellipse.Radius_Height = 102;
				cLibPicTraySuspects.Options.Ellipse.Radius_Width = 119;
				cLibPicTraySuspects.Options.Front.Angle = 0.0816814089933346;
				cLibPicTraySuspects.Options.Front.UserSet = PicTray.enuFrontUserSet.none;
				cLibPicTraySuspects.Options.ImageSize.Height_MinMax = new PicTray.classMinMax(75, 250);
				cLibPicTraySuspects.Options.ImageSize.Width_MinMax = new PicTray.classMinMax(75, 151);
				cLibPicTraySuspects.Options.ImageSize.Size_Control = enuSizeControl.both;
				cLibPicTraySuspects.Options.Caption.Show = false;
				cLibPicTraySuspects.Options.Caption.Font = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular);
				cLibPicTraySuspects.Options.Caption.ForeColor = Color.FromArgb(255, 255, 255, 0);
				cLibPicTraySuspects.Options.Caption.BackColor = Color.FromArgb(255, 0, 0, 0);
			
				cLibPicTraySuspects.Left = picBoard.Left;
				cLibPicTraySuspects.Top = 0;
			}
			#endregion

			#region "init tray : cLibPicTrayWeapons"
			{
				cLibPicTrayWeapons.Options.Mirror = PicTray.enuMirror.horizontal;
				cLibPicTrayWeapons.Options.makeImagesTransparent = true;
				cLibPicTrayWeapons.Options.PopUpClickPic = false;
				cLibPicTrayWeapons.Options.SelectionMode = PicTray.enuSelectionMode.click;
				cLibPicTrayWeapons.Options.TrayCenter = new Point(-3, 144);
				cLibPicTrayWeapons.Options.Width = 355;
				cLibPicTrayWeapons.Options.Height = 422;
				cLibPicTrayWeapons.Options.Rotation.StepSize = 0.120951317163207;
				cLibPicTrayWeapons.Options.Rotation.Interval = 27;
				cLibPicTrayWeapons.Options.Rotation.Mode = PicTray.enuRotationMode.toSelected;
				cLibPicTrayWeapons.Options.Ellipse.Angle = 1.77499984927823;
				cLibPicTrayWeapons.Options.Ellipse.Radius_Height = 102;
				cLibPicTrayWeapons.Options.Ellipse.Radius_Width = 119;
				cLibPicTrayWeapons.Options.Front.Angle = 0.0816814089933346;
				cLibPicTrayWeapons.Options.Front.UserSet = PicTray.enuFrontUserSet.none;
				cLibPicTrayWeapons.Options.ImageSize.Height_MinMax = new PicTray.classMinMax(75, 250);
				cLibPicTrayWeapons.Options.ImageSize.Width_MinMax = new PicTray.classMinMax(75, 151);
				cLibPicTrayWeapons.Options.ImageSize.Size_Control = enuSizeControl.both;
				cLibPicTrayWeapons.Options.Caption.Show = false;
				cLibPicTrayWeapons.Options.Caption.Font = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular);
				cLibPicTrayWeapons.Options.Caption.ForeColor = Color.FromArgb(255, 255, 255, 0);
				cLibPicTrayWeapons.Options.Caption.BackColor = Color.FromArgb(255, 0, 0, 0);

				cLibPicTrayWeapons.Left = cLibPicTraySuspects.Left + cLibPicTraySuspects.Width;
				cLibPicTrayWeapons.Top = 0;
			}
			#endregion
			#region "init tray : cLibPicTrayRooms"
			
			cLibPicTrayRooms.Options.Mirror = PicTray.enuMirror.vertical;
			cLibPicTrayRooms.Options.makeImagesTransparent = false;
			cLibPicTrayRooms.Options.PopUpClickPic = false;
			cLibPicTrayRooms.Options.SelectionMode = PicTray.enuSelectionMode.click;
			cLibPicTrayRooms.Options.TrayCenter = new Point(350, 100);
			cLibPicTrayRooms.Options.Width = 705;
			cLibPicTrayRooms.Options.Height = 289;
			cLibPicTrayRooms.Options.Rotation.StepSize = 0.117809724509617;
			cLibPicTrayRooms.Options.Rotation.Interval = 27;
			cLibPicTrayRooms.Options.Rotation.Mode = PicTray.enuRotationMode.toSelected;
			cLibPicTrayRooms.Options.Ellipse.Angle = 0;
			cLibPicTrayRooms.Options.Ellipse.Radius_Height = 66;
			cLibPicTrayRooms.Options.Ellipse.Radius_Width = 290;
			cLibPicTrayRooms.Options.Front.Angle = 1.49225651045515;
			cLibPicTrayRooms.Options.Front.UserSet = PicTray.enuFrontUserSet.none;
			cLibPicTrayRooms.Options.ImageSize.Height_MinMax = new PicTray.classMinMax(50, 250);
			cLibPicTrayRooms.Options.ImageSize.Width_MinMax = new PicTray.classMinMax(50, 150);
			cLibPicTrayRooms.SizeControl = enuSizeControl.both;
			cLibPicTrayRooms.Options.Caption.Show = false;
			cLibPicTrayRooms.Options.Caption.Font = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular);
			cLibPicTrayRooms.Options.Caption.ForeColor = Color.FromArgb(255, 255, 255, 0);
			cLibPicTrayRooms.Options.Caption.BackColor = Color.FromArgb(255, 0, 0, 0);
			
			cLibPicTrayRooms.Top = cLibPicTraySuspects.Top + cLibPicTraySuspects.Height;
			cLibPicTrayRooms.Left = 0;
			#endregion
		
			cLibPicTrayRooms.SendToBack();
			cLibPicTraySuspects.SendToBack();
			cLibPicTrayWeapons.SendToBack();
			
			cLibPicTrayRooms.Visible = true;	
			cLibPicTraySuspects.Visible = true;
			cLibPicTrayWeapons.Visible = true;

			setPicTrayBackgroundImage(ref cLibPicTrayRooms);
			setPicTrayBackgroundImage(ref cLibPicTraySuspects);
			setPicTrayBackgroundImage(ref cLibPicTrayWeapons); 
			
			cLibPicTrayRooms.BringToFront();
			cLibPicTraySuspects.BringToFront();
			cLibPicTrayWeapons.BringToFront(); 

			btnAccuse_Ok.Top = cLibPicTrayRooms.Top - btnAccuse_Ok.Height + 40;
			btnAccuse_Ok.Left = (bmpBoard.Width - btnAccuse_Ok.Width) / 2;
			btnAccuse_Ok.Visible = true;
		}
		#endregion

		void setPicTrayBackgroundImage(ref classPicTray_V2 cLibTray)
		{
			Bitmap bmpTempTwo = new Bitmap(cLibTray.Width, cLibTray.Height);

			using (Graphics g = Graphics.FromImage(bmpTempTwo))
			{
				Rectangle recSrc = new Rectangle(cLibTray.Location, cLibTray.Size);
				Rectangle recDest = new Rectangle(0, 0, cLibTray.Width, cLibTray.Height);
				g.DrawImage((Bitmap)picBoard.Image, recDest, recSrc, GraphicsUnit.Pixel);
			}
		
			cLibTray.BackgroundImage = bmpTempTwo;
			cLibTray.RefreshTrayImage();
			cLibTray.Refresh();
		}

		public void GameOver()
		{
			eMode = enuMode.gameOver;
			//grbControls.Enabled = false;
			Bitmap bmpGameOver = new Bitmap(bmpGameBoard);			
			Bitmap bmpBanner =new Bitmap( Resources.Winner);
			bmpBanner.MakeTransparent();

			Bitmap bmpFace = new Bitmap((int)(bmpSuspects[intSuspectTurn].Width), (int)(bmpSuspects[intSuspectTurn].Height));
			using (Graphics g = Graphics.FromImage(bmpFace))
			{
				g.FillRectangle(new SolidBrush(bmpSuspects[intSuspectTurn].GetPixel(bmpSuspects[intSuspectTurn].Width / 2, 0)), new Rectangle(0, 0, bmpFace.Width, bmpFace.Height));
				g.DrawImage(bmpSuspects[intSuspectTurn], new Rectangle (0,0, bmpFace.Width, bmpFace.Height), new Rectangle(0,0, bmpSuspects[intSuspectTurn].Width, bmpSuspects[intSuspectTurn].Height), GraphicsUnit.Pixel);
			}
			bmpFace.MakeTransparent(bmpFace.GetPixel(0, 0));

			using (Graphics g = Graphics.FromImage(bmpGameOver))
			{
				// draw face
				double dblSizeFactor = 2.1;
				Size  szFace= new System.Drawing.Size((int)(bmpFace.Width *dblSizeFactor), (int)(bmpFace.Height *dblSizeFactor));
				Rectangle recDest = new Rectangle((bmpGameOver.Width - szFace.Width) / 2, (bmpGameOver.Height - szFace.Height)/2, szFace.Width, szFace.Height);
				Rectangle recSrc = new Rectangle(0, 0, bmpFace.Width, bmpFace.Height);
				g.DrawImage(bmpFace, recDest, recSrc, GraphicsUnit.Pixel);

				// draw banner
				recDest = new Rectangle((bmpGameOver.Width - bmpBanner.Width) / 2, (int)(bmpGameOver.Height *.6), bmpBanner.Width, bmpBanner.Height);
				recSrc = new Rectangle(0, 0, bmpBanner.Width, bmpBanner.Height);
				g.DrawImage(bmpBanner, recDest, recSrc, GraphicsUnit.Pixel);
			}
			setDelayTimer(2000);
			pnlNotebook.BringToFront();
			picBoard.Image = bmpGameOver; picBoard.Refresh();

		}

		public void showAllowableMoves()
		{
			eMode = enuMode.showAllowableMoves;

			//pnlControls.Enabled 
				//= btnEndTurn.Enabled 
				 EndTurnButtonEnabled
                = cSuspects[intSuspectTurn].setAllowableMoves();

			drawBoard();
		}
		
		void drawBoard()
		{
			bmpGameBoard = new Bitmap(bmpBoard);
			classSuspect cS = cSuspects[intSuspectTurn];

			Pen pTrim = new Pen(clrSuspects[intSuspectTurn], 4);
			Pen pWhite = new Pen(Color.White, 1);
			using (Graphics g = Graphics.FromImage(bmpGameBoard))
			{
				// draw allowable moves
				for (int intX = 0; intX < sz.Width; intX++)
				{
					for (int intY = 0; intY < sz.Height; intY++)
					{
						if (cS.cSEAllowableMoves[intX, intY] != null)
						{
							g.DrawRectangle(pWhite, new Rectangle(ptBoardTL.X + intX * 28 + 3, ptBoardTL.Y + intY * 28 + 3, 22, 22));
							g.DrawRectangle(pTrim, new Rectangle(ptBoardTL.X + intX * 28 + 6, ptBoardTL.Y + intY * 28 + 6, 17, 17));
							g.DrawRectangle(pWhite, new Rectangle(ptBoardTL.X + intX * 28 + 8, ptBoardTL.Y + intY * 28 + 8, 12, 12));
						}
					}
				}

				// draw center back of card				
				Point ptCenter = getRoomCenter(enuRooms._numRooms);
				Point ptTLCard = new Point(ptCenter.X - cCardUnknown.cBmp.getImage(0).Width / 2, ptCenter.Y - cCardUnknown.cBmp.getImage(0).Height / 2);
				Rectangle recDestCard = new Rectangle(ptTLCard, cCardUnknown.cBmp.getImage(0).Size);
				Rectangle recSrcCard = new Rectangle(0, 0, cCardUnknown.cBmp.getImage(0).Width, cCardUnknown.cBmp.getImage(0).Height);
				g.DrawImage(cCardUnknown.cBmp.getImage(0), recDestCard, recSrcCard, GraphicsUnit.Pixel);				

				// draw weapons
				Size szWeapon = new System.Drawing.Size(35, 35);
				Rectangle recSrc = new Rectangle(0, 0, bmpWeapons_Board[0].Width, bmpWeapons_Board[0].Height);
				for (enuWeapons eWeaponCounter = (enuWeapons)0; eWeaponCounter < enuWeapons._numWeapons; eWeaponCounter++)
				{
					if (cWeapons[(int)eWeaponCounter].eRoom != enuRooms.start
						&& !(eMode == enuMode.animateSummonWeapon && eWeaponCounter == cSuggestion.eWeapon)) // do not draw the weapon if it is being animated in 'summon weapon' mode
					{ // in a room
						Point ptPieceCenter = getWeaponGraphicPositionInRoom(eWeaponCounter);
						Point ptPieceTL = new Point(ptPieceCenter.X - szWeapon.Width / 2, ptPieceCenter.Y - szWeapon.Height / 2);
						Rectangle recDest = new Rectangle(ptPieceTL, szWeapon);

						g.DrawImage(new Bitmap(bmpWeapons_Board[(int)eWeaponCounter]), recDest, recSrc, GraphicsUnit.Pixel);
					}
				}

				// draw pieces
				for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				{
					if (!(eMode == enuMode.animateSummonSuspect && eSuspectCounter == cSuggestion.eSuspect)// do not draw the suspect if it is being animated in 'summon suspect' mode
						&& !(eMode == enuMode.animateSecretPassage && eSuspectCounter == (enuSuspects)intSuspectTurn)) // do not draw the suspect if it is being animated in 'secret passage' mode
					{
						if (cSuspects[(int)eSuspectCounter].eRoom == enuRooms.tiles)
						{ // on a tile
							g.DrawImage(bmpPieces[(int)eSuspectCounter], new Point(ptBoardTL.X + cSuspects[(int)eSuspectCounter].ptTile.X * 28 + 2, ptBoardTL.Y + cSuspects[(int)eSuspectCounter].ptTile.Y * 28 + 2));
						}
						else if (cSuspects[(int)eSuspectCounter].eRoom != enuRooms.start)
						{ // in a room
							Point ptPieceCenter = getPieceGraphicPositionInRoom(eSuspectCounter);
							Point ptPieceTL = new Point(ptPieceCenter.X - bmpPieces[(int)eSuspectCounter].Width / 2, ptPieceCenter.Y - bmpPieces[(int)eSuspectCounter].Height / 2);
							g.DrawImage(bmpPieces[(int)eSuspectCounter], ptPieceTL);
						}
					}
				}
			}

			picBoard.Image = bmpGameBoard; picBoard.Refresh();
		}	

		private void btnSuggestion_Click(object sender, EventArgs e)
		{
			if (cSuspects[intSuspectTurn].bolPlayerControlled && !cSuspects[intSuspectTurn].bolEliminated)
				eMode = enuMode.Suggest;
		}

		public void Suggest()
		{
            //btnSuggest.Enabled = false;
            SuggestButtonEnabled = false;
			//pnlControls.Enabled = false;
			drawBoard();

			#region "cLibPicTraySuspects make suggestion"
			cLibPicTraySuspects.Location = new Point(0, 0);
			cLibPicTraySuspects.Options.Mirror = PicTray.enuMirror.none;
			cLibPicTraySuspects.Options.makeImagesTransparent = true;
			cLibPicTraySuspects.Options.PopUpClickPic = false;
			cLibPicTraySuspects.Options.SelectionMode = PicTray.enuSelectionMode.click;
			cLibPicTraySuspects.Options.TrayCenter = new Point(47, 193);
			cLibPicTraySuspects.Options.Width = 355;
			cLibPicTraySuspects.Options.Height = 385;
			cLibPicTraySuspects.Options.Rotation.StepSize = 0.119380520836412;
			cLibPicTraySuspects.Options.Rotation.Interval = 27;
			cLibPicTraySuspects.Options.Rotation.Mode = PicTray.enuRotationMode.toSelected;
			cLibPicTraySuspects.Options.Ellipse.Angle = 1.21579635693925;
			cLibPicTraySuspects.Options.Ellipse.Radius_Height = 67;
			cLibPicTraySuspects.Options.Ellipse.Radius_Width = 126;
			cLibPicTraySuspects.Options.Front.Angle = 0;
			cLibPicTraySuspects.Options.Front.UserSet = PicTray.enuFrontUserSet.none;
			cLibPicTraySuspects.Options.ImageSize.Height_MinMax = new PicTray.classMinMax(50, 150);
			cLibPicTraySuspects.Options.ImageSize.Width_MinMax = new PicTray.classMinMax(50, 150);
			cLibPicTraySuspects.Options.Caption.Show = false;
			cLibPicTraySuspects.Options.Caption.Font = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular);
			cLibPicTraySuspects.Options.Caption.ForeColor = Color.FromArgb(255, 255, 255, 0);
			cLibPicTraySuspects.Options.Caption.BackColor = Color.FromArgb(255, 0, 0, 0);

			cLibPicTraySuspects.tmrRotate.Enabled = true;
			#endregion

			#region "cLibPicTrayWeapons make suggestion"
			cLibPicTrayWeapons.Options.BackColor = Color.Transparent;
			cLibPicTrayWeapons.Options.Mirror = PicTray.enuMirror.horizontal;
			cLibPicTrayWeapons.Options.makeImagesTransparent = true;
			cLibPicTrayWeapons.Options.PopUpClickPic = false;
			cLibPicTrayWeapons.Options.SelectionMode = PicTray.enuSelectionMode.click;
			cLibPicTrayWeapons.Options.TrayCenter = new Point(60, 210);
			cLibPicTrayWeapons.Options.Width = 355;
			cLibPicTrayWeapons.Options.Height = 385;
			cLibPicTrayWeapons.Options.Rotation.StepSize = 0.119380520836412;
			cLibPicTrayWeapons.Options.Rotation.Interval = 27;
			cLibPicTrayWeapons.Options.Rotation.Mode = PicTray.enuRotationMode.toSelected;
			cLibPicTrayWeapons.Options.Ellipse.Angle = 1.01579635693925;// 1.21579635693925;
			cLibPicTrayWeapons.Options.Ellipse.Radius_Height = 67;
			cLibPicTrayWeapons.Options.Ellipse.Radius_Width = 126;
			cLibPicTrayWeapons.Options.Front.Angle = 0;
			cLibPicTrayWeapons.Options.Front.UserSet = PicTray.enuFrontUserSet.none;
			cLibPicTrayWeapons.Options.ImageSize.Height_MinMax = new PicTray.classMinMax(50, 150);
			cLibPicTrayWeapons.Options.ImageSize.Width_MinMax = new PicTray.classMinMax(50, 150);
			cLibPicTrayWeapons.Options.Caption.Show = false;
			cLibPicTrayWeapons.Options.Caption.Font = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular);
			cLibPicTrayWeapons.Options.Caption.ForeColor = Color.FromArgb(255, 255, 255, 0);
			cLibPicTrayWeapons.Options.Caption.BackColor = Color.FromArgb(255, 0, 0, 0);

			cLibPicTrayWeapons.tmrRotate.Enabled = true;
			#endregion

			DrawSuggestingSuspect();
			writeSuggestion();

			setUpCLibPicTrayChooseSuspect();
			setUpCLibPicTrayChooseWeapon();

			picBoard.Refresh();
		}

		void DrawRespondingSuspect(enuSuspects eSuspectResponding)
		{
			Bitmap bmpTemp = new Bitmap(bmpSuggestionBoard);
			ptResponseBubbleTL = new Point(50, 0);
			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				g.DrawImage(bmpSuspects[(int)eSuspectResponding], new Rectangle(ptResponseBubbleTL.X + bmpResponseBubble.Width, 0, 220, 220), new Rectangle(0, 0, bmpSuspects[(int)eSuspectResponding].Width, bmpSuspects[(int)eSuspectResponding].Height), GraphicsUnit.Pixel);
				g.DrawImage(bmpResponseBubble, ptResponseBubbleTL);
			}

			if (cButtons[(int)enuButtons.RespondToSuggestion_Ok] == null)
				cButtons[(int)enuButtons.RespondToSuggestion_Ok] = new classButton(this,
																			   ref picBoard,
																				   enuMode.respondToSuggestion,
																			   new Point(ptResponseBubbleTL.X + bmpResponseBubble.Width - 120, ptResponseBubbleTL.Y + bmpResponseBubble.Height - 50),
																				   Color.Black,
																				   "Ok",
																			   new Font("blackadder itc", 26));
			picBoard.Image = bmpTemp; picBoard.Refresh();
			cButtons[(int)enuButtons.RespondToSuggestion_Ok].eButtonName = enuButtons.RespondToSuggestion_Ok;
			cButtons[(int)enuButtons.RespondToSuggestion_Ok].draw();

			autoProceedEnabled = bolAutoProceed;
		}

		Bitmap getRoomBackGroundImage(enuRooms eRoomRequested)
		{
			Bitmap bmpRetVal = new Bitmap(139, 100);

			Rectangle recDest = new Rectangle(0, 0, 139, 100);
			Point ptRoomBackground = new Point(0, 0);

			switch (cSuspects[intSuspectTurn].eRoom)
			{
				case enuRooms.Study:
					ptRoomBackground = new Point(41, 17);
					break;

				case enuRooms.Hall:
					ptRoomBackground = new Point(288, 52);
					break;

				case enuRooms.Lounge:
					ptRoomBackground = new Point(530, 38);
					break;

				case enuRooms.DiningRoom:
					ptRoomBackground = new Point(519, 280);
					break;

				case enuRooms.Kitchen:
					ptRoomBackground = new Point(544, 530);
					break;

				case enuRooms.BallRoom:
					ptRoomBackground = new Point(293, 513);
					break;

				case enuRooms.Conservatory:
					ptRoomBackground = new Point(39, 568);
					break;

				case enuRooms.BilliardRoom:
					ptRoomBackground = new Point(37, 356);
					break;

				case enuRooms.Library:
					ptRoomBackground = new Point(55, 195);
					break;
			}

			Rectangle recSrc = new Rectangle(ptRoomBackground.X, ptRoomBackground.Y, 139, 100);
			using (Graphics g = Graphics.FromImage(bmpRetVal))
				g.DrawImage(bmpBoard, recDest, recSrc, GraphicsUnit.Pixel);

			return bmpRetVal;
		}

		void DrawSuggestingSuspect()
		{
			Bitmap bmpTemp = new Bitmap(picBoard.Image);

			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				Rectangle recDest = new Rectangle(279, 252, 139, 100);				
				Rectangle recSrc = new Rectangle(0,0, 139, 100);

				g.DrawImage(getRoomBackGroundImage(cSuspects[intSuspectTurn].eRoom), recDest, recSrc, GraphicsUnit.Pixel);

				Size szWeapon = new System.Drawing.Size(35, 35);
				recSrc = new Rectangle(0, 0, bmpWeapons_Board[0].Width, bmpWeapons_Board[0].Height);
				for (enuWeapons eWeaponCounter = 0; eWeaponCounter < enuWeapons._numWeapons; eWeaponCounter++)
				{
					if (cWeapons[(int)eWeaponCounter].eRoom == enuRooms._numRooms)
					{					// at center of map -> draw on top of room image
						Point ptPieceCenter = getWeaponGraphicPositionInRoom(eWeaponCounter);
						Point ptPieceTL = new Point(ptPieceCenter.X - szWeapon.Width / 2, ptPieceCenter.Y - szWeapon.Height / 2);
						recDest = new Rectangle(ptPieceTL, szWeapon);
						//bmpTemp.Save(@"c:\debug\bmptemp.png");
						g.DrawImage(new Bitmap(bmpWeapons_Board[(int)eWeaponCounter]), recDest, recSrc, GraphicsUnit.Pixel);
					}
				}

				Point ptSuspectTL = new Point(0, 400);
				double dblSuspectImageFactor = 2;
				int intSuspectImageSize = (int)(bmpSuspects[intSuspectTurn].Width * dblSuspectImageFactor);
				ptSuggestionBubbleTL = new Point(ptSuspectTL.X + intSuspectImageSize - 50, 365);
				recDest = new Rectangle(ptSuspectTL.X, ptSuspectTL.Y, intSuspectImageSize, intSuspectImageSize);
				recSrc = new Rectangle(0, 0, bmpSuspects[intSuspectTurn].Width, bmpSuspects[intSuspectTurn].Height);
				g.DrawImage(bmpSuspects[intSuspectTurn], recDest, recSrc, GraphicsUnit.Pixel);

				recDest = new Rectangle(ptSuggestionBubbleTL.X, ptSuggestionBubbleTL.Y, bmpSuggestionBubble.Width, bmpSuggestionBubble.Height);
				recSrc = new Rectangle(0, 0, bmpSuggestionBubble.Width, bmpSuggestionBubble.Height);
				g.DrawImage(bmpSuggestionBubble, recDest, recSrc, GraphicsUnit.Pixel);
			}
			//bmpSuggestionBubble.Save(@"c:\debug\bmpSuggestionBubble.png");
			picBoard.Image = bmpTemp;
			Font fntButtons = new Font("blackadder itc", 26);

			if (cButtons[(int)enuButtons.MakeSuggestion_Cancel] == null)
				cButtons[(int)enuButtons.MakeSuggestion_Cancel] = new classButton(this,
																				  ref picBoard,
																					  enuMode.Suggest,
																				  new Point(ptSuggestionBubbleTL.X + 225, ptSuggestionBubbleTL.Y + 290),
																					  Color.Black,
																					  "Cancel",
																					  fntButtons);
			if (cSuspects[intSuspectTurn].bolPlayerControlled)
				cButtons[(int)enuButtons.MakeSuggestion_Cancel].draw();


			if (cButtons[(int)enuButtons.MakeSuggestion_Ok] == null)
				cButtons[(int)enuButtons.MakeSuggestion_Ok] = new classButton(this,
																			  ref picBoard,
																				  enuMode.Suggest,
																			  new Point(cButtons[(int)enuButtons.MakeSuggestion_Cancel].pt.X + cButtons[(int)enuButtons.MakeSuggestion_Cancel].sz.Width + 5,
																						cButtons[(int)enuButtons.MakeSuggestion_Cancel].pt.Y),
																				  Color.Black,
																				  "Ok",
																				  fntButtons);
			if (cSuspects[intSuspectTurn].bolPlayerControlled)
				cButtons[(int)enuButtons.MakeSuggestion_Ok].draw(); 
		}

		public void selectedSuspectChange()
		{
			setBtnChooseSuspectColorAndText();
		}

		private void btnEndTurn_Click(object sender, EventArgs e)
		{
			if (cSuspects[intSuspectTurn].bolPlayerControlled && !cSuspects[intSuspectTurn].bolEliminated)
				eMode = enuMode.endTurn;
		}

		void drawPlayerCards()
		{
			Bitmap bmpNotes = new Bitmap(picNotebook.Image);
			using (Graphics g = Graphics.FromImage(bmpNotes))
			{
				double dblAspectRatioXOverY = ((double)cCards[0].cBmp.getImage(0).Width / (double)cCards[0].cBmp.getImage(0).Height);
				int intHeight = 24;
				int intWidth = (int)((double)intHeight * dblAspectRatioXOverY);

				classSuspect cSuspectPlayer = getPlayerSuspect();


				for (int intCardCounter = 0; intCardCounter < cSuspects[intSuspectTurn].cCards.Length; intCardCounter++)
				{
					Point ptDest = new Point(2, cPlayerNotes[0, (int)cSuspectPlayer.cCards[intCardCounter].eCardName].pt.Y);
					Size szDest = new System.Drawing.Size(intWidth, intHeight);
					Rectangle recDest = new Rectangle(ptDest, szDest);
					Rectangle recSrc = new Rectangle(0, 0, cCards[0].cBmp.getImage(0).Width + 1, cCards[0].cBmp.getImage(0).Height + 1);
					g.DrawImage(cSuspectPlayer.cCards[intCardCounter].cBmp.getImage(0), recDest, recSrc, GraphicsUnit.Pixel);
				}
			}

			picNotebook.Image = bmpNotebook = bmpNotes; picNotebook.Refresh();
		}

		classSuspect getPlayerSuspect()
		{
			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				if (cSuspects[(int)eSuspectCounter].bolPlayerControlled)
					return cSuspects[(int)eSuspectCounter];
			return cSuspects[0];
		}

		#region "roll die"
		public void rollDie()
		{
            //btnRollDie.Enabled = false;
            RollDieButtonEnabled = false;
			SuggestButtonEnabled = true;
			eMode = enuMode.rollDie_begin;
			cRollDieInfo.intDieValue = 0;
			cRollDieInfo.intDieWidth = 50;
			cRollDieInfo.intMaxVel = 6;
			cRollDieInfo.intVelFactor = 20;
			cRollDieInfo.dblVelocityAttenuationFactor = 0.90;
			cRollDieInfo.intRightMost = picDieBox.Width;
			cRollDieInfo.intLowerMost = picDieBox.Height;

			cSuspects[intSuspectTurn].bolCanSuggest = false;

			cRollDieInfo.dblVel = (double)(cRollDieInfo.intMaxVel * cRollDieInfo.intVelFactor / 2) * rnd.NextDouble() + (cRollDieInfo.intMaxVel * cRollDieInfo.intVelFactor / 2);

			cRollDieInfo.dblAngle = 0.0;
			cRollDieInfo.ptDie = new Point(0, 0);
			switch (cSuspects[intSuspectTurn].eName)
			{
				case enuSuspects.MissScarlet:
					cRollDieInfo.dblAngle = 10.0 / 18.0 * Math.PI;
					cRollDieInfo.ptDie = new Point((int)(picDieBox.Width * .7 - cRollDieInfo.intDieWidth / 2.0), 0);
					break;
				case enuSuspects.ColMustard:
					cRollDieInfo.dblAngle = 7.0 / 8.8 * Math.PI;
					cRollDieInfo.ptDie = new Point(picDieBox.Width - cRollDieInfo.intDieWidth, (int)(picDieBox.Height * .4 - cRollDieInfo.intDieWidth / 2));
					break;

				case enuSuspects.MrsWhite:
					cRollDieInfo.dblAngle = 26.0 / 18.0 * Math.PI;
					cRollDieInfo.ptDie = new Point((int)(picDieBox.Width * .7 - cRollDieInfo.intDieWidth / 2), picDieBox.Height - cRollDieInfo.intDieWidth);
					break;

				case enuSuspects.RevGreen:
					cRollDieInfo.dblAngle = 28.0 / 18.0 * Math.PI;
					cRollDieInfo.ptDie = new Point((int)(picDieBox.Width * .3 - cRollDieInfo.intDieWidth / 2), picDieBox.Height - cRollDieInfo.intDieWidth);
					break;

				case enuSuspects.MrsPeacock:
					cRollDieInfo.dblAngle = 35.0 / 18.0 * Math.PI;
					cRollDieInfo.ptDie = new Point(0, (int)(picDieBox.Height * .6 - cRollDieInfo.intDieWidth / 2));
					break;

				case enuSuspects.ProfPlum:
					cRollDieInfo.dblAngle = 1.0 / 18.0 * Math.PI;
					cRollDieInfo.ptDie = new Point(0, (int)(picDieBox.Height * .4 - cRollDieInfo.intDieWidth / 2));
					break;
			}

			cRollDieInfo.dblXVel = cRollDieInfo.dblVel * Math.Cos(cRollDieInfo.dblAngle);
			cRollDieInfo.dblYVel = cRollDieInfo.dblVel * Math.Sin(cRollDieInfo.dblAngle);

			double dblStartVel = Math.Sqrt(cRollDieInfo.dblXVel * cRollDieInfo.dblXVel + cRollDieInfo.dblYVel * cRollDieInfo.dblYVel);
			double dblMinVel = 2.0;
			cRollDieInfo.intRollCount = (int)(Math.Log(dblMinVel / dblStartVel) / Math.Log(cRollDieInfo.dblVelocityAttenuationFactor));
			cRollDieInfo.intRollAnimation = 0;
			//
			eMode = enuMode.rollDie_animate;
		}

		void rollDie_animate()
		{
			Bitmap bmpDieBox = new Bitmap(bmpBaize,picDieBox.Size);
			if (cRollDieInfo.bmpCurrent == null)
				cRollDieInfo.bmpCurrent = cBmpDie[1].getImage(1);

			Rectangle recDieSrc = new Rectangle(0, 0, cRollDieInfo.bmpCurrent.Width, cRollDieInfo.bmpCurrent.Height);

			Rectangle recDieBox = new Rectangle(0, 0, picDieBox.Width, picDieBox.Height);
			Rectangle recDieDest;
			if (cRollDieInfo.intRollAnimation < cRollDieInfo.intRollCount)
			{
				cRollDieInfo.intRollAnimation++;
				cRollDieInfo.intDieValue = (int)(rnd.NextDouble() * 1000) % 6 + 1;
				int intSleepTime = 0;
				using (Graphics g = Graphics.FromImage(bmpDieBox))
				{
					g.DrawImage(bmpBaize, recDieBox, recDieBox, GraphicsUnit.Pixel);
					cRollDieInfo.bmpCurrent = cBmpDie[cRollDieInfo.intDieValue].getImage(cRollDieInfo.intImageIndex);
					recDieDest = new Rectangle(cRollDieInfo.ptDie.X - cRollDieInfo.bmpCurrent.Width / 2, cRollDieInfo.ptDie.Y - cRollDieInfo.bmpCurrent.Height / 2, cRollDieInfo.bmpCurrent.Width, cRollDieInfo.bmpCurrent.Height);
					g.DrawImage(cRollDieInfo.bmpCurrent, recDieDest, recDieSrc, GraphicsUnit.Pixel);
					picDieBox.Image = bmpDieBox;
					picDieBox.Refresh();
					
					int intMinSleep = (int)((double)cRollDieInfo.intVelFactor * (double)cRollDieInfo.intMaxVel) + 1;
					intSleepTime = intMinSleep - (int)(Math.Sqrt(cRollDieInfo.dblXVel * cRollDieInfo.dblXVel + cRollDieInfo.dblYVel * cRollDieInfo.dblYVel));

					cRollDieInfo.intDieValue =  (int)(rnd.NextDouble() * 1000) % 6 + 1;

					if ((int)(rnd.NextDouble() * 1000) % intSleepTime < 300)
					{
						if ((int)(rnd.NextDouble() * 1000) % 2 == 0)
							cRollDieInfo.intImageIndex = (int)(cRollDieInfo.intImageIndex + 1) % 16;
						else
							cRollDieInfo.intImageIndex = (int)(cRollDieInfo.intImageIndex + 15) % 16;
					}
					cRollDieInfo.bmpCurrent = cBmpDie[cRollDieInfo.intDieValue].getImage(cRollDieInfo.intImageIndex);

					cRollDieInfo.dblXVel *= cRollDieInfo.dblVelocityAttenuationFactor;					

					cRollDieInfo.ptDie.X += (int)cRollDieInfo.dblXVel;
					if (cRollDieInfo.ptDie.X - cRollDieInfo.bmpCurrent .Width/2< 0)
					{
						int intDifference = cRollDieInfo.ptDie.X - cRollDieInfo.bmpCurrent.Width / 2;
						cRollDieInfo.ptDie.X = cRollDieInfo.bmpCurrent.Width / 2 - intDifference;

						cRollDieInfo.dblXVel *= -1;
					}
					else if (cRollDieInfo.ptDie.X + cRollDieInfo.bmpCurrent .Width/2 > cRollDieInfo.intRightMost)
					{
						int intDifference = cRollDieInfo.intRightMost - (cRollDieInfo.ptDie.X + cRollDieInfo.bmpCurrent.Width / 2);
						cRollDieInfo.ptDie.X = cRollDieInfo.intRightMost + intDifference - cRollDieInfo.bmpCurrent.Width/2;

						cRollDieInfo.dblXVel *= -1;
					}

					cRollDieInfo.dblYVel *= cRollDieInfo.dblVelocityAttenuationFactor;
					cRollDieInfo.ptDie.Y += (int)cRollDieInfo.dblYVel;
					if (cRollDieInfo.ptDie.Y - cRollDieInfo.bmpCurrent.Height /2 < 0)
					{
						int intDifference = cRollDieInfo.ptDie.Y - cRollDieInfo.bmpCurrent.Height / 2;
						cRollDieInfo.ptDie.Y = cRollDieInfo.bmpCurrent.Height / 2 - intDifference;

						cRollDieInfo.dblYVel *= -1;
					}
					else if (cRollDieInfo.ptDie.Y + cRollDieInfo.bmpCurrent.Height/2 > cRollDieInfo.intLowerMost)
					{
						int intDifference = cRollDieInfo.intLowerMost - (cRollDieInfo.ptDie.Y + cRollDieInfo.bmpCurrent.Height / 2);
						cRollDieInfo.ptDie.Y = cRollDieInfo.intLowerMost - cRollDieInfo.bmpCurrent.Height / 2 + intDifference;

						cRollDieInfo.dblYVel *= -1;
					}


					double dblVel = Math.Sqrt(Math.Pow(cRollDieInfo.dblXVel, 2) + Math.Pow(cRollDieInfo.dblYVel, 2));
					if (dblVel < cBmpDie[1].getImage(0).Width)
						cRollDieInfo.intRollAnimation = cRollDieInfo.intRollCount; // quit when moving too slow


				}
				setDelayTimer(intSleepTime);
				return;
			}
			else
				eMode = enuMode.rollDie_end;
		}

		void rollDie_End()
		{
			Bitmap bmpDieBox = new Bitmap(bmpBaize);
			Rectangle recDieSrc = new Rectangle(0, 0, cRollDieInfo.bmpCurrent.Width + 1, cRollDieInfo.bmpCurrent.Height + 1);
			Rectangle recDieBox = new Rectangle(0, 0, picDieBox.Width, picDieBox.Height);
			Rectangle recDieDest;
			using (Graphics g = Graphics.FromImage(bmpDieBox))
			{
				g.DrawImage(bmpBaize, recDieBox, recDieBox, GraphicsUnit.Pixel);
				recDieDest = new Rectangle(cRollDieInfo.ptDie.X - cRollDieInfo.bmpCurrent.Width/2, cRollDieInfo.ptDie.Y - cRollDieInfo.bmpCurrent.Height/2, cRollDieInfo.bmpCurrent.Width, cRollDieInfo.bmpCurrent.Height);
				g.DrawImage(cRollDieInfo.bmpCurrent, recDieDest, recDieSrc, GraphicsUnit.Pixel);
			}

			picDieBox.Image = bmpDieBox;
			picDieBox.Refresh();

			if (!cSuspects[intSuspectTurn].bolPlayerControlled)
			{
				showAllowableMoves();
				setDelayTimer(500);
			}
			else
				showAllowableMoves();
		}
		#endregion

		private void btnRollDie_Click(object sender, EventArgs e)
		{
			if (cSuspects[intSuspectTurn].bolPlayerControlled && !cSuspects[intSuspectTurn].bolEliminated)
			{
				//pnlControls.Enabled = false;
				rollDie();
			}
		}

		public void ProveSuggestion()
		{
			// display appropriate images on pic trays
			cLibPicTraySuspects.setSelectedImage((int)cSuggestion.eSuspect);
			cLibPicTraySuspects.Angle = cLibPicTraySuspects.FrontAngle - cLibPicTraySuspects.Tray[(int)cSuggestion.eSuspect].angleOnTray;
			cLibPicTraySuspects.RefreshTrayImage();

			cLibPicTrayWeapons.setSelectedImage((int)cSuggestion.eWeapon);
			cLibPicTrayWeapons.Angle = cLibPicTrayWeapons.FrontAngle - cLibPicTrayWeapons.Tray[(int)cSuggestion.eWeapon].angleOnTray;
			cLibPicTrayWeapons.RefreshTrayImage();
			cSuggestionAnimation.intProveSuggestionCycleCounter = 1;

			eMode = enuMode.respondToSuggestion;
			cSuspects[intSuspectTurn].bolCanSuggest = false;
			cSuspects[intSuspectTurn].bolHasNotYetMadeASuggestionThisTurn = true;

			bmpSuggestionBoard = new Bitmap(picBoard.Image);

			// erase pic trays & draw their images onto the bmpSuggestionBoard
			using (Graphics g = Graphics.FromImage(bmpSuggestionBoard))
			{
				Rectangle recSrc, recDest;

				recSrc = new Rectangle(0, 0, cLibPicTraySuspects.Width, cLibPicTraySuspects.Height);
				recDest = new Rectangle(cLibPicTraySuspects.Left, cLibPicTraySuspects.Top, cLibPicTraySuspects.Width, cLibPicTraySuspects.Height);
				g.DrawImage(new Bitmap(cLibPicTraySuspects.Image), recDest, recSrc, GraphicsUnit.Pixel);
				cLibPicTraySuspects.Visible = false;

				recSrc = new Rectangle(0, 0, cLibPicTrayWeapons.Width, cLibPicTrayWeapons.Height);
				recDest = new Rectangle(cLibPicTrayWeapons.Left, cLibPicTrayWeapons.Top, cLibPicTrayWeapons.Width, cLibPicTrayWeapons.Height);
				g.DrawImage(new Bitmap(cLibPicTrayWeapons.Image), recDest, recSrc, GraphicsUnit.Pixel);
				cLibPicTrayWeapons.Visible = false;
			}

			cSuggestionAnimation.intProveSuggestionCycleCounter = 1;
			ProveSuggestion_CycleThroughSuspects();
		}

   

        void ProveSuggestion_CycleThroughSuspects()
		{
			// cycle through all suspects
			enuSuspects eSuspectCounter = (enuSuspects)(((int)cSuspects[intSuspectTurn].eName + cSuggestionAnimation.intProveSuggestionCycleCounter) % (int)enuSuspects._numSuspects);
			if (cSuspects[(int)eSuspectCounter].bolPlayerControlled)
			{
				eMode = enuMode.playerChoosesCardToShow;
				showPlayerResponseOptions();
				return;
			}
			else
			{
				enuCards eResponse = cSuspects[(int)eSuspectCounter].RespondToSuggestion();
				ProveSuggestion_ReceiveResponse(eSuspectCounter, eResponse);
			}
		}

		void showPlayerResponseOptions()
		{
			eValidPlayerResponseCards = new enuCards[0];
			classSuspect cPlayer = getPlayerSuspect();
			enuCards eCardTemp;

			eCardTemp = classCard.getECardFromERoom(cSuggestion.eRoom);
			if (eCardIsInListeCards(ref cPlayer.cCards, eCardTemp))
				appendCardList(ref eValidPlayerResponseCards, eCardTemp);

			eCardTemp = classCard.getECardFromESuspect(cSuggestion.eSuspect);
			if (eCardIsInListeCards(ref cPlayer.cCards, eCardTemp))
				appendCardList(ref eValidPlayerResponseCards, eCardTemp);

			eCardTemp = classCard.getECardFromEWeapon(cSuggestion.eWeapon);
			if (eCardIsInListeCards(ref cPlayer.cCards, eCardTemp))
				appendCardList(ref eValidPlayerResponseCards, eCardTemp);

			double dblBannerAspectRatioXOverY = (double)bmpBannerCardToShow.Width / (double)bmpBannerCardToShow.Height;

			Point ptTLBanner = new Point(100, 135);

			int intBannerWidth = bmpBoard.Width - ptTLBanner.X - 5;
			int intBannerHeight = (int)(intBannerWidth / dblBannerAspectRatioXOverY);

			Size szBanner = new System.Drawing.Size(intBannerWidth, intBannerHeight);

			Rectangle recBanner = new Rectangle(ptTLBanner, szBanner);

			Bitmap bmpBannerBackground = new Bitmap(szBanner.Width, szBanner.Height);
			using (Graphics g = Graphics.FromImage(bmpBannerBackground))
			{
				Rectangle recDest = new Rectangle(0, 0, bmpBannerBackground.Width, bmpBannerBackground.Height);

				g.DrawImage(bmpSuggestionBoard, recDest, recBanner, GraphicsUnit.Pixel);

				if (eValidPlayerResponseCards.Length > 0)
				{
					g.DrawImage(bmpBannerCardToShow, recDest, new Rectangle(0, 0, bmpBannerCardToShow.Width, bmpBannerCardToShow.Height), GraphicsUnit.Pixel);
					// player has at least one card to show 				

					int intTop = 2;
					int intHGap = 10;
					int intWidth = 120;

					Point[] pts = new Point[eValidPlayerResponseCards.Length];
					switch (eValidPlayerResponseCards.Length)
					{
						case 1:
							pts[0] = new Point((bmpBoard.Width - intWidth) / 2, intTop);
							break;

						case 2:
							pts[0] = new Point(bmpBoard.Width / 2 - intWidth - intHGap, intTop);
							pts[1] = new Point(bmpBoard.Width / 2 + intHGap, intTop);
							break;

						case 3:
							pts[0] = new Point((bmpBoard.Width - intWidth) / 2, intTop);
							pts[1] = new Point(pts[0].X - intWidth - intHGap, intTop);
							pts[2] = new Point(pts[0].X + intWidth + intHGap, intTop);
							break;
					}

					for (int intValidCardCounter = 0; intValidCardCounter < eValidPlayerResponseCards.Length; intValidCardCounter++)
					{
						double dblAspectRatioYOverX = (double)cCards[(int)eValidPlayerResponseCards[intValidCardCounter]].cBmp.getImage(0).Height / (double)cCards[(int)eValidPlayerResponseCards[intValidCardCounter]].cBmp.getImage(0).Width;
						int intHeight = (int)(intWidth * dblAspectRatioYOverX);
						Size szButton = new Size(intWidth, intHeight);

						Bitmap bmpBackgroundImage = new Bitmap(cCards[(int)eValidPlayerResponseCards[intValidCardCounter]].cBmp.getImage(0), intWidth, intHeight);
						btnPlayerResponse[intValidCardCounter].BackgroundImage = bmpBackgroundImage;
						btnPlayerResponse[intValidCardCounter].Width = szButton.Width + 3;
						btnPlayerResponse[intValidCardCounter].Height = szButton.Height + 3;
						btnPlayerResponse[intValidCardCounter].Tag = cCards[(int)eValidPlayerResponseCards[intValidCardCounter]];
						btnPlayerResponse[intValidCardCounter].Location = pts[intValidCardCounter];
						btnPlayerResponse[intValidCardCounter].BringToFront();
						btnPlayerResponse[intValidCardCounter].Visible = true;
						btnPlayerResponse[intValidCardCounter].Refresh();
					}
					autoProceedEnabled = bolAutoProceed && (eValidPlayerResponseCards.Length == 1); // auto-proceed if there is only one choice
				}
				else
				{
					g.DrawImage(bmpBannerNoCard, recDest, new Rectangle(0, 0, bmpBannerNoCard.Width, bmpBannerNoCard.Height), GraphicsUnit.Pixel);
					autoProceedEnabled = bolAutoProceed;
				}
			}

			Bitmap bmpTemp = new Bitmap(bmpSuggestionBoard);
			using (Graphics g = Graphics.FromImage(bmpTemp))
				g.DrawImage(bmpBannerBackground, recBanner, new Rectangle(0, 0, bmpBannerBackground.Width, bmpBannerBackground.Height), GraphicsUnit.Pixel);
			recBannerButton = new Rectangle(recBanner.Left + 127, recBanner.Top + 29, 363, 68);
			picBoard.Image = bmpTemp;
			picBoard.Refresh();
		}

		void btnPlayerResponse_Click(object sender, MouseEventArgs e)
		{
			autoProceedEnabled = false;
			picBoard.Image = bmpSuggestionBoard; picBoard.Refresh();

			Button btnThis = (Button)sender;
			for (int intButtonCounter = 0; intButtonCounter < btnPlayerResponse.Length; intButtonCounter++)
				btnPlayerResponse[intButtonCounter].Visible = false;

			classCard cCardToShow = (classCard)(btnThis.Tag);
			eMode = enuMode.respondToSuggestion;
			for (int intButtonCounter = 0; intButtonCounter < btnPlayerResponse.Length; intButtonCounter++)
				btnPlayerResponse[intButtonCounter].Visible = false;
			ProveSuggestion_ReceiveResponse(getPlayerSuspect().eName, cCardToShow.eCardName);
		}

		void ProveSuggestion_ReceiveResponse(enuSuspects eRespondingSuspect, enuCards eResponse)
		{
			DrawRespondingSuspect(eRespondingSuspect);
			writeResponse(eResponse, eRespondingSuspect);

			for (enuSuspects eSuspectAICounter = (enuSuspects)0; eSuspectAICounter < enuSuspects._numSuspects; eSuspectAICounter++)
			{
				if (!cSuspects[(int)eSuspectAICounter].bolPlayerControlled
					&& eRespondingSuspect != eSuspectAICounter)
				{
					enuCards eCardThisAISuspectSees = eResponse;
					if (eSuspectAICounter != cSuspects[intSuspectTurn].eName)
					{ // this AISuspect is NOT the player who's turn it is
						if (eResponse != enuCards.NoCardShown)
							eCardThisAISuspectSees = enuCards.Unknown;
					}
					cSuspects[(int)eSuspectAICounter].ResponseToSuggestion(eRespondingSuspect, eCardThisAISuspectSees);
				}
			}

			cSuggestionAnimation.intProveSuggestionCycleCounter++;

			if (eResponse != enuCards.NoCardShown)
			{
				cSuggestionAnimation.intProveSuggestionCycleCounter = 6;
			}

		}

		private void btnWarnPlayerWhoseTurnItIs_Click(object sender, EventArgs e)
		{
			btnWarnPlayerWhoseTurnItIs.Visible = false;
            //btnAccuse.Enabled = true;
            AccuseButtonEnabled = true;
			RollDieButtonEnabled = true;
			SuggestButtonEnabled = false;
			EndTurnButtonEnabled = true;
			eMode = enuMode.beginTurn;
			setButtonsEnabled();
		}

		
	}

    public class classSearchElement
	{
		public Point pt;
		public int intSteps;
		public int intTurns;
		public int intCost;

		public enuDir SrcDir;
		public classSearchElement next;

		public void set(Point PT, int Cost, enuDir sourceDirection)
		{ set(PT, sourceDirection, Cost, 0); }

		public void set(Point PT, enuDir sourceDirection, int Steps, int turns)
		{
			pt = PT;
			SrcDir = sourceDirection;
			intSteps = Steps;
			intTurns = turns;
			intCost = intTurns * 3 + intSteps;
		}
	}

	public struct udtSearchElementQ
	{
		public classSearchElement head;
		public classSearchElement tail;
	}

	public class classRoom
	{
		public enuRooms name;
		public Point[] ptDoors;
		formClue_2022 mainForm;

		public classRoom(enuRooms Name, formClue_2022 MainForm)
		{
			mainForm = MainForm;
			name = Name;
			setDoors();
		}
		public Point[] getValidDoors() { return getValidDoors(true); }
		public Point[] getValidDoors(bool bolAllowSecretDoor)
		{
			Point[] ptRetVal = new Point[0];
			for (int intDoorCounter = 0; intDoorCounter < ptDoors.Length; intDoorCounter++)
			{
				if (classSuspect.cFloor[ptDoors[intDoorCounter].X, ptDoors[intDoorCounter].Y].dirDoor == enuDir.secretPassage)
				{
					if (bolAllowSecretDoor)
					{
						Array.Resize<Point>(ref ptRetVal, ptRetVal.Length + 1);
						ptRetVal[ptRetVal.Length - 1] = ptDoors[intDoorCounter];
					}
				}
				else
				{
					Point ptNext = mainForm.movePoint(ptDoors[intDoorCounter], classSuspect.cFloor[ptDoors[intDoorCounter].X, ptDoors[intDoorCounter].Y].dirDoor);
					if (mainForm.floorTileIsFree(ptNext) || mainForm.cSuspects[mainForm.intSuspectTurn].ptTile == ptNext) // tile is free or suspect whose turn it is is standing on it
					{
						// doors are only valid if they are NOT BLOCKED
						bool bolDoorValid = true;
						for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
						{
							if (eSuspectCounter != (enuSuspects)mainForm.intSuspectTurn && mainForm.cSuspects[(int)eSuspectCounter].eRoom == enuRooms.tiles)
								if (mainForm.cSuspects[(int)eSuspectCounter].ptTile == ptNext)
									bolDoorValid = false;
						}
						if (bolDoorValid)
						{
							Array.Resize<Point>(ref ptRetVal, ptRetVal.Length + 1);
							ptRetVal[ptRetVal.Length - 1] = ptDoors[intDoorCounter];
						}
					}
				}
			}
			return ptRetVal;
		}

		void setDoors()
		{
			ptDoors = new Point[0];
			int intRoomID = (int)name;
			for (int intX = 0; intX < mainForm.sz.Width; intX++)
				for (int intY = 0; intY < mainForm.sz.Height; intY++)
				{
					if (classSuspect.cFloor[intX, intY].eType == enuFloor.door
						&& classSuspect.cFloor[intX, intY].eRoom == name)
					{
						Array.Resize<Point>(ref ptDoors, ptDoors.Length + 1);
						ptDoors[ptDoors.Length - 1] = new Point(intX, intY);
					}
				}
		}

		public enuRooms oppositeCornerRoom()
		{
			switch (name)
			{
				case enuRooms.Study:
					return enuRooms.Kitchen;

				case enuRooms.Lounge:
					return enuRooms.Conservatory;

				case enuRooms.Kitchen:
					return enuRooms.Study;

				case enuRooms.Conservatory:
					return enuRooms.Lounge;

				default:
					return name;
			}
		}
	}

	public class classCardsCalled
	{
		public enuCards[] cCardsThatMightHaveBeenShown;
	}

	public class classSuspectCardsCalled
	{
		public classCardsCalled[] cSetsOfCardsCalled;
	}

	public class classAILogic
	{
		public classSuspectCardsCalled[] cSuspectsUnknowns;
		public enuNote[,] eNotes;
		public enuRooms[] eRoomsLeft;
		public enuWeapons[] eWeaponsLeft;
		public enuSuspects[] eSuspectsLeft;
		public enuRooms eDestinationRoom;
		public Point ptDestinationTile;
		public classSuggestionAI cSuggestionAI = new classSuggestionAI();
	}

	public class classTurnsReachRoom
	{
		public enuRooms eRoom;
		int intCost;
		public int getCost
		{
			get { return intCost; }
		}

		public void resetCost()
		{
			intCost = 1000;
		}

		public bool setCost(int intNewValue)
		{
			if (intNewValue < intCost)
			{
				intCost = intNewValue;
				return true;
			}
			else
				return false;
		}
	}

	public class classSuspect
	{
		public bool bolPlayerControlled;
		public bool bolEliminated;

		bool _bolCanSuggest;
		public bool bolMustMove;
		public bool bolHasNotYetMadeASuggestionThisTurn;
		public enuSuspects eName;
		public Point ptTile;
		public Point ptFirstTile;
		public enuRooms eRoom;
		public classCard[] cCards = new classCard[0];
		public classSearchElement[,] cSEAllowableMoves;
		public classSearchElement[,] cShortestPath;
		static classSearchElement[] cSEArray = new classSearchElement[0];
		public classTurnsReachRoom[] cNumTurnsToReachRooms = new classTurnsReachRoom[(int)enuRooms._numRooms];
		public static classFloor[,] cFloor;
		public enuRooms[] eRoomsIHoldACardFor;
		public enuWeapons[] eWeaponsIHoldACardFor;
		public enuSuspects[] eSuspectsIHoldACardFor;
		public enuAILevel eAILevel = enuAILevel.average;
		public classAILogic udrAILogic;

		udtSearchElementQ searchQ;
		formClue_2022 MainForm;

		public classSuspect(enuSuspects Name, formClue_2022 mainForm)
		{
			eName = Name;
			MainForm = mainForm;
			setFirstTiles();

			if (cFloor == null)
				initFloor();
			bolPlayerControlled = false;

			// init allowable moves table
			if (cSEAllowableMoves == null)
				cSEAllowableMoves = new classSearchElement[MainForm.sz.Width, MainForm.sz.Height];
		}

		public bool bolCanSuggest
		{
			get { return _bolCanSuggest; }
			set
			{
				if (_bolCanSuggest != value)
					_bolCanSuggest = value;
			}
		}

		public void initNotes()
		{
			udrAILogic = new classAILogic();
			udrAILogic.eNotes = new enuNote[(int)enuSuspects._numSuspects, (int)enuCards._numCards];
			udrAILogic.cSuspectsUnknowns = new classSuspectCardsCalled[(int)enuSuspects._numSuspects];

			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
			{
				// init logic of suggestion responses
				udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter] = new classSuspectCardsCalled();
				udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled = new classCardsCalled[0];

				// init notes
				for (enuCards eCardCounter = (enuCards)0; eCardCounter < enuCards._numCards; eCardCounter++)
					udrAILogic.eNotes[(int)eSuspectCounter, (int)eCardCounter] = (eSuspectCounter == eName ? enuNote.X : enuNote.blank);
			}

			// reset possible rooms
			udrAILogic.eRoomsLeft = new enuRooms[(int)enuRooms._numRooms];
			for (enuRooms eRoomCounter = (enuRooms)0; eRoomCounter < enuRooms._numRooms; eRoomCounter++)
				udrAILogic.eRoomsLeft[(int)eRoomCounter] = eRoomCounter;

			udrAILogic.eWeaponsLeft = new enuWeapons[(int)enuWeapons._numWeapons];
			for (enuWeapons eWeaponCounter = (enuWeapons)0; eWeaponCounter < enuWeapons._numWeapons; eWeaponCounter++)
				udrAILogic.eWeaponsLeft[(int)eWeaponCounter] = eWeaponCounter;

			udrAILogic.eSuspectsLeft = new enuSuspects[(int)enuSuspects._numSuspects];
			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				udrAILogic.eSuspectsLeft[(int)eSuspectCounter] = eSuspectCounter;

			// init suggestionAI
			udrAILogic.cSuggestionAI.lstSuspectMysteryInfo = new List<classSuggestionAI_perSuspect>();// = new udtSuggestionAI_perSuspect[(int)enuSuspects._numSuspects - 1];
			for (int intSuspectCounter = 1; intSuspectCounter < (int)enuSuspects._numSuspects; intSuspectCounter++)
			{
				//udrAILogic.udrSuggestionAI.suspectMysteryInfo[intSuspectCounter - 1].eSuspect = (enuSuspects)(((int)eName + intSuspectCounter) % (int)enuSuspects._numSuspects);
				udrAILogic.cSuggestionAI.lstSuspectMysteryInfo.Add(new classSuggestionAI_perSuspect());//
				classSuggestionAI_perSuspect cSUggestionAI_perSuspect = udrAILogic.cSuggestionAI.lstSuspectMysteryInfo[udrAILogic.cSuggestionAI.lstSuspectMysteryInfo.Count - 1];
                cSUggestionAI_perSuspect.eSuspect = (enuSuspects)(((int)eName + intSuspectCounter) % (int)enuSuspects._numSuspects); 
            }

        }

		/// <summary>
		/// uses the 24x24 pixel bitmap bmpClueFloor to set up 2d array describing the game map.
		/// each pixel represents a square on the board.
		/// the pixel color components (Red, Green, Blue) determines the type of tile.
		/// Marble Tile (corridors) : R=255, 
		///                           G=255, 
		///                           B=255                          (white).
		/// Illegal square          : R=0, 
		///                           G=0, 
		///                           B=0                            (black).
		/// Room                    : R=255, 
		///                           G = ROOM ID NUMBER (study =0, hall =1, ... billiard room = 7, library =8), 
		///                           B=0                            (variant of Red).
		/// Door					: R=egress direction (0=north, 1=east, 2=south, 3=west, 4=secretpassage), 
		///                           G=Room ID, 
		///                           B=255                          (variant of Blue).
		/// e.g. the marble tile south of the door (6,4 in 2d array) to the study is white (0,0,0).
		///      the first tile into the study(roomId=0) is considered a door-tile facing south(dir=2) therefore tile (6,3 in 2d array) is colored (2,0,255).
		///      the top-left-most tile (0,0) is the study's secret passage to the kitchen(roomID=4) therefore its tile is colored(4,4,255).
		///      the right-bottom-most tile (23,23) is the kitchen's secret passage to the Study(roomID=0) therefore its tile is colored (4,0,255).
		/// </summary>
		void initFloor()
		{ // static floor tiles 
			Bitmap bmpFloorTiles = new Bitmap(Resources.ClueFloor);
			cFloor = new classFloor[bmpFloorTiles.Width, bmpFloorTiles.Height];
			for (int intX = 0; intX < bmpFloorTiles.Width; intX++)
				for (int intY = 0; intY < bmpFloorTiles.Height; intY++)
				{
					//if (intX == 0 && intY == 23)
					//    MessageBox.Show("stop initFloor()");
					cFloor[intX, intY] = new classFloor();
					Color clrTile = bmpFloorTiles.GetPixel(intX, intY);

					if (clrTile.R == 255 && clrTile.G == 255 && clrTile.B == 255)
					{ // white = tile
						cFloor[intX, intY].eType = enuFloor.tile;
					}
					else if (clrTile.R == 0 && clrTile.G == 0 && clrTile.B == 0)
					{ // black = invalid
						cFloor[intX, intY].eType = enuFloor.invalid;
					}
					else if (clrTile.B == 255)
					{ // blue = door : R = direction door exits room, G = roomID#
						cFloor[intX, intY].eType = enuFloor.door;
						cFloor[intX, intY].dirDoor = (enuDir)clrTile.R;
						cFloor[intX, intY].eRoom = (enuRooms)clrTile.G;
					}
					else if (clrTile.R == 255)
					{ // red = room : G = roomID#
						cFloor[intX, intY].eType = enuFloor.room;
						cFloor[intX, intY].eRoom = (enuRooms)clrTile.G;
					}
					else
						MessageBox.Show("this should not happen");
				}
		}

		void disposeSE(ref classSearchElement cSE)
		{
			Array.Resize<classSearchElement>(ref cSEArray, cSEArray.Length + 1);
			cSEArray[cSEArray.Length - 1] = cSE;
		}

		classSearchElement getSE()
		{
			classSearchElement cSERetVal;
			if (cSEArray.Length > 0)
			{
				cSERetVal = cSEArray[cSEArray.Length - 1];
				Array.Resize<classSearchElement>(ref cSEArray, cSEArray.Length - 1);
			}
			else
			{
				cSERetVal = new classSearchElement();
			}
			return cSERetVal;
		}

		public void resetAllowableMoves()
		{
			// reset allowable moves table
			for (int intX = 0; intX < MainForm.sz.Width; intX++)
				for (int intY = 0; intY < MainForm.sz.Height; intY++)
				{
					if (cSEAllowableMoves[intX, intY] != null)
					{
						disposeSE(ref cSEAllowableMoves[intX, intY]);
						cSEAllowableMoves[intX, intY] = null;
					}
				}
		}

		public void allowSecretPassage()
		{
			// if in a corner room -> set allowable secret passage
			switch (eRoom)
			{
				case enuRooms.Study:
					Point ptStudySecretPassage = new Point(0, 0);
					cSEAllowableMoves[ptStudySecretPassage.X, ptStudySecretPassage.Y] = getSE();
					cSEAllowableMoves[ptStudySecretPassage.X, ptStudySecretPassage.Y].set(ptStudySecretPassage, 0, enuDir.secretPassage);
					break;

				case enuRooms.Lounge:
					Point ptLoungeSecretPassage = new Point(MainForm.sz.Width - 1, 0);
					cSEAllowableMoves[ptLoungeSecretPassage.X, ptLoungeSecretPassage.Y] = getSE();
					cSEAllowableMoves[ptLoungeSecretPassage.X, ptLoungeSecretPassage.Y].set(ptLoungeSecretPassage, 0, enuDir.secretPassage);
					break;

				case enuRooms.Kitchen:
					Point ptKitchenSecretPassage = new Point(MainForm.sz.Width - 1, MainForm.sz.Height - 1);
					cSEAllowableMoves[ptKitchenSecretPassage.X, ptKitchenSecretPassage.Y] = getSE();
					cSEAllowableMoves[ptKitchenSecretPassage.X, ptKitchenSecretPassage.Y].set(ptKitchenSecretPassage, 0, enuDir.secretPassage);
					break;

				case enuRooms.Conservatory:
					Point ptConservatorySecretPassage = new Point(0, MainForm.sz.Height - 1);
					cSEAllowableMoves[ptConservatorySecretPassage.X, ptConservatorySecretPassage.Y] = getSE();
					cSEAllowableMoves[ptConservatorySecretPassage.X, ptConservatorySecretPassage.Y].set(ptConservatorySecretPassage, 0, enuDir.secretPassage);
					break;
			}
		}

		void resetShortestPath()
		{
			if (cShortestPath == null)
			{
				cShortestPath = new classSearchElement[MainForm.sz.Width, MainForm.sz.Height];
			}
			for (int intX = 0; intX < MainForm.sz.Width; intX++)
				for (int intY = 0; intY < MainForm.sz.Height; intY++)
				{
					if (cShortestPath[intX, intY] != null)
					{
						disposeSE(ref cShortestPath[intX, intY]);
						cShortestPath[intX, intY] = null;
					}
				}
			cNumTurnsToReachRooms = new classTurnsReachRoom[(int)enuRooms._numRooms];
			for (enuRooms eRoomCounter = (enuRooms)0; eRoomCounter < enuRooms._numRooms; eRoomCounter++)
			{
				if (cNumTurnsToReachRooms[(int)eRoomCounter] == null)
					cNumTurnsToReachRooms[(int)eRoomCounter] = new classTurnsReachRoom();
				cNumTurnsToReachRooms[(int)eRoomCounter].resetCost();
				cNumTurnsToReachRooms[(int)eRoomCounter].eRoom = eRoomCounter;
			}

			if (eRoom < enuRooms._numRooms)
				cNumTurnsToReachRooms[(int)eRoom].setCost(0);
		}

		public bool ShortestPath()
		{
			resetShortestPath();
			int intStartTurnCost = 0;
			enuRooms eCurrentRoom = eRoom;
			classSearchElement cSE;

		startShortestPath:

			if (eCurrentRoom == enuRooms.start)  // this suspect is at starting position
			{
				cSE = getSE();
				cSE.set(ptFirstTile, enuDir.secretPassage, 1, intStartTurnCost);
				cShortestPath[cSE.pt.X, cSE.pt.Y] = cSE;
				enQSE(ref cSE);
			}
			else if (eCurrentRoom == enuRooms.tiles)  // this suspect is on a floor tile outside a room
			{
				cSE = getSE();
				cSE.set(ptTile, enuDir.secretPassage, 0, intStartTurnCost);
				cShortestPath[cSE.pt.X, cSE.pt.Y] = cSE;
				enQSE(ref cSE);
			}
			else
			{									// this suspect is in a room
				classRoom cRoom = MainForm.cRooms[(int)eCurrentRoom];
				Point[] ptDoors = cRoom.getValidDoors();
				for (int intDoorCounter = 0; intDoorCounter < ptDoors.Length; intDoorCounter++)
				{
					if (classSuspect.cFloor[ptDoors[intDoorCounter].X, ptDoors[intDoorCounter].Y].dirDoor == enuDir.secretPassage)
					{
						intStartTurnCost = 0;
						switch (eCurrentRoom)
						{
							case enuRooms.Study:
								ptDoors[intDoorCounter] = new Point(0, 0);
								break;

							case enuRooms.Lounge:
								ptDoors[intDoorCounter] = new Point(23, 0);
								break;

							case enuRooms.Kitchen:
								ptDoors[intDoorCounter] = new Point(23, 23);
								break;

							case enuRooms.Conservatory:
								ptDoors[intDoorCounter] = new Point(0, 23);
								break;
						}
					}
					else
						intStartTurnCost = 0;

					cSE = getSE();
					cSE.set(ptDoors[intDoorCounter], enuDir.secretPassage, 0, intStartTurnCost);
					cShortestPath[cSE.pt.X, cSE.pt.Y] = cSE;
					enQSE(ref cSE);
				}
			}

			cSE = deQSE();

			int intAverageRoll = 3;

			while (cSE != null)
			{
				classFloor cTile = cFloor[cSE.pt.X, cSE.pt.Y];
				if (cTile.eType == enuFloor.door && cTile.dirDoor == enuDir.secretPassage && cTile.eRoom != eRoom)
				{ // take secret passage
					if (cNumTurnsToReachRooms[(int)cFloor[cSE.pt.X, cSE.pt.Y].eRoom].setCost((cSE.intTurns + 1) * 3))
					{
						classRoom cRoom = MainForm.cRooms[(int)cFloor[cSE.pt.X, cSE.pt.Y].eRoom];

						for (int intDoorCounter = 0; intDoorCounter < cRoom.ptDoors.Length; intDoorCounter++)
						{
							if (cShortestPath[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y] == null
								&& cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor != enuDir.secretPassage)
							{
								classSearchElement cSENew = getSE();
								cSENew.set(cRoom.ptDoors[intDoorCounter], cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor, 0, cSE.intTurns + 1);
								cShortestPath[cSENew.pt.X, cSENew.pt.Y] = cSENew;
								enQSE(ref cSENew);
							}
						}
					}
				}
				else
					for (enuDir dirCounter = enuDir.north; dirCounter <= enuDir.west; dirCounter++)
					{
						bool bolDoor = (cTile.eType == enuFloor.door);
						if ((bolDoor && cTile.dirDoor == dirCounter)
							|| !bolDoor)
						{
							Point ptDir = MainForm.movePoint(cSE.pt, dirCounter);
							if (ptDir.X < MainForm.sz.Width && ptDir.X >= 0 && ptDir.Y < MainForm.sz.Height && ptDir.Y >= 0)
							{
								classFloor cNewTile = cFloor[ptDir.X, ptDir.Y];
								if (cNewTile.eType == enuFloor.tile
									&& MainForm.floorTileIsFree(ptDir))
								{  // floor tile
									if (cShortestPath[ptDir.X, ptDir.Y] == null) // this new tile has not yet been seen
									{
										classSearchElement cSENew = getSE();

										int intNewSteps = cSE.intSteps + 1;
										int intNewTurns = cSE.intTurns;
										if (intNewSteps > intAverageRoll)
										{
											intNewSteps = 1;
											intNewTurns++;
										}

										cSENew.set(ptDir, MainForm.getOppDir(dirCounter), intNewSteps, intNewTurns);
										cShortestPath[cSENew.pt.X, cSENew.pt.Y] = cSENew;
										enQSE(ref cSENew);
									}
								}
								else if (cNewTile.eType == enuFloor.door)
								{    // door to a room 
									if (cNewTile.dirDoor == MainForm.getOppDir(dirCounter))
									{
										if (cNumTurnsToReachRooms[(int)cFloor[ptDir.X, ptDir.Y].eRoom].setCost((cSE.intTurns * 3 + cSE.intSteps + 1)))
										{
											classSearchElement cSENew = getSE();

											int intNewSteps = cSE.intSteps + 1;
											int intNewTurns = cSE.intTurns;
											if (intNewSteps > intAverageRoll)
											{
												intNewSteps = 1;
												intNewTurns++;
											}


											cSENew.set(ptDir, MainForm.getOppDir(dirCounter), intNewSteps, intNewTurns);

											cShortestPath[cSENew.pt.X, cSENew.pt.Y] = cSENew;

											classRoom cRoom = MainForm.cRooms[(int)cFloor[cSENew.pt.X, cSENew.pt.Y].eRoom];
											for (int intDoorCounter = 0; intDoorCounter < cRoom.ptDoors.Length; intDoorCounter++)
											{
												if (cShortestPath[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y] == null
													&& cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor != enuDir.secretPassage)
												{
													cSENew = getSE();
													cSENew.set(cRoom.ptDoors[intDoorCounter], cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor, 0, intNewTurns + 1);
													cShortestPath[cSENew.pt.X, cSENew.pt.Y] = cSENew;
													enQSE(ref cSENew);
												}
												else if (cShortestPath[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y] == null
													&& cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor == enuDir.secretPassage)
												{

													cSENew = getSE();
													switch (cRoom.name)
													{
														case enuRooms.Study:
															cSENew.set(new Point(0, 0), enuDir.secretPassage, 0, intNewTurns);
															break;

														case enuRooms.Lounge:
															cSENew.set(new Point(23, 0), enuDir.secretPassage, 0, intNewTurns);
															break;

														case enuRooms.Kitchen:
															cSENew.set(new Point(23, 23), enuDir.secretPassage, 0, intNewTurns);
															break;

														case enuRooms.Conservatory:
															cSENew.set(new Point(0, 23), enuDir.secretPassage, 0, intNewTurns);
															break;
													}
													cShortestPath[cSENew.pt.X, cSENew.pt.Y] = cSENew;
													enQSE(ref cSENew);
												}
											}
										}
									}
								}
							}
						}
					}
				cSE = deQSE();
			}

			// debugging test
			bool bolRetVal = true;
			for (int intX = 0; intX < MainForm.sz.Width; intX++)
				for (int intY = 0; intY < MainForm.sz.Height; intY++)
					if (cShortestPath[intX, intY] != null)
					{
						bolRetVal = false;
						if (cShortestPath[intX, intY].pt.X != intX || cShortestPath[intX, intY].pt.Y != intY)
							MessageBox.Show("setAllowableMoves() error : cell misplaced (" + intX.ToString() + "," + intY.ToString() + ") thinks it belongs to (" + cShortestPath[intX, intY].pt.X.ToString() + "," + cShortestPath[intX, intY].pt.Y.ToString() + ")");
					}
			//goto startAgain;
			return bolRetVal;
		}

		public void removeSuspectFromDoorways()
		{
			if (eRoom == enuRooms.tiles)
			{
				if (cFloor[ptTile.X, ptTile.Y].eType == enuFloor.tile)
				{
					for (enuDir eDirCounter = (enuDir)0; eDirCounter < enuDir.secretPassage; eDirCounter++)
					{
						Point ptNext = MainForm.movePoint(ptTile, eDirCounter);
						if (cFloor[ptNext.X, ptNext.Y].eType == enuFloor.door)
						{
							eRoom = cFloor[ptNext.X, ptNext.Y].eRoom;
							return;
						}
					}
				}
			}
		}

		public bool setAllowableMoves()
		{
		startAgain:
			resetAllowableMoves();

			classSearchElement cSE;
			if (eRoom == enuRooms.start)  // this suspect is at starting position
			{
				cSE = getSE();
				cSE.set(ptFirstTile, 1, enuDir.secretPassage);
				cSEAllowableMoves[cSE.pt.X, cSE.pt.Y] = cSE;
				enQSE(ref cSE);
			}
			else if (eRoom == enuRooms.tiles)  // this suspect is on a floor tile outside a room
			{
				cSE = getSE();
				cSE.set(ptTile, 0, enuDir.secretPassage);
				cSEAllowableMoves[cSE.pt.X, cSE.pt.Y] = cSE;
				enQSE(ref cSE);
			}
			else
			{									// this suspect is in a room
				classRoom cRoom = MainForm.cRooms[(int)eRoom];
				for (int intDoorCounter = 0; intDoorCounter < cRoom.ptDoors.Length; intDoorCounter++)
				{
					cSE = getSE();
					cSE.set(cRoom.ptDoors[intDoorCounter], 0, enuDir.secretPassage);

					if (cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor == enuDir.secretPassage)
						enQSE(ref cSE);
					else
					{
						cSE.set(cRoom.ptDoors[intDoorCounter], 0, enuDir.secretPassage);
						cSEAllowableMoves[cSE.pt.X, cSE.pt.Y] = cSE;

						enuDir dirDoor = cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor;
						Point ptTileOutsideDoor = MainForm.movePoint(cRoom.ptDoors[intDoorCounter], dirDoor);
						cSE.set(ptTileOutsideDoor, 0,MainForm.getOppDir( dirDoor));
						cSEAllowableMoves[cSE.pt.X, cSE.pt.Y] = cSE;
						enQSE(ref cSE);
					}
				}
			}

			cSE = deQSE();

			while (cSE != null)
			{
				if (cSE.intSteps < MainForm.cRollDieInfo.intDieValue)
				{
					classFloor cTile = cFloor[cSE.pt.X, cSE.pt.Y];
					for (enuDir dirCounter = enuDir.north; dirCounter <= enuDir.west; dirCounter++)
					{
						bool bolDoor = (cTile.eType == enuFloor.door);
						if ((bolDoor && cTile.dirDoor == dirCounter)
							|| !bolDoor)
						{
							Point ptDir = MainForm.movePoint(cSE.pt, dirCounter);
							if (ptDir.X < MainForm.sz.Width && ptDir.X >= 0 && ptDir.Y < MainForm.sz.Height && ptDir.Y >= 0)
							{
								classFloor cNewTile = cFloor[ptDir.X, ptDir.Y];
								if (cNewTile.eType == enuFloor.tile
									&& MainForm.floorTileIsFree(ptDir))
								{  // floor tile
									if (cSEAllowableMoves[ptDir.X, ptDir.Y] == null) // this new tile has not yet been seen
									{
										classSearchElement cSENew = getSE();
										cSENew.set(ptDir, cSE.intSteps + 1, MainForm.getOppDir(dirCounter));
										cSEAllowableMoves[cSENew.pt.X, cSENew.pt.Y] = cSENew;
										enQSE(ref cSENew);
									}
								}
								else if (cNewTile.eType == enuFloor.door)
								{    // door to a room 
									if (cNewTile.dirDoor == MainForm.getOppDir(dirCounter))
									{
										classSearchElement cSENew = getSE();
										cSENew.set(ptDir, cSE.intSteps + 1, MainForm.getOppDir(dirCounter));
										cSEAllowableMoves[cSENew.pt.X, cSENew.pt.Y] = cSENew;
									}
								}
							}
						}
					}
				}
				else if (cSE.intSteps == MainForm.cRollDieInfo.intDieValue)
				{
					// if next to a door -> allow enter room
					classFloor cTile = cFloor[cSE.pt.X, cSE.pt.Y];
					for (enuDir dirCounter = enuDir.north; dirCounter <= enuDir.west; dirCounter++)
					{
						Point ptDir = MainForm.movePoint(cSE.pt, dirCounter);
						if (ptDir.X < MainForm.sz.Width && ptDir.X >= 0 && ptDir.Y < MainForm.sz.Height && ptDir.Y >= 0)
						{
							classFloor cNewTile = cFloor[ptDir.X, ptDir.Y];
							if (cNewTile.eType == enuFloor.door)
							{    // door to a room 
								if (cNewTile.dirDoor == MainForm.getOppDir(dirCounter))
								{
									classSearchElement cSENew = getSE();
									cSENew.set(ptDir, cSE.intSteps + 1, MainForm.getOppDir(dirCounter));
									cSEAllowableMoves[cSENew.pt.X, cSENew.pt.Y] = cSENew;
								}
							}
						}
					}
				}
				cSE = deQSE();
			}

			if (eRoom < enuRooms._numRooms) // this suspect is inside a room -> remove doors from allowable moves
				removeDoorsFromAllowableMoves();

			bool bolRetVal = true;
			for (int intX = 0; intX < MainForm.sz.Width; intX++)
				for (int intY = 0; intY < MainForm.sz.Height; intY++)
					if (cSEAllowableMoves[intX, intY] != null)
					{
						bolRetVal = false;
						if (cSEAllowableMoves[intX, intY].pt.X != intX || cSEAllowableMoves[intX, intY].pt.Y != intY)
							MessageBox.Show("setAllowableMoves() error : cell misplaced (" + intX.ToString() + "," + intY.ToString() + ") thinks it belongs to (" + cSEAllowableMoves[intX, intY].pt.X.ToString() + "," + cSEAllowableMoves[intX, intY].pt.Y.ToString() + ")");
					}
			//goto startAgain;
			return bolRetVal;
		}

		void removeDoorsFromAllowableMoves()
		{ // this is called when the suspect is moving away from a room
			for (int intX = 0; intX < MainForm.sz.Width; intX++)
				for (int intY = 0; intY < MainForm.sz.Height; intY++)
				{
					if (cSEAllowableMoves[intX, intY] != null)
					{
						classFloor cTile = cFloor[intX, intY];

						if ((cTile.eType == enuFloor.door && cTile.eRoom == oppositeCornerRoomID(eRoom))
							|| (cTile.eType == enuFloor.door && cTile.eRoom == eRoom))
						{
							disposeSE(ref cSEAllowableMoves[intX, intY]);
							cSEAllowableMoves[intX, intY] = null;
						}
					}
				}
		}

		enuRooms oppositeCornerRoomID(enuRooms eRoom)
		{
			switch (eRoom)
			{
				case enuRooms.Study:
					return enuRooms.Kitchen;

				case enuRooms.Lounge:
					return enuRooms.Conservatory;

				case enuRooms.Kitchen:
					return enuRooms.Study;

				case enuRooms.Conservatory:
					return enuRooms.Lounge;

				default:
					return enuRooms._numRooms;
			}
		}






		void enQSE(ref classSearchElement cThisSE)
		{
			if (searchQ.head == null)
			{
				searchQ.head = cThisSE;
				searchQ.tail = cThisSE;
			}
			else if (searchQ.tail == searchQ.head)
			{
				searchQ.head.next = cThisSE;
				searchQ.tail = cThisSE;
			}
			else
			{
				searchQ.tail.next = cThisSE;
				searchQ.tail = cThisSE;
			}
		}

		classSearchElement deQSE()
		{
			classSearchElement SERetVal = searchQ.head;
			if (searchQ.head == null)
			{
				return null;
			}
			else if (searchQ.head == searchQ.tail)
			{
				searchQ.head = searchQ.tail = null;
			}
			else
			{
				searchQ.head = searchQ.head.next;
			}
			return SERetVal;
		}

		public void receiveCard(ref classCard thisCard)
		{
			Array.Resize<classCard>(ref cCards, cCards.Length + 1);
			cCards[cCards.Length - 1] = thisCard;
			checkNote(thisCard.eCardName, eName);
		}


		public void XNote(enuCards eCard, enuSuspects eSuspect)
		{

			udrAILogic.eNotes[(int)eSuspect, (int)eCard] = enuNote.X;

			bool bolAllXs = true;
			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
			{
				if (udrAILogic.eNotes[(int)eSuspectCounter, (int)eCard] != enuNote.X)
					bolAllXs = false;
			}

			if (bolAllXs)
			{
				// we have eliminated all possibilities -> this card is part of the solution
				if (MainForm.cCards[(int)eCard].IsARoom)
				{
					udrAILogic.eRoomsLeft = new enuRooms[1];
					udrAILogic.eRoomsLeft[0] = MainForm.getERoomFromCard(eCard);
				}
				else if (MainForm.cCards[(int)eCard].IsAWeapon)
				{
					udrAILogic.eWeaponsLeft = new enuWeapons[1];
					udrAILogic.eWeaponsLeft[0] = MainForm.getEWeaponFromCard(eCard);
				}
				else if (MainForm.cCards[(int)eCard].IsASuspect)
				{
					udrAILogic.eSuspectsLeft = new enuSuspects[1];
					udrAILogic.eSuspectsLeft[0] = MainForm.getESuspectFromCard(eCard);
				}
				else
					MessageBox.Show("we have a problem! : xNote(" + eCard.ToString() + ", " + eSuspect.ToString() + ") -> card type invalid");
			}
		}

		/// <summary>
		/// called when a suspect has been determined to have a card
		/// </summary>
		/// <param name="eCard">card which the suspect holds</param>
		/// <param name="eSuspect">suspect holding the card</param>
		void checkNote(enuCards eCard, enuSuspects eSuspect)
		{
			// debug start -> test faulty logic
			if (eCard == classCard.getECardFromERoom(MainForm.cMurder.eRoom)
				|| eCard == classCard.getECardFromEWeapon(MainForm.cMurder.eWeapon)
				|| eCard == classCard.getECardFromESuspect(MainForm.cMurder.eSuspect))
			{
				MessageBox.Show("checkNote : faulty logic");
				return;
			}
			// debug end

			udrAILogic.eNotes[(int)eSuspect, (int)eCard] = enuNote.check;

			// for this card : set 'X' in note for all suspects (they DO NOT have this card) and a 'check' for suspect who does have it
			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
			{
				if (eSuspect != eSuspectCounter)
				{
					if (udrAILogic.eNotes[(int)eSuspectCounter, (int)eCard] != enuNote.X)
					{
						//udrAILogic.eNotes[(int)eSuspectCounter, (int)eCard] = enuNote.X;
						XNote(eCard, eSuspectCounter);

					startSetLoop:
						if (udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled != null)
							for (int intSetCounter = 0; intSetCounter < udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled.Length; intSetCounter++)
							{
								if (udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter] != null)
								{
									for (int intCardCounter = 0; intCardCounter < udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length; intCardCounter++)
									{
										if (udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[intCardCounter] == eCard)
										{ // since we now know that this suspect does NOT have this card
											// this suspect therefore did NOT show this card previously
											// remove this card from set of unknowns
											udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[intCardCounter] = udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length - 1];
											Array.Resize<enuCards>(ref udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown, udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length - 1);
											if (udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length == 1)
											{ // there is only one card remaining -> the card remaining MUST BE the one this suspect showed (has)
												checkNote(udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[0], eSuspectCounter);
											}
											goto startSetLoop;
										}
									}
								}
							}
					}
				}
			}

			// scan through all AI sets
		// if this new 'known' card is among the list of unknown sets -> cancel those sets
		startScanningPreviousUnknownSets:
			if (udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled != null)
			{ // scan each of this suspects MayHaveBeenShown sets of cards
				for (int intSetCounter = 0; intSetCounter < udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled.Length; intSetCounter++)
				{  // scan each card in this set
					for (int intCardCounter = 0; intCardCounter < udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length; intCardCounter++)
					{ // compare each card in this set to new 'known' card eCard
						if (udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[intCardCounter] == eCard)
						{
							// this set needs to be deleted
							udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled[intSetCounter] = udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled[udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled.Length - 1];
							Array.Resize<classCardsCalled>(ref udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled, udrAILogic.cSuspectsUnknowns[(int)eSuspect].cSetsOfCardsCalled.Length - 1);
							goto startScanningPreviousUnknownSets;
						}
					}
				}
			}

			int intNumSuspects = (int)enuSuspects._numSuspects;
			int intNumWeapons = (int)enuWeapons._numWeapons;

			if ((int)eCard < intNumSuspects)
			{ // known card is a suspect
				enuSuspects eSuspectCardShown = (enuSuspects)((int)eCard);
				for (int intUnknownSuspectsCounter = 0; intUnknownSuspectsCounter < udrAILogic.eSuspectsLeft.Length; intUnknownSuspectsCounter++)
				{
					if (udrAILogic.eSuspectsLeft[intUnknownSuspectsCounter] == eSuspectCardShown)
					{
						udrAILogic.eSuspectsLeft[intUnknownSuspectsCounter] = udrAILogic.eSuspectsLeft[udrAILogic.eSuspectsLeft.Length - 1];
						Array.Resize<enuSuspects>(ref udrAILogic.eSuspectsLeft, udrAILogic.eSuspectsLeft.Length - 1);
					}
				}
			}
			else if ((int)eCard < intNumSuspects + intNumWeapons)
			{ // known card is a weapon
				enuWeapons eWeaponCardShown = (enuWeapons)((int)eCard - intNumSuspects);
				for (int intUnknownWeaponsCounter = 0; intUnknownWeaponsCounter < udrAILogic.eWeaponsLeft.Length; intUnknownWeaponsCounter++)
				{
					if (udrAILogic.eWeaponsLeft[intUnknownWeaponsCounter] == eWeaponCardShown)
					{
						udrAILogic.eWeaponsLeft[intUnknownWeaponsCounter] = udrAILogic.eWeaponsLeft[udrAILogic.eWeaponsLeft.Length - 1];
						Array.Resize<enuWeapons>(ref udrAILogic.eWeaponsLeft, udrAILogic.eWeaponsLeft.Length - 1);
					}
				}
			}
			else
			{ // known card is a room
				enuRooms eRoomCardShown = (enuRooms)((int)eCard - intNumSuspects - intNumWeapons);
				for (int intUnknownRoomsCounter = 0; intUnknownRoomsCounter < udrAILogic.eRoomsLeft.Length; intUnknownRoomsCounter++)
				{
					if (udrAILogic.eRoomsLeft[intUnknownRoomsCounter] == eRoomCardShown)
					{
						udrAILogic.eRoomsLeft[intUnknownRoomsCounter] = udrAILogic.eRoomsLeft[udrAILogic.eRoomsLeft.Length - 1];
						Array.Resize<enuRooms>(ref udrAILogic.eRoomsLeft, udrAILogic.eRoomsLeft.Length - 1);
					}
				}
			}
		}


		bool IHaveThisCard(enuRooms eRoom) { return IHaveThisCard(classCard.getECardFromERoom(eRoom)); }
		bool IHaveThisCard(enuWeapons eWeapon) { return IHaveThisCard(classCard.getECardFromEWeapon(eWeapon)); }
		bool IHaveThisCard(enuSuspects eSuspect) { return IHaveThisCard(classCard.getECardFromESuspect(eSuspect)); }
		bool IHaveThisCard(enuCards eCard)
		{
			for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
				if (cCards[intCardCounter].eCardName == eCard)
					return true;
			return false;
		}

		public enuCards RespondToSuggestion()
		{
			enuCards[] eSuggestedCardsIHave = new enuCards[0];
			if (IHaveThisCard(MainForm.cSuggestion.eSuspect))
				appendECardArray(ref eSuggestedCardsIHave, classCard.getECardFromESuspect(MainForm.cSuggestion.eSuspect));
			if (IHaveThisCard(MainForm.cSuggestion.eWeapon))
				appendECardArray(ref eSuggestedCardsIHave, classCard.getECardFromEWeapon(MainForm.cSuggestion.eWeapon));
			if (IHaveThisCard(MainForm.cSuggestion.eRoom))
				appendECardArray(ref eSuggestedCardsIHave, classCard.getECardFromERoom(MainForm.cSuggestion.eRoom));

			if (eSuggestedCardsIHave.Length > 1)
			{
				// cycle through the cards I can respond and see if I've already shown one of them to the suggesting suspect
				for (int intCardCounter = 0; intCardCounter < eSuggestedCardsIHave.Length; intCardCounter++)
				{
					if (udrAILogic.eNotes[MainForm.intSuspectTurn, (int)eSuggestedCardsIHave[intCardCounter]] == enuNote.shown)
						return eSuggestedCardsIHave[intCardCounter];
				}
				// if none of the valid cards have already been shown -> show a new one
				int intRnd = (int)(MainForm.rnd.NextDouble() * 1000) % eSuggestedCardsIHave.Length;
				udrAILogic.eNotes[MainForm.intSuspectTurn, (int)eSuggestedCardsIHave[intRnd]] = enuNote.shown;
				return eSuggestedCardsIHave[intRnd];
			}
			else if (eSuggestedCardsIHave.Length == 1)
			{
				return eSuggestedCardsIHave[0];
			}

			return enuCards.NoCardShown;
		}

		void appendECardArray(ref enuCards[] eCardArray, enuCards eNewCard)
		{
			Array.Resize<enuCards>(ref eCardArray, eCardArray.Length + 1);
			eCardArray[eCardArray.Length - 1] = eNewCard;
		}

		public void ResponseToSuggestion(enuSuspects eSuspectResponding, enuCards eCardShown)
		{
			enuCards[] eCardsCalled = new enuCards[3];
			eCardsCalled[0] = MainForm.getCardFromERoom(MainForm.cSuggestion.eRoom);
			eCardsCalled[1] = MainForm.getCardFromESuspect(MainForm.cSuggestion.eSuspect);
			eCardsCalled[2] = MainForm.getCardFromEWeapon(MainForm.cSuggestion.eWeapon);

			// scan list of cards which we know the responding suspect does NOT have and eliminate those from the current suggestion
		beginScanCardsCalled:
			for (int intCalledCardsCounter = 0; intCalledCardsCounter < eCardsCalled.Length; intCalledCardsCounter++)
			{
				for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				{ // we know the responding suspect has this card -> remove it from the list of currently suggested cards

					if ((eSuspectCounter == eSuspectResponding && udrAILogic.eNotes[(int)eSuspectCounter, (int)eCardsCalled[intCalledCardsCounter]] == enuNote.X)
						|| (eSuspectCounter != eSuspectResponding && udrAILogic.eNotes[(int)eSuspectCounter, (int)eCardsCalled[intCalledCardsCounter]] == enuNote.check))
					{ // we know some responding suspect does NOT HAVE THIS CARD
						eCardsCalled[intCalledCardsCounter] = eCardsCalled[eCardsCalled.Length - 1];
						Array.Resize<enuCards>(ref eCardsCalled, eCardsCalled.Length - 1);
						goto beginScanCardsCalled;
					}
					else if (eSuspectCounter == eSuspectResponding && udrAILogic.eNotes[(int)eSuspectCounter, (int)eCardsCalled[intCalledCardsCounter]] == enuNote.check)
					{
						// we already know that the responding suspect has one of the cards -> no inference can be made
						return;
					}
				}
			}

			if (eCardsCalled.Length == 1 && eCardShown != enuCards.NoCardShown)
			{ // after eliminating all known cards we are left with one card and that must be the card which was shown
				eCardShown = eCardsCalled[0];
			}

			if (eCardShown == enuCards.Unknown)
			{ // the suspect responding to suggestion holds one of called card but we don't know which of the three (room, suspect or weapon)
				// create a new set and append the current list of unknown sets for the responding suspect
				if (eAILevel == enuAILevel.genius
					|| (eAILevel == enuAILevel.bright && ((int)(MainForm.rnd.NextDouble() * 1000)) % 4 == 0)
					|| (eAILevel == enuAILevel.average && ((int)(MainForm.rnd.NextDouble() * 1000)) % 8 == 0)
					|| (eAILevel == enuAILevel.dull && ((int)(MainForm.rnd.NextDouble() * 1000)) % 12 == 0)
					|| (eAILevel == enuAILevel.stupid && ((int)(MainForm.rnd.NextDouble() * 1000)) % 15 == 0))
				{
					if (udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled == null)
						udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled = new classCardsCalled[0];
					Array.Resize<classCardsCalled>(ref udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled, udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled.Length + 1);

					udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled.Length - 1] = new classCardsCalled();
					udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled.Length - 1].cCardsThatMightHaveBeenShown = eCardsCalled;
				}
			}
			else if (eCardShown == enuCards.NoCardShown)
			{ // this Suspect has none of the suggested cards in his hand
				// set the responding suspect's notes to reflect that he does not have the called cards
				if (eAILevel == enuAILevel.genius
					|| (eAILevel == enuAILevel.bright && ((int)(MainForm.rnd.NextDouble() * 1000)) % 2 == 0)
					|| (eAILevel == enuAILevel.average && ((int)(MainForm.rnd.NextDouble() * 1000)) % 4 == 0)
					|| (eAILevel == enuAILevel.dull && ((int)(MainForm.rnd.NextDouble() * 1000)) % 6 == 0)
					|| (eAILevel == enuAILevel.stupid && ((int)(MainForm.rnd.NextDouble() * 1000)) % 8 == 0))
				{
					for (int intCalledCardCounter = 0; intCalledCardCounter < eCardsCalled.Length; intCalledCardCounter++)
					{
						XNote(eCardsCalled[intCalledCardCounter], eSuspectResponding);
					}
					// scan all previous sets of cards for which this suspect has shown one of the called card (above: eCardShown == enuCards.Unknown)
					// if any of the suggested cards are included in these sets of unknowns -> we now know that that card was NOT SHOWN because the suspect does not have that card
					// eliminate it from the three for that(those) set(s) -> when set is reduced to 1 card -> remaining card is the card he showed, the card he has

					// scan each previous set
					if (udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled != null)
					{
					startSetCounterLoop:
						for (int intSetCounter = 0; intSetCounter < udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled.Length; intSetCounter++)
						{
							// scan each card in this previous set
							for (int intCardsMayHaveBeenShownCounter = 0; intCardsMayHaveBeenShownCounter < udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length; intCardsMayHaveBeenShownCounter++)
							{
								// compare to each of the three cards in the current set (current suggestion)							
								for (int intCardsCalledCounter = 0; intCardsCalledCounter < eCardsCalled.Length; intCardsCalledCounter++)
								{
									if (eCardsCalled[intCardsCalledCounter] == udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[intCardsMayHaveBeenShownCounter])
									{  // we now know that this is NOT the card which the responding suspect showed previously
										// remove this card from the list of possible cards which the responding suspect showed in an earlier response to another suggestion
										udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[intCardsMayHaveBeenShownCounter] = udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length - 1];
										Array.Resize<enuCards>(ref udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown, udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length - 1);
										if (udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown.Length == 1)
										{ // the only card remaining MUST be the card which this responding suspect showed earlier
											checkNote(udrAILogic.cSuspectsUnknowns[(int)eSuspectResponding].cSetsOfCardsCalled[intSetCounter].cCardsThatMightHaveBeenShown[0], eSuspectResponding);
											// this set is removed inside checkNote() -> NO NEED TO REMOVE IT HERE
										}
										goto startSetCounterLoop;
									}
								}
							}
						}
					}
				}
			}
			else
			{
				// responding suspect has shown a card
				// include this information in our notes
				checkNote(eCardShown, eSuspectResponding);
			}
		}

		void setFirstTiles()
		{
			switch (eName)
			{
				case enuSuspects.ColMustard:
					ptFirstTile = new Point(22, 7);
					break;

				case enuSuspects.MissScarlet:
					ptFirstTile = new Point(16, 1);
					break;

				case enuSuspects.RevGreen:
					ptFirstTile = new Point(9, 23);
					break;

				case enuSuspects.MrsPeacock:
					ptFirstTile = new Point(1, 18);
					break;

				case enuSuspects.MrsWhite:
					ptFirstTile = new Point(14, 23);
					break;

				case enuSuspects.ProfPlum:
					ptFirstTile = new Point(1, 5);
					break;
			}
		}

		bool IsACornerRoom() { return IsACornerRoom(eRoom); }
		bool IsACornerRoom(enuRooms eThisRoom)
		{
			return (eThisRoom == enuRooms.Study || eThisRoom == enuRooms.Lounge || eThisRoom == enuRooms.Kitchen || eThisRoom == enuRooms.Conservatory);
		}

		

		bool useSecretPassage()
		{
			if (!IsACornerRoom())
				return false;

			enuRooms eOppositeCornerRoom = MainForm.cRooms[(int)eRoom].oppositeCornerRoom();

			// if heading to opposite corner room
			if (udrAILogic.eDestinationRoom == eOppositeCornerRoom)
			{
				switch (eRoom)
				{
					case enuRooms.Study:
						udrAILogic.ptDestinationTile = new Point(0, 0);
						return true;

					case enuRooms.Lounge:
						udrAILogic.ptDestinationTile = new Point(23, 0);
						return true;

					case enuRooms.Kitchen:
						udrAILogic.ptDestinationTile = new Point(23, 23);
						return true;

					case enuRooms.Conservatory:
						udrAILogic.ptDestinationTile = new Point(0, 23);
						return true;
				}
			}

			// trace steps back from target room
			enuRooms eCurrentRoom = udrAILogic.eDestinationRoom;

			while (true)
			{
				// in a room
				Point ptBestDoorFromRoom = new Point(0, 0);
				if (getBestDoorOutThisRoom(eCurrentRoom, ref ptBestDoorFromRoom, true))
				{
					bool bolOnTiles = true;
					if (ptBestDoorFromRoom.X < 0)
					{ // use a secret passage
						if (Math.Abs(ptBestDoorFromRoom.X) % (int)enuRooms._numRooms == (int)eRoom)
							return true;
						else
						{
							eCurrentRoom = (enuRooms)((int)Math.Abs(ptBestDoorFromRoom.X) % (int)enuRooms._numRooms);
							bolOnTiles = false;
						}
					}
					else
					{
						Point ptTile = MainForm.movePoint(ptBestDoorFromRoom, cFloor[ptBestDoorFromRoom.X, ptBestDoorFromRoom.Y].dirDoor);
						while (bolOnTiles)
						{
							ptTile = MainForm.movePoint(ptTile, cShortestPath[ptTile.X, ptTile.Y].SrcDir);
							bolOnTiles = (cFloor[ptTile.X, ptTile.Y].eType == enuFloor.tile);
						}
						eCurrentRoom = cFloor[ptTile.X, ptTile.Y].eRoom;

					}
					if (eCurrentRoom == eRoom)
						return false;

				}
				else
				{
					return false;
				}
			}




			//classRoom cOppRoom = MainForm.cRooms[(int)eOppositeCornerRoom];
			//Point[] ptOppositeCornerRoomValidDoors = cOppRoom.getValidDoors();

			//for (int intOppCorRooValDoorCounter = 0; intOppCorRooValDoorCounter < ptOppositeCornerRoomValidDoors.Length; intOppCorRooValDoorCounter++)
			//{
			//    if (classSuspect.cFloor[ptOppositeCornerRoomValidDoors[intOppCorRooValDoorCounter].X, ptOppositeCornerRoomValidDoors[intOppCorRooValDoorCounter].Y].dirDoor != enuDir.secretPassage)
			//    {
			//        Point ptTileOutsideOppRoomDoor = MainForm.movePoint(ptOppositeCornerRoomValidDoors[intOppCorRooValDoorCounter], classSuspect.cFloor[ptOppositeCornerRoomValidDoors[intOppCorRooValDoorCounter].X, ptOppositeCornerRoomValidDoors[intOppCorRooValDoorCounter].Y].dirDoor);
			//        if (cShortestPath[ptTileOutsideOppRoomDoor.X, ptTileOutsideOppRoomDoor.Y].intCost == 4)
			//            return true;
			//    }
			//}
			return false;
		}


		bool eRoomIsLeft(enuRooms eThisRoom)
		{
			for (int intRoomsLeftCounter = 0; intRoomsLeftCounter < udrAILogic.eRoomsLeft.Length; intRoomsLeftCounter++)
				if (udrAILogic.eRoomsLeft[intRoomsLeftCounter] == eThisRoom)
					return true;
			return false;
		}

		bool IWantToAccuse()
		{
			return (udrAILogic.eRoomsLeft.Length == 1 && udrAILogic.eSuspectsLeft.Length == 1 && udrAILogic.eWeaponsLeft.Length == 1);
		}

		public void playTurn()
		{
			ShortestPath();

			if (bolMustMove)
				PickDestinationRoom();
			else 
				udrAILogic.eDestinationRoom = eRoom;

			/* /// debug start 
			udrAILogic.eRoomsLeft = new enuRooms[1];
			udrAILogic.eRoomsLeft[0] = MainForm.cMurder.eRoom;
			
			udrAILogic.eWeaponsLeft = new enuWeapons[1];
			udrAILogic.eWeaponsLeft[0] = MainForm.cMurder.eWeapon;

			udrAILogic.eSuspectsLeft = new enuSuspects[1];
			udrAILogic.eSuspectsLeft[0] = MainForm.cMurder.eSuspect;
			/// debug end */



			if (IWantToAccuse())
			{
				classMurder  udrAccusation = new classMurder ();
				udrAccusation.eRoom = udrAILogic.eRoomsLeft[0];
				udrAccusation.eSuspect = udrAILogic.eSuspectsLeft[0];
				udrAccusation.eWeapon = udrAILogic.eWeaponsLeft[0];
				MainForm.Accuse(eName, udrAccusation);
				return;
			}

			if (!bolCanSuggest && udrAILogic.eDestinationRoom == eRoom)
			{ // the room I am in is the destination room because there is no way out
				// I can NOT suggest -> end turn
				MainForm.eMode = enuMode.endTurn;
				resetShortestPath();
				return;
			}


			if (bolCanSuggest && eRoomIsLeft(eRoom)
				&& !(eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 5000 == 0) // lower ai may make a mistake and neglect to suggest
				&& !(eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 1000 == 0)
				&& !(eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0)
				&& !(eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 100 == 0)
				&& !(eAILevel == enuAILevel.stupid && (int)(MainForm.rnd.NextDouble() * 1000) % 10 == 0))
			{
				makeSuggestion();
				return;
			}
			else
			{
				if (useSecretPassage())
				{
					switch (eRoom)
					{
						case enuRooms.Study:
							udrAILogic.ptDestinationTile = new Point(0, 0);
							break;

						case enuRooms.Lounge:
							udrAILogic.ptDestinationTile = new Point(23, 0);
							break;

						case enuRooms.Kitchen:
							udrAILogic.ptDestinationTile = new Point(23, 23);
							break;

						case enuRooms.Conservatory:
							udrAILogic.ptDestinationTile = new Point(0, 23);
							break;
					}
					allowSecretPassage();
				}
				else
				{
					MainForm.rollDie();
					return;
				}

				MainForm.picMouseClick((object)MainForm.picBoard, new MouseEventArgs(MouseButtons.Left, 1, MainForm.ptBoardTL.X + 28 * udrAILogic.ptDestinationTile.X + 3, MainForm.ptBoardTL.Y + 28 * udrAILogic.ptDestinationTile.Y + 3, 0));
				bolMustMove = false;
				if (bolCanSuggest)
					makeSuggestion();
				return;
			}

		endPlayTurn:
			bolCanSuggest = false;
			resetShortestPath();
		}

		public void endShowAllowableMoves()
		{
			if (!PickDestinationTile())
			{ // can't move
				bolCanSuggest = false;
				resetShortestPath();
			}
			bolMustMove = false;
			MainForm.picMouseClick((object)MainForm.picBoard, new MouseEventArgs(MouseButtons.Left, 1, MainForm.ptBoardTL.X + 28 * udrAILogic.ptDestinationTile.X + 3, MainForm.ptBoardTL.Y + 28 * udrAILogic.ptDestinationTile.Y + 3, 0));
			if (bolCanSuggest)
				makeSuggestion();
		}


		public void playTurnAfterMove()
		{
			if (bolCanSuggest)
			{
				makeSuggestion();
				return;
			}
			bolCanSuggest = false;
			resetShortestPath();
			MainForm.eMode = enuMode.endTurn;
		}

		void prepareSuggestionAI()
		{
			udrAILogic.cSuggestionAI.lstUdrRoomCardsMysteryFrequency = new List<classSuggestionAI_CardFrequency>();//= new classSuggestionAI_CardFrequency[0];
			udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency = new List<classSuggestionAI_CardFrequency>();
			udrAILogic.cSuggestionAI.lstUdrSuspectMysteryFrequency = new List<classSuggestionAI_CardFrequency>();

			for (int intSuspectCounter = 0; intSuspectCounter < udrAILogic.cSuggestionAI.lstSuspectMysteryInfo.Count; intSuspectCounter++)
			{
				// scan each suspect's unknown "mystery" card sets
				// count the number of each type of card and order them into that suspect's arrays AND accumulate into overall array
				
				//udrAILogic.udrSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter].udrRoomsMystery = new classSuggestionAI_CardFrequency[0];
				//udrAILogic.udrSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter].udrWeaponCardsMystery = new classSuggestionAI_CardFrequency[0];
				//udrAILogic.udrSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter].udrSuspectCardsMystery = new classSuggestionAI_CardFrequency[0];

                classSuggestionAI_perSuspect cSuggestionAI_perSuspect = udrAILogic.cSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter];

				cSuggestionAI_perSuspect.lstUdrRoomsMystery = new List<classSuggestionAI_CardFrequency>();
				cSuggestionAI_perSuspect.lstUdrWeaponCardsMystery = new List<classSuggestionAI_CardFrequency>();
				cSuggestionAI_perSuspect.lstUdrSuspectCardsMystery = new List<classSuggestionAI_CardFrequency>();

				classCardsCalled[] cCardSets = udrAILogic.cSuspectsUnknowns[(int)udrAILogic.cSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter].eSuspect].cSetsOfCardsCalled;
				if (cCardSets != null)
				{
					for (int intSetCounter = 0; intSetCounter < cCardSets.Length; intSetCounter++)
					{
						enuCards[] eCardsCalled = cCardSets[intSetCounter].cCardsThatMightHaveBeenShown;
						// for each card which this suspect was asked when he showed a card
						// separate into type : room, weapon or suspect
						for (int intCardCounter = 0; intCardCounter < eCardsCalled.Length; intCardCounter++)
						{
							if (MainForm.cCards[(int)eCardsCalled[intCardCounter]].IsARoom)
							{
								//addECardToFrequencyCards(ref udrAILogic.udrSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter].udrRoomsMystery, eCardsCalled[intCardCounter]);
								addECardToFrequencyCards(ref cSuggestionAI_perSuspect.lstUdrRoomsMystery, eCardsCalled[intCardCounter]);
								addECardToFrequencyCards(ref udrAILogic.cSuggestionAI.lstUdrRoomCardsMysteryFrequency, eCardsCalled[intCardCounter]);
							}
							else if (MainForm.cCards[(int)eCardsCalled[intCardCounter]].IsAWeapon)
							{
								addECardToFrequencyCards(ref cSuggestionAI_perSuspect.lstUdrWeaponCardsMystery, eCardsCalled[intCardCounter]);
								addECardToFrequencyCards(ref udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency, eCardsCalled[intCardCounter]);
							}
							else if (MainForm.cCards[(int)eCardsCalled[intCardCounter]].IsASuspect)
							{
								addECardToFrequencyCards(ref cSuggestionAI_perSuspect.lstUdrSuspectCardsMystery, eCardsCalled[intCardCounter]);
								addECardToFrequencyCards(ref udrAILogic.cSuggestionAI.lstUdrSuspectMysteryFrequency, eCardsCalled[intCardCounter]);
							}
							else
								MessageBox.Show("this should NOT HAPPEN! : prepareSuggestionAI() -> don't know what kind of card this is");
						}
					}
					// reorder the three type arrays according to frequency
					reorderFrequencyCardsByNumber(ref cSuggestionAI_perSuspect.lstUdrRoomsMystery);
					reorderFrequencyCardsByNumber(ref cSuggestionAI_perSuspect.lstUdrSuspectCardsMystery);
					reorderFrequencyCardsByNumber(ref cSuggestionAI_perSuspect.lstUdrWeaponCardsMystery);
				}
			}

			// reorder three overall type arrays according to frequency
			reorderFrequencyCardsByNumber(ref udrAILogic.cSuggestionAI.lstUdrRoomCardsMysteryFrequency);
			reorderFrequencyCardsByNumber(ref udrAILogic.cSuggestionAI.lstUdrSuspectMysteryFrequency);
			reorderFrequencyCardsByNumber(ref udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency);
		}

		void reorderFrequencyCardsByNumber(ref List<classSuggestionAI_CardFrequency> lstUdrFreqCards)
		{
			if (lstUdrFreqCards == null)
				return;
			int intBestIndex, intInnerLoop, intOuterLoop;

			for (intOuterLoop = 0; intOuterLoop < lstUdrFreqCards.Count - 1; intOuterLoop++)
			{
				intBestIndex = intOuterLoop;
				for (intInnerLoop = intOuterLoop + 1; intInnerLoop < lstUdrFreqCards.Count; intInnerLoop++)
				{
					if (lstUdrFreqCards[intInnerLoop].intNumMystery > lstUdrFreqCards[intBestIndex].intNumMystery)
						intBestIndex = intInnerLoop;
				}
				if (intBestIndex != intOuterLoop)
				{
					enuCards eCardBestIndex = lstUdrFreqCards[intBestIndex].eCards;
					int intNumBestIndex = lstUdrFreqCards[intBestIndex].intNumMystery;
					classSuggestionAI_CardFrequency udrSuggestionAi_FrequenCard = lstUdrFreqCards[intBestIndex];


					//lstUdrFreqCards[intBestIndex].eCards = lstUdrFreqCards[intOuterLoop].eCards;
					//lstUdrFreqCards[intBestIndex].intNumMystery = lstUdrFreqCards[intOuterLoop].intNumMystery;

					//lstUdrFreqCards[intOuterLoop].eCards = eCardBestIndex;
					//lstUdrFreqCards[intOuterLoop].intNumMystery = intNumBestIndex;


					udrSuggestionAi_FrequenCard.eCards = lstUdrFreqCards[intOuterLoop].eCards;
                    udrSuggestionAi_FrequenCard.intNumMystery = lstUdrFreqCards[intOuterLoop].intNumMystery;

                    udrSuggestionAi_FrequenCard.eCards = eCardBestIndex;
                    udrSuggestionAi_FrequenCard.intNumMystery = intNumBestIndex;
				}
			}
		}

		void addECardToFrequencyCards(ref List<classSuggestionAI_CardFrequency> lstUdrFreqCards, enuCards eNewCard)
		{
			if (lstUdrFreqCards == null)
				lstUdrFreqCards = new List<classSuggestionAI_CardFrequency>();
			for (int intRoomCounter = 0; intRoomCounter < lstUdrFreqCards.Count; intRoomCounter++)
			{
				if (lstUdrFreqCards[intRoomCounter].eCards == eNewCard)
				{  // this suspect has more than one set which includes this card as a possible solution
					classSuggestionAI_CardFrequency udrSuggestionAI_FrequenCard = lstUdrFreqCards[intRoomCounter];
					//lstUdrFreqCards[intRoomCounter].intNumMystery++;
					udrSuggestionAI_FrequenCard.intNumMystery++;
					return;
				}
			}
			// we have scanned the list and NOT found this new room
			// increase size of array and insert this new room at the end
			//Array.Resize<classSuggestionAI_CardFrequency>(ref udrFreqCards, udrFreqCards.Length + 1);
			//udrFreqCards[udrFreqCards.Length - 1] = new classSuggestionAI_CardFrequency();
			//udrFreqCards[udrFreqCards.Length - 1].eCards = eNewCard;
			//udrFreqCards[udrFreqCards.Length - 1].intNumMystery = 1;
			lstUdrFreqCards.Add(new classSuggestionAI_CardFrequency());
			classSuggestionAI_CardFrequency udrNewCard = lstUdrFreqCards[lstUdrFreqCards.Count - 1];
			udrNewCard.eCards = eNewCard;
			udrNewCard.intNumMystery = 1;
		}


		public void makeSuggestion()
		{
			prepareSuggestionAI();

			pickSuspectForSuggestion();
			pickWeaponForSuggestion();
			MainForm.cSuggestion.eRoom = eRoom;

			MainForm.cLibPicTraySuspects.setSelectedImage((int)MainForm.cSuggestion.eSuspect);
			MainForm.cLibPicTraySuspects.Angle = MainForm.cLibPicTraySuspects.FrontAngle - MainForm.cLibPicTraySuspects.Tray[(int)MainForm.cSuggestion.eSuspect].angleOnTray;
			MainForm.cLibPicTraySuspects.RefreshTrayImage();

			MainForm.cLibPicTrayWeapons.setSelectedImage((int)MainForm.cSuggestion.eWeapon);
			MainForm.cLibPicTrayWeapons.Angle = MainForm.cLibPicTrayWeapons.FrontAngle - MainForm.cLibPicTrayWeapons.Tray[(int)MainForm.cSuggestion.eWeapon].angleOnTray;
			MainForm.cLibPicTrayWeapons.RefreshTrayImage();
			MainForm.cSuggestionAnimation.intProveSuggestionCycleCounter = 1;
			MainForm.eMode = enuMode.Suggest;

			bolCanSuggest = false;

			MainForm.btnMakeSuggestion_OK_click();
		}

		void pickSuspectForSuggestion()
		{
			if ((eAILevel == enuAILevel.stupid && (int)(MainForm.rnd.NextDouble() * 1000) % 2 == 0) // ai may make a poor random choice from ALL suspects
				|| (eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 5 == 0)
				|| (eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 50 == 0)
				|| (eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0)
				|| (eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 5000 == 0))
			{
				MainForm.cSuggestion.eSuspect = (enuSuspects)((int)(MainForm.rnd.NextDouble() * 1000) % (int)enuSuspects._numSuspects);
				return;
			}
			else if (eAILevel == enuAILevel.stupid													 // ai may make a poor random choice from ALL REMAINING suspects
					 || (eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 2 == 0)
					 || (eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 5 == 0)
					 || (eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 50 == 0)
					 || (eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0))
			{
				MainForm.cSuggestion.eSuspect = udrAILogic.eSuspectsLeft[(int)(MainForm.rnd.NextDouble() * 1000) % udrAILogic.eSuspectsLeft.Length];
				return;
			}

			if (udrAILogic.eSuspectsLeft.Length == 1)
			{ // I have narrowed down the number of suspects to one and now know which suspect has committed the murder
				// do not reveal this information to other players
				// select a suspect whose card I have in my hands
				if ((int)(MainForm.rnd.NextDouble() * 1000) % 3 == 0)
				{ // one third of the time -> pick the one I know is part of the solution
					MainForm.cSuggestion.eSuspect = udrAILogic.eSuspectsLeft[0];
				}
				else
				{
					if (eSuspectsIHoldACardFor.Length > 0)
					{
						MainForm.cSuggestion.eSuspect = eSuspectsIHoldACardFor[(int)(MainForm.rnd.NextDouble() * 1000) % eSuspectsIHoldACardFor.Length];
						return;
					}

					// I don't hold any suspect cards
					// go around the table in reverse order and pick the first suspect card I know the last suspect to answer my suggest already has
					for (int intSuspectCounter = 1; intSuspectCounter < (int)enuSuspects._numSuspects; intSuspectCounter++)
					{
						enuSuspects eSuspectCounter = (enuSuspects)(((int)eName + (int)enuSuspects._numSuspects - intSuspectCounter) % (int)enuSuspects._numSuspects);
						enuSuspects[] eSuspectCardsIKnowThisSuspectHolds = new enuSuspects[0];
						for (enuCards eSuspectCardCounter = (enuCards)0;
									  eSuspectCardCounter < (enuCards)((enuSuspects)(int)enuSuspects._numSuspects);
									  eSuspectCardCounter++)
						{
							if (udrAILogic.eNotes[(int)eSuspectCounter, (int)eSuspectCardCounter] == enuNote.check)
							{
								Array.Resize<enuSuspects>(ref eSuspectCardsIKnowThisSuspectHolds, eSuspectCardsIKnowThisSuspectHolds.Length + 1);
								eSuspectCardsIKnowThisSuspectHolds[eSuspectCardsIKnowThisSuspectHolds.Length - 1] = MainForm.getESuspectFromCard(eSuspectCardCounter);
							}
						}

						if (eSuspectCardsIKnowThisSuspectHolds.Length > 0)
						{
							MainForm.cSuggestion.eSuspect = eSuspectCardsIKnowThisSuspectHolds[(int)(MainForm.rnd.NextDouble() * 1000) % eSuspectCardsIKnowThisSuspectHolds.Length];
							return;
						}
						else
						{
							MainForm.cSuggestion.eSuspect = udrAILogic.eSuspectsLeft[0];
							return;
						}
					}

					// this shouldn't happen
					// if I reach here : I have no suspect cards and neither do any other suspects in the game
					MessageBox.Show("this should not happen : pickSuspectForSuggestion() -> I know the murder suspect is " + udrAILogic.eSuspectsLeft[0].ToString() + " and I can't pick a reasonable card");
					// program will flow into the suspect we know committed the murder
				}
			}

			// make an informed decision based on the udrAISuggestion information
			if (udrAILogic.cSuggestionAI.lstUdrSuspectMysteryFrequency.Count == 0) // we know of no "mystery" suspect cards -> pick one we don't know at random
				MainForm.cSuggestion.eSuspect = udrAILogic.eSuspectsLeft[(int)(MainForm.rnd.NextDouble() * 1000) % udrAILogic.eSuspectsLeft.Length];
			else if ((int)(MainForm.rnd.NextDouble() * 1000) % 30 == 0) // tweak random frequency according to suspect's intelligence
			{ // one 30th of the time -> pick one we don't know at random
				MainForm.cSuggestion.eSuspect = udrAILogic.eSuspectsLeft[(int)(MainForm.rnd.NextDouble() * 1000) % udrAILogic.eSuspectsLeft.Length];
			}
			else
			{
				// use udrAISuggestion information
				// go around the table in reverse order
				for (int intSuspectCounter = 1; intSuspectCounter < (int)enuSuspects._numSuspects; intSuspectCounter++)
				{
					enuSuspects eSuspectCounter = (enuSuspects)(((int)eName + (int)enuSuspects._numSuspects - intSuspectCounter) % (int)enuSuspects._numSuspects);
					classCardsCalled[] cSetsCardsCalled = udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter].cSetsOfCardsCalled;
					if (cSetsCardsCalled != null)
						for (int intSetsCounter = 0; intSetsCounter < cSetsCardsCalled.Length; intSetsCounter++)
						{
							// for each set of mystery cards for this suspect
							enuCards[] eCardsCalled = cSetsCardsCalled[intSetsCounter].cCardsThatMightHaveBeenShown;
							for (int intCardCounter = 0; intCardCounter < eCardsCalled.Length; intCardCounter++)
							{
								// find the first suspect-card and suggest it
								if (classCard.eCardIsASuspect(eCardsCalled[intCardCounter]))
								{
									MainForm.cSuggestion.eSuspect = MainForm.getESuspectFromCard(eCardsCalled[intCardCounter]);
									return;
								}
							}
						}

				}
				// if still haven't made a choice -> pick the most common 'mystery' suspect
				MainForm.cSuggestion.eSuspect = MainForm.getESuspectFromCard(udrAILogic.cSuggestionAI.lstUdrSuspectMysteryFrequency[0].eCards);
			}
		}

		void pickWeaponForSuggestion()
		{
			if ((eAILevel == enuAILevel.stupid && (int)(MainForm.rnd.NextDouble() * 1000) % 2 == 0) // ai may make a poor random choice from ALL suspects
				|| (eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 5 == 0)
				|| (eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 50 == 0)
				|| (eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0)
				|| (eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 5000 == 0))
			{
				MainForm.cSuggestion.eWeapon = (enuWeapons)((int)(MainForm.rnd.NextDouble() * 1000) % (int)enuWeapons._numWeapons);
				return;
			}
			else if (eAILevel == enuAILevel.stupid													 // ai may make a poor random choice from ALL REMAINING suspects
					 || (eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 2 == 0)
					 || (eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 5 == 0)
					 || (eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 50 == 0)
					 || (eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0))
			{
				MainForm.cSuggestion.eWeapon = udrAILogic.eWeaponsLeft[(int)(MainForm.rnd.NextDouble() * 1000) % udrAILogic.eWeaponsLeft.Length];
				return;
			}

			if (udrAILogic.eWeaponsLeft.Length == 1)
			{ // I have narrowed down the number of Weapons to one and now know which Weapon was used in committing the murder
				// do not reveal this information to other players
				// select a Weapon whose card I have in my hands
				if ((int)(MainForm.rnd.NextDouble() * 1000) % 3 == 0)
				{ // one third of the time -> pick the one I know is part of the solution
					MainForm.cSuggestion.eWeapon = udrAILogic.eWeaponsLeft[0];
					return;
				}
				else
				{
					if (eWeaponsIHoldACardFor.Length > 0)
					{
						MainForm.cSuggestion.eWeapon = eWeaponsIHoldACardFor[(int)(MainForm.rnd.NextDouble() * 1000) % eWeaponsIHoldACardFor.Length];
						return;
					}

					// I don't hold any Weapon cards
					// go around the table in reverse order and pick the first Weapon card I know the last suspect to answer my suggest already has
					for (int intSuspectCounter = 1; intSuspectCounter < (int)enuSuspects._numSuspects; intSuspectCounter++)
					{
						enuSuspects eSuspectCounter = (enuSuspects)(((int)eName + (int)enuSuspects._numSuspects - intSuspectCounter) % (int)enuSuspects._numSuspects);

						enuWeapons[] eWeaponCardsIKnowThisSuspectHolds = new enuWeapons[0];
						for (enuCards eWeaponCardCounter = (enuCards)(int)enuSuspects._numSuspects;
									  eWeaponCardCounter < (enuCards)((enuWeapons)((int)enuSuspects._numSuspects + (int)enuWeapons._numWeapons));
									  eWeaponCardCounter++)
						{ // cycle through all weapons cards
							if (udrAILogic.eNotes[(int)eSuspectCounter, (int)eWeaponCardCounter] == enuNote.check)
							{ // I know this suspect has this weapon-card
								Array.Resize<enuWeapons>(ref eWeaponCardsIKnowThisSuspectHolds, eWeaponCardsIKnowThisSuspectHolds.Length + 1);
								eWeaponCardsIKnowThisSuspectHolds[eWeaponCardsIKnowThisSuspectHolds.Length - 1] = MainForm.getEWeaponFromCard(eWeaponCardCounter);
							}
						}

						if (eWeaponCardsIKnowThisSuspectHolds.Length > 0)
						{
							MainForm.cSuggestion.eWeapon = eWeaponCardsIKnowThisSuspectHolds[(int)(MainForm.rnd.NextDouble() * 1000) % eWeaponCardsIKnowThisSuspectHolds.Length];
							return;
						}
						else
						{
							MainForm.cSuggestion.eWeapon = udrAILogic.eWeaponsLeft[0];
							return;
						}
					}
				}
				// this shouldn't happen
				// if I reach here : I have no Weapon cards and neither do any other suspects in the game
				MessageBox.Show("this should not happen : pickWeaponForSuggestion() -> I know the murder Weapon is " + udrAILogic.eWeaponsLeft[0].ToString() + " and I can't pick a reasonable card");
				// program will flow into the Weapon we know committed the murder
			}

			// make an informed decision based on the udrAISuggestion information
			if (udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency.Count == 0) // we know of no "mystery" Weapon cards -> pick one we don't know at random
				MainForm.cSuggestion.eWeapon = udrAILogic.eWeaponsLeft[(int)(MainForm.rnd.NextDouble() * 1000) % udrAILogic.eWeaponsLeft.Length];
			else if ((eAILevel == enuAILevel.stupid && (int)(MainForm.rnd.NextDouble() * 1000) % 2 == 0) // ai may make a poor random choice from ALL REMAINING weapons
					|| (eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 5 == 0)
					|| (eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 50 == 0)
					|| (eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0)
					|| (eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 5000 == 0))// tweak random frequency according to suspect's intelligence
			{
				MainForm.cSuggestion.eWeapon = udrAILogic.eWeaponsLeft[(int)(MainForm.rnd.NextDouble() * 1000) % udrAILogic.eWeaponsLeft.Length];
			}
			else
			{
				// use udrAISuggestion information
				enuCards eSuspectCardSelected = MainForm.getCardFromESuspect(MainForm.cSuggestion.eSuspect);
				for (int intWeaponCounter = 0; intWeaponCounter < udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency.Count; intWeaponCounter++)
				{
					// if no suspect has both the previously selected 'suspect card' in his list of unknowns AND this 'weapon card' -> select this weapon card
					bool bolThisWeaponOk = true;
					for (int intSuspectCounter = udrAILogic.cSuggestionAI.lstSuspectMysteryInfo.Count - 1; intSuspectCounter >= 0; intSuspectCounter--)
					{
						if ((eCardIsInArray(udrAILogic.cSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter].lstUdrSuspectCardsMystery,
											 eSuspectCardSelected) // 
							&& eCardIsInArray(udrAILogic.cSuggestionAI.lstSuspectMysteryInfo[intSuspectCounter].lstUdrWeaponCardsMystery,
											  udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency[intWeaponCounter].eCards)))
						{
							bolThisWeaponOk = false;
						}
					}
					if (bolThisWeaponOk)
					{
						MainForm.cSuggestion.eWeapon = MainForm.getEWeaponFromCard(udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency[intWeaponCounter].eCards);
						return;
					}
				}
				// no suspect has only one
				// scan all weapons left
				// pick one that is not in the list of unknowns
				enuWeapons[] eWeaponArray = new enuWeapons[0];
				for (int intWeaponCounter = 0; intWeaponCounter < udrAILogic.eWeaponsLeft.Length; intWeaponCounter++)
				{
					if (!eCardIsInArray(udrAILogic.cSuggestionAI.lstUdrWeaponMysteryFrequency, MainForm.getCardFromEWeapon(udrAILogic.eWeaponsLeft[intWeaponCounter])))
					{
						Array.Resize<enuWeapons>(ref eWeaponArray, eWeaponArray.Length + 1);
						eWeaponArray[eWeaponArray.Length - 1] = udrAILogic.eWeaponsLeft[intWeaponCounter];
					}
				}

				if (eWeaponArray.Length > 0)
				{ // there are a few options
					MainForm.cSuggestion.eWeapon = eWeaponArray[((int)MainForm.rnd.NextDouble() * 10000) % eWeaponArray.Length];
					return;
				}

				// the only weapons left are possibly in the hands of the same suspect
				// pick one at random 
				MainForm.cSuggestion.eWeapon = udrAILogic.eWeaponsLeft[((int)MainForm.rnd.NextDouble() * 10000) % udrAILogic.eWeaponsLeft.Length];
				return;
			}
		}

		bool eCardIsInArray(List<classSuggestionAI_CardFrequency> lstUdrFreqCardsArray, enuCards eCard)
		{
			if (lstUdrFreqCardsArray == null)
				return false;
			for (int intCardCounter = 0; intCardCounter < lstUdrFreqCardsArray.Count; intCardCounter++)
			{
				if (lstUdrFreqCardsArray[intCardCounter].eCards == eCard)
					return true;
			}
			return false;
		}

		bool ICanLeaveThisRoom()
		{
			classRoom cRoom = MainForm.cRooms[(int)eRoom];

			for (int intDoorCounter = 0; intDoorCounter < cRoom.ptDoors.Length; intDoorCounter++)
			{
				if (cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor == enuDir.secretPassage)
					return true;
				else
				{
					Point ptNext = MainForm.movePoint(cRoom.ptDoors[intDoorCounter], cFloor[cRoom.ptDoors[intDoorCounter].X, cRoom.ptDoors[intDoorCounter].Y].dirDoor);
					if (MainForm.floorTileIsFree(ptNext))
						return true;
				}
			}
			return false;
		}

		bool PickDestinationTile()
		{
			// start from destination room 
			// travel back along shortest path until reach a tile that is included in the allowable tiles

			if (eRoom < enuRooms._numRooms)
			{
				if (!ICanLeaveThisRoom())
					return false;
			}

			Point ptCurrentTile = new Point(0, 0);
			bool bolAllowSecretPassage =(eRoom != enuRooms.start 
										&& eRoom != enuRooms.tiles 
										&& (udrAILogic.eDestinationRoom != MainForm.cRooms[(int)eRoom].oppositeCornerRoom()));

			bool bolThereIsADoorOutOfDestinationRoom = getBestDoorOutThisRoom(udrAILogic.eDestinationRoom, ref ptCurrentTile,bolAllowSecretPassage);
			 
			if (ptCurrentTile.X < 0) // using secret passage -> decode roomID -> get best door out of next room
			{
				enuRooms eRoomOnOtherSideOfPassage = (enuRooms)(Math.Abs(ptCurrentTile.X) % ((int)enuRooms._numRooms));
				if (eRoomOnOtherSideOfPassage == udrAILogic.eDestinationRoom)
				{
					switch (eRoom)
					{
						case enuRooms.Study:
							udrAILogic.ptDestinationTile = new Point(0, 0);
							return true;

						case enuRooms.Lounge:
							udrAILogic.ptDestinationTile = new Point(23, 0);
							return true;

						case enuRooms.Kitchen:
							udrAILogic.ptDestinationTile = new Point(23, 23);
							return true;

						case enuRooms.Conservatory:
							udrAILogic.ptDestinationTile = new Point(0, 23);
							return true;
					}
				}
				else if (eRoomOnOtherSideOfPassage == MainForm.cRooms[(int)udrAILogic.eDestinationRoom].oppositeCornerRoom())
				{
					getBestDoorOutThisRoom(eRoomOnOtherSideOfPassage, ref ptCurrentTile, false);
				}
				else
					getBestDoorOutThisRoom((enuRooms)(Math.Abs(ptCurrentTile.X) % (int)enuRooms._numRooms), ref ptCurrentTile, true);
			}
			else if (cSEAllowableMoves[ptCurrentTile.X, ptCurrentTile.Y] == null)
			{
				ptCurrentTile = MainForm.movePoint(ptCurrentTile, classSuspect.cFloor[ptCurrentTile.X, ptCurrentTile.Y].dirDoor);
			}

			while (cSEAllowableMoves[ptCurrentTile.X, ptCurrentTile.Y] == null)
			{
				if (classSuspect.cFloor[ptCurrentTile.X, ptCurrentTile.Y].eType == enuFloor.door)
				{
					getBestDoorOutThisRoom(classSuspect.cFloor[ptCurrentTile.X, ptCurrentTile.Y].eRoom, ref ptCurrentTile, true);
					if (ptCurrentTile.X < 0)
					{ // using secret passage
						enuRooms eThisRoom = (enuRooms)((int)Math.Abs(ptCurrentTile.X) % (int)enuRooms._numRooms);
						getBestDoorOutThisRoom(eThisRoom, ref ptCurrentTile, true);
					}
					else if (cSEAllowableMoves[ptCurrentTile.X, ptCurrentTile.Y] == null)
					{
						ptCurrentTile = MainForm.movePoint(ptCurrentTile, classSuspect.cFloor[ptCurrentTile.X, ptCurrentTile.Y].dirDoor);
					}
				}
				else
					ptCurrentTile = MainForm.movePoint(ptCurrentTile, cShortestPath[ptCurrentTile.X, ptCurrentTile.Y].SrcDir);
			}
			udrAILogic.ptDestinationTile = ptCurrentTile;
			return true;
		}

		bool getBestDoorOutThisRoom(enuRooms eRoom, ref Point ptTileOfBestDoor) { return getBestDoorOutThisRoom(eRoom, ref ptTileOfBestDoor, true); }
		bool getBestDoorOutThisRoom(enuRooms eThisRoom, ref Point ptTileOfBestDoor, bool bolAllowSecretPassage)
		{
			classRoom cRoom = MainForm.cRooms[(int)eThisRoom];
			Point[] ptDoors = cRoom.getValidDoors(bolAllowSecretPassage);

			// cancel blocked doors
			for (int intDoorCounter = 0; intDoorCounter < ptDoors.Length; intDoorCounter++)
			{
				Point ptTileOutsideDoor = MainForm.movePoint(ptDoors[intDoorCounter], cFloor[ptDoors[intDoorCounter].X, ptDoors[intDoorCounter].Y].dirDoor);
				if (!MainForm.floorTileIsFree(ptTileOutsideDoor) && ptTile != ptTileOutsideDoor) // if the door is not blocked (by some other suspect)
				{ // this door is blocked
					ptDoors[intDoorCounter] = ptDoors[ptDoors.Length - 1];
					Array.Resize<Point>(ref ptDoors, ptDoors.Length - 1);
				}
			}

			if (ptDoors.Length == 0)
				return false;

			ptTileOfBestDoor = ptDoors[0];  // start with door 0th index
			if (classSuspect.cFloor[ptTileOfBestDoor.X, ptTileOfBestDoor.Y].dirDoor == enuDir.secretPassage)
				if (ptDoors.Length > 1)
					ptTileOfBestDoor = ptDoors[1];
				else
				{
					if (bolAllowSecretPassage)
					{
						switch (cRoom.name)
						{  // encode destination Room's ID into door's "point"
							case enuRooms.Lounge:
								ptTileOfBestDoor = new Point(-6, -6);
								return true;

							case enuRooms.Study:
								ptTileOfBestDoor = new Point(-4, -4);
								return true;

							case enuRooms.Kitchen:
								ptTileOfBestDoor = new Point(-(int)enuRooms._numRooms, -(int)enuRooms._numRooms); // study's ID is 'zero' -> decode with Modulo of absolute value
								return true;

							case enuRooms.Conservatory:
								ptTileOfBestDoor = new Point(-2, -2);
								return true;
						}
					}
					else
						return false;
				}

			for (int intDoorCounter = 0; intDoorCounter < ptDoors.Length; intDoorCounter++)
			{
				Point ptDoor = ptDoors[intDoorCounter];
				if (classSuspect.cFloor[ptDoor.X, ptDoor.Y].dirDoor == enuDir.secretPassage)
				{ // code roomID of room on other side of secret passage into x & y values of 'best door' point
					Point ptNextBestDoor = new Point(0, 0);
					// test shortest path travel cost for this door
					switch (cRoom.name)
					{
						case enuRooms.Lounge:
							ptNextBestDoor = new Point(0, 23);
							break;

						case enuRooms.Study:
							ptNextBestDoor = new Point(23, 23);
							break;

						case enuRooms.Kitchen:
							ptNextBestDoor = new Point(0, 0);
							break;

						case enuRooms.Conservatory:
							ptNextBestDoor = new Point(23, 0);
							break;
					}

					if (cShortestPath[ptNextBestDoor.X, ptNextBestDoor.Y] != null
						&& cShortestPath[ptNextBestDoor.X, ptNextBestDoor.Y].intTurns * 3 + cShortestPath[ptNextBestDoor.X, ptNextBestDoor.Y].intSteps
							< cShortestPath[ptTileOfBestDoor.X, ptTileOfBestDoor.Y].intTurns * 3 + cShortestPath[ptTileOfBestDoor.X, ptTileOfBestDoor.Y].intSteps)
					{ // using this secret passage is a short cut to destination
						switch (cRoom.name)
						{  // encode destination Room's ID into door's "point"
							case enuRooms.Lounge:
								ptTileOfBestDoor = new Point(-6, -6);
								return true;

							case enuRooms.Study:
								ptTileOfBestDoor = new Point(-4, -4);
								return true;

							case enuRooms.Kitchen:
								ptTileOfBestDoor = new Point(-(int)enuRooms._numRooms, -(int)enuRooms._numRooms); // study's ID is 'zero' -> decode with Modulo of absolute value
								return true;

							case enuRooms.Conservatory:
								ptTileOfBestDoor = new Point(-2, -2);
								return true;
						}
						return true;
					}
				}
				else
				{
					Point ptNextTile = MainForm.movePoint(ptDoor, classSuspect.cFloor[ptDoor.X, ptDoor.Y].dirDoor);
					if (cShortestPath[ptNextTile.X, ptNextTile.Y] != null)
						if (cShortestPath[ptNextTile.X, ptNextTile.Y].intTurns * 3 + cShortestPath[ptNextTile.X, ptNextTile.Y].intSteps
							<
							cShortestPath[ptTileOfBestDoor.X, ptTileOfBestDoor.Y].intTurns * 3 + cShortestPath[ptTileOfBestDoor.X, ptTileOfBestDoor.Y].intSteps)
						{
							ptTileOfBestDoor = ptDoors[intDoorCounter];
						}
				}
			}

			return true;
		}

		void PickDestinationRoom()
		{
			classTurnsReachRoom[] cNumTurnsReachableRooms = new classTurnsReachRoom[0];
			string strReachableRooms = ".";
			for (int intRoomCounter = 0; intRoomCounter < cNumTurnsToReachRooms.Length; intRoomCounter++)
			{
				if (cNumTurnsToReachRooms[intRoomCounter].getCost > 0 && cNumTurnsToReachRooms[intRoomCounter].getCost < 1000)
				{
					Array.Resize<classTurnsReachRoom>(ref	cNumTurnsReachableRooms, cNumTurnsReachableRooms.Length + 1);
					cNumTurnsReachableRooms[cNumTurnsReachableRooms.Length - 1] = cNumTurnsToReachRooms[intRoomCounter];
					strReachableRooms += cNumTurnsToReachRooms[intRoomCounter].ToString().ToUpper() + ".";
				}
			}
			cNumTurnsToReachRooms = cNumTurnsReachableRooms;

			if ((eAILevel == enuAILevel.stupid && (int)(MainForm.rnd.NextDouble() * 1000) % 2 == 0) // ai may make a poor random choice from ALL remaining accessible rooms
				|| (eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 5 == 0)
				|| (eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 50 == 0)
				|| (eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0)
				|| (eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 5000 == 0))
			{
				if (cNumTurnsToReachRooms.Length > 0)
				{
					udrAILogic.eDestinationRoom = (cNumTurnsToReachRooms[((int)(MainForm.rnd.NextDouble() * 1000) % cNumTurnsToReachRooms.Length)].eRoom);
				}
				else
				{
					udrAILogic.eDestinationRoom = eRoom;

				}
				return;
			}

			// reorder list of rooms in ascending number of turns
			int intBestIndex;
			int intInnerLoop, intOuterLoop;
			for (intOuterLoop = 0; intOuterLoop < cNumTurnsToReachRooms.Length - 1; intOuterLoop++)
			{
				intBestIndex = intOuterLoop;
				for (intInnerLoop = intOuterLoop + 1; intInnerLoop < cNumTurnsToReachRooms.Length; intInnerLoop++)
				{
					if (cNumTurnsToReachRooms[intInnerLoop].getCost < cNumTurnsToReachRooms[intBestIndex].getCost)
						intBestIndex = intInnerLoop;
				}
				if (intBestIndex != intOuterLoop)
				{
					classTurnsReachRoom cTemp = cNumTurnsToReachRooms[intOuterLoop];
					cNumTurnsToReachRooms[intOuterLoop] = cNumTurnsToReachRooms[intBestIndex];
					cNumTurnsToReachRooms[intBestIndex] = cTemp;
				}
			}

			if (cNumTurnsToReachRooms.Length == 0)
			{
				udrAILogic.eDestinationRoom = eRoom;
				return;
			}

			if (udrAILogic.eRoomsLeft.Length == 1)
			{ // I have narrowed down the possible room solutions and now know which room the murder was committed in
				// avoid revealing this information to other players by choosing another room
				udrAILogic.eDestinationRoom = cNumTurnsToReachRooms[0].eRoom; // default is the nearest room

				if ((eAILevel == enuAILevel.stupid && (int)(MainForm.rnd.NextDouble() * 1000) % 2 == 0) // ai may make a poor choice and go to the nearest room
					|| (eAILevel == enuAILevel.dull && (int)(MainForm.rnd.NextDouble() * 1000) % 5 == 0)
					|| (eAILevel == enuAILevel.average && (int)(MainForm.rnd.NextDouble() * 1000) % 50 == 0)
					|| (eAILevel == enuAILevel.bright && (int)(MainForm.rnd.NextDouble() * 1000) % 500 == 0)
					|| (eAILevel == enuAILevel.genius && (int)(MainForm.rnd.NextDouble() * 1000) % 5000 == 0))
					return;

				if (eRoomsIHoldACardFor.Length > 0)
				{ // pick a room for which I hold the card (not give away the murder-room solution)
					for (int intRoomCounter = 0; intRoomCounter < cNumTurnsToReachRooms.Length; intRoomCounter++)
					{ // scan through the list in order ranked by distance (nearest first)
						if (cNumTurnsToReachRooms[intRoomCounter].getCost > 0)
						{ // exclude the room I am in
							for (int intCardRoomsIHaveCounter = 0; intCardRoomsIHaveCounter < eRoomsIHoldACardFor.Length; intCardRoomsIHaveCounter++)
							{ // compare to the rooms I have a card for
								if (eRoomsIHoldACardFor[intCardRoomsIHaveCounter] == cNumTurnsToReachRooms[intRoomCounter].eRoom)
								{ // I have this room's card -> go there
									udrAILogic.eDestinationRoom = cNumTurnsToReachRooms[intRoomCounter].eRoom;
									return;
								}
							}
						}
					}
				}

				// if I am still here it is because I do not hold any room cards
				// go around the table and pick a room which I know player to my right hold
				for (int intSuspectCounter = 1; intSuspectCounter < (int)enuSuspects._numSuspects; intSuspectCounter++)
				{
					enuSuspects eSuspectCounter = (enuSuspects)((int)eName + (int)enuSuspects._numSuspects - intSuspectCounter);

					enuRooms[] eRoomsIKnowThisSuspectHas = new enuRooms[0];
					for (enuCards eCardCounter = (enuCards)((int)enuSuspects._numSuspects + (int)enuWeapons._numWeapons);
								  eCardCounter < enuCards._numCards;
								  eCardCounter++)
					{ // scan through all room cards
						if (strReachableRooms.Contains(eCardCounter.ToString().ToUpper())) // if it is a reachable room
						{
							if (udrAILogic.eNotes[(int)eSuspectCounter, (int)eCardCounter] == enuNote.check)
							{ // my notes tell me this suspect has this room card in his hands
								Array.Resize<enuRooms>(ref eRoomsIKnowThisSuspectHas, eRoomsIKnowThisSuspectHas.Length + 1);
								eRoomsIKnowThisSuspectHas[eRoomsIKnowThisSuspectHas.Length - 1] = MainForm.getERoomFromCard(eCardCounter);
							}
						}
					}

					for (int intRoomCounter = 0; intRoomCounter < cNumTurnsToReachRooms.Length; intRoomCounter++)
					{ // scan through the list in order ranked by distance (nearest first)
						if (cNumTurnsToReachRooms[intRoomCounter].getCost > 0)
						{ // exclude the room I am in
							for (int intCardRoomsThisSuspectHasCounter = 0; intCardRoomsThisSuspectHasCounter < eRoomsIKnowThisSuspectHas.Length; intCardRoomsThisSuspectHasCounter++)
							{ // compare to the rooms I have a card for
								if (eRoomsIKnowThisSuspectHas[intCardRoomsThisSuspectHasCounter] == cNumTurnsToReachRooms[intRoomCounter].eRoom)
								{ // I have this room's card -> go there
									udrAILogic.eDestinationRoom = cNumTurnsToReachRooms[intRoomCounter].eRoom;
									return;
								}
							}
						}
					}
				}
			}

			// scan list until find a good choice

			udrAILogic.eDestinationRoom = cNumTurnsToReachRooms[0].eRoom; // default is the nearest room
			for (int intRoomCounter = 0; intRoomCounter < cNumTurnsToReachRooms.Length; intRoomCounter++)
			{
				if (cNumTurnsToReachRooms[intRoomCounter].getCost > 0)
				{
					if (eRoomIsStillPossibleSolution(cNumTurnsToReachRooms[intRoomCounter].eRoom))
					{
						udrAILogic.eDestinationRoom = cNumTurnsToReachRooms[intRoomCounter].eRoom;
						return;
					}
				}
			}
		}

		bool eRoomIsStillPossibleSolution(enuRooms eRoom)
		{
			for (int intRoomCounter = 0; intRoomCounter < udrAILogic.eRoomsLeft.Length; intRoomCounter++)
				if (eRoom == udrAILogic.eRoomsLeft[intRoomCounter])
					return true;
			return false;
		}

		bool eWeaponIsStillPossibleSolution(enuWeapons eWeapon)
		{
			for (int intWeaponCounter = 0; intWeaponCounter < udrAILogic.eWeaponsLeft.Length; intWeaponCounter++)
				if (eWeapon == udrAILogic.eWeaponsLeft[intWeaponCounter])
					return true;
			return false;
		}

		bool eSuspectIsStillPossibleSolution(enuSuspects eSuspect)
		{
			for (int intSuspectCounter = 0; intSuspectCounter < udrAILogic.eSuspectsLeft.Length; intSuspectCounter++)
				if (eSuspect == udrAILogic.eSuspectsLeft[intSuspectCounter])
					return true;
			return false;
		}

		public void setAI()
		{
			eRoomsIHoldACardFor = new enuRooms[0];
			for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
			{
				if (cCards[intCardCounter].IsARoom)
				{
					Array.Resize<enuRooms>(ref eRoomsIHoldACardFor, eRoomsIHoldACardFor.Length + 1);
					eRoomsIHoldACardFor[eRoomsIHoldACardFor.Length - 1] = MainForm.getERoomFromCard(cCards[intCardCounter].eCardName);
				}
			}

			eSuspectsIHoldACardFor = new enuSuspects[0];
			for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
			{
				if (cCards[intCardCounter].IsASuspect)
				{
					Array.Resize<enuSuspects>(ref eSuspectsIHoldACardFor, eSuspectsIHoldACardFor.Length + 1);
					eSuspectsIHoldACardFor[eSuspectsIHoldACardFor.Length - 1] = MainForm.getESuspectFromCard(cCards[intCardCounter].eCardName);
				}
			}

			eWeaponsIHoldACardFor = new enuWeapons[0];
			for (int intCardCounter = 0; intCardCounter < cCards.Length; intCardCounter++)
			{
				if (cCards[intCardCounter].IsAWeapon)
				{
					Array.Resize<enuWeapons>(ref eWeaponsIHoldACardFor, eWeaponsIHoldACardFor.Length + 1);
					eWeaponsIHoldACardFor[eWeaponsIHoldACardFor.Length - 1] = MainForm.getEWeaponFromCard(cCards[intCardCounter].eCardName);
				}
			}

			for (enuSuspects eSuspectCounter = (enuSuspects)0; eSuspectCounter < enuSuspects._numSuspects; eSuspectCounter++)
				udrAILogic.cSuspectsUnknowns[(int)eSuspectCounter] = new classSuspectCardsCalled();
		}
	}

	public class classWeapon
	{
		public enuWeapons eName;
		public Point pt;
		enuRooms _eRoom;

		public classWeapon(enuWeapons weaponName)
		{
			eName = weaponName;
			_eRoom = enuRooms._numRooms;
		}

		public enuRooms eRoom
		{
			get { return _eRoom; }
			set
			{
				_eRoom = value;
			}
		}
	}

	public class classCard
	{
		public enuCardType eType;
		public enuCards eCardName;
		public classSuspect cSuspect;
		public classRotatedImage cBmp = new classRotatedImage();
		formClue_2022 MainForm;

		public classAnimationInfo cAnimationInfo = new classAnimationInfo();

		public classCard(formClue_2022 mainform, enuCards Name)
		{
			MainForm = mainform;
			eCardName = Name;
			setCardType();
			setImage();
		}

		string getRootDirectory(string strThisDirectory)
		{
			int intIndexBackSlash = strThisDirectory.LastIndexOf("\\");
			if (intIndexBackSlash > 0)
				return strThisDirectory.Substring(0, intIndexBackSlash);
			return "";
		}

		string FileExists(string strImageName)
		{
			string strDir = System.IO.Directory.GetCurrentDirectory();
			string strFilename = strImageName + ".rBMP";

			string strFilenameAndDirectory = strDir + "\\" + strFilename;

			if (System.IO.File.Exists(strFilenameAndDirectory))
				return strFilenameAndDirectory;
			else
			{
				while (strDir.Length > 0)
				{
					strDir = getRootDirectory(strDir);
					strFilenameAndDirectory = strDir + "\\" + strFilename;
					if (System.IO.File.Exists(strFilenameAndDirectory))
						return strFilenameAndDirectory;
				}
			}
			return strImageName;
		}

		void setImage()
		{
			string strCurrentDir_Filename = System.IO.Directory.GetCurrentDirectory() + "\\" + eCardName.ToString() + ".rbmp";				
			bool bolSaveCurrentDir = false;
			if (!System.IO.File.Exists(strCurrentDir_Filename))
				bolSaveCurrentDir = true;
			MainForm.advanceProBar();
			string strFilename = FileExists(eCardName.ToString());

			if (System.IO.File.Exists(strFilename))
			{
				cBmp.loadBaseImages(strFilename);
				if (bolSaveCurrentDir)
					cBmp.saveBaseImages(strCurrentDir_Filename);
			}
			else
			{

				double dblFractionSize = 0.75;
				Size sz = new Size((int)(Resources.cardback.Width * dblFractionSize), (int)(Resources.cardback.Height * dblFractionSize));

				switch (eCardName)
				{
					/// suspects
					case enuCards.ColMustard:
						cBmp.createBaseImage(new Bitmap(Resources.CardSuspectColMustard, sz));
						break;

					case enuCards.ProfPlum:
						cBmp.createBaseImage(new Bitmap(Resources.CardSuspectProfPlum, sz));
						break;

					case enuCards.RevGreen:
						cBmp.createBaseImage(new Bitmap(Resources.CardSuspectRevGreen, sz));
						break;

					case enuCards.MrsPeacock:
						cBmp.createBaseImage(new Bitmap(Resources.CardSuspectMrsPeacock, sz));
						break;

					case enuCards.MissScarlet:
						cBmp.createBaseImage(new Bitmap(Resources.CardSuspectMissScarlet, sz));
						break;

					case enuCards.MrsWhite:
						cBmp.createBaseImage(new Bitmap(Resources.CardSuspectMrsWhite, sz));
						break;

					/// weapons
					case enuCards.Knife:
						cBmp.createBaseImage(new Bitmap(Resources.CardWeaponKnife, sz));
						break;

					case enuCards.Candlestick:
						cBmp.createBaseImage(new Bitmap(Resources.CardWeaponCandleStick, sz));
						break;

					case enuCards.Revolver:
						cBmp.createBaseImage(new Bitmap(Resources.CardWeaponRevolver, sz));
						break;

					case enuCards.Rope:
						cBmp.createBaseImage(new Bitmap(Resources.CardWeaponRope, sz));
						break;

					case enuCards.LeadPipe:
						cBmp.createBaseImage(new Bitmap(Resources.CardWeaponLeadPipe, sz));
						break;

					case enuCards.Wrench:
						cBmp.createBaseImage(new Bitmap(Resources.CardWeaponWrench, sz));
						break;

					/// rooms
					case enuCards.Hall:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomHall, sz));
						break;

					case enuCards.Lounge:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomLounge, sz));
						break;

					case enuCards.DiningRoom:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomDiningRoom, sz));
						break;

					case enuCards.Kitchen:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomKitchen, sz));
						break;

					case enuCards.BallRoom:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomBallroom, sz));
						break;

					case enuCards.Conservatory:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomConservatory, sz));
						break;

					case enuCards.BilliardRoom:
						cBmp.createBaseImage(new Bitmap(Resources.CardBilliardRoom, sz));
						break;

					case enuCards.Library:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomLibrary, sz));
						break;

					case enuCards.Study:
						cBmp.createBaseImage(new Bitmap(Resources.CardRoomStudy, sz));
						break;

					case enuCards.Unknown:
						cBmp.createBaseImage(new Bitmap(Resources.cardback, sz));
						break;
				}

				cBmp.getImage(0); MainForm.advanceProBar();

				cBmp.getImage(1); MainForm.advanceProBar();
				cBmp.getImage(2); MainForm.advanceProBar();
				cBmp.getImage(3); MainForm.advanceProBar();

				cBmp.saveBaseImages(strCurrentDir_Filename);
			}
		}

		/// <summary>
		/// assumes card starts with initial velocity, slides across table and slowly stops
		/// </summary>
		/// <param name="ptStart">start position on the screen</param>
		/// <param name="ptEnd">end position on the screen</param>
		/// <param name="intNumSteps">number of clock cycles to reach end position and v=0 given a constant negative acceleration</param>
		public void setAnimationVelocity(Point ptStart, Point ptEnd, int intNumSteps)
		{
			cAnimationInfo.ptStart = ptStart;
			cAnimationInfo.ptEnd = ptEnd;
			cAnimationInfo.dblTravelAngle = classMath.arcTan(ptEnd.X - ptStart.X, ptEnd.Y - ptStart.Y);
			cAnimationInfo.dblTravelDistance = Math.Sqrt(Math.Pow(ptEnd.X - ptStart.X, 2) + Math.Pow(ptEnd.Y - ptStart.Y, 2));
			cAnimationInfo.dblTravelAcceleration = -10;
			cAnimationInfo.intMaxSteps = 25 + (int)(MainForm.rnd.NextDouble() * 1000) % 20;
			cAnimationInfo.dblTravelInitialVelocity = -cAnimationInfo.intMaxSteps * cAnimationInfo.dblTravelAcceleration;
		}

		void setCardType()
		{
			int intCardNum = (int)eCardName;
			if (intCardNum < 6)
				eType = enuCardType.Suspect;
			else if (intCardNum < 12)
				eType = enuCardType.weapon;
			else
				eType = enuCardType.room;
			SetIsARoom();
			SetIsAWeapon();
			SetIsASuspect();
		}

		bool bolIsARoom;
		public bool IsARoom
		{
			get { return bolIsARoom; }
		}
		void SetIsARoom()
		{
			bolIsARoom = eCardIsARoom(eCardName);
		}

		public static bool eCardIsARoom(enuCards eCard)
		{
			return ((int)eCard >= (int)enuSuspects._numSuspects + (int)enuWeapons._numWeapons);
		}

		bool bolIsAWeapon;
		public bool IsAWeapon
		{
			get { return bolIsAWeapon; }
		}
		void SetIsAWeapon()
		{
			bolIsAWeapon = eCardIsAWeapon(eCardName);
		}
		public static bool eCardIsAWeapon(enuCards eCard)
		{
			return ((int)eCard >= (int)enuSuspects._numSuspects && (int)eCard < (int)enuSuspects._numSuspects + (int)enuWeapons._numWeapons);
		}

		bool bolIsASuspect;
		public bool IsASuspect
		{
			get { return bolIsASuspect; }
		}
		void SetIsASuspect()
		{
			bolIsASuspect = eCardIsASuspect(eCardName);
		}
		public static bool eCardIsASuspect(enuCards eCard)
		{
			return ((int)eCard < (int)enuSuspects._numSuspects);
		}

		public static enuCards getECardFromERoom(enuRooms eThisRoom) { return (enuCards)((int)eThisRoom + (int)enuSuspects._numSuspects + (int)enuWeapons._numWeapons); }
		public static enuCards getECardFromESuspect(enuSuspects eThisSuspect) { return (enuCards)(int)eThisSuspect; }
		public static enuCards getECardFromEWeapon(enuWeapons eThisWeapon) { return (enuCards)((int)eThisWeapon + (int)enuSuspects._numSuspects); }
	}

	public class classFloor
	{
		public enuFloor eType;
		public enuDir dirDoor;
		public enuRooms eRoom;
	}

	public class classButton
	{
		static Brush brWhite;
		public Point pt;
		public Size sz;
		public Color clrBorder;
		public string strText;
		public Font fnt;
		public Bitmap bmpMyself;
		public Bitmap bmpMyHighlight;
		public PictureBox picBox;
		public formClue_2022 mainForm;
		public enuMode eMode;
		public classNote cNote;

		public enuButtons eButtonName;

		public classButton(formClue_2022 MainForm, ref PictureBox picField, enuMode Mode, Point Pt, Color ClrBorder, string text, Font myFont)
		{
			picBox = picField;
			eMode = Mode;
			mainForm = MainForm;
			pt = Pt;
			clrBorder = ClrBorder;
			strText = text;
			fnt = myFont;
			if (text.Length > 0 && fnt != null)
				setImage();
			if (brWhite == null)
				brWhite = new SolidBrush(Color.White);
		}

		public string Text
		{
			get { return strText; }
			set
			{
				strText = value;
				setImage();
			}
		}

		void setImage()
		{
			bmpMyself = mainForm.getTextImage(strText, fnt);
			Rectangle recBorder = new Rectangle(0, 0, bmpMyself.Width - 1, bmpMyself.Height - 7);
			using (Graphics g = Graphics.FromImage(bmpMyself))
			{
				g.DrawRectangle(new Pen(clrBorder), recBorder);
			}

			bmpMyHighlight = new Bitmap(bmpMyself);

			using (Graphics g = Graphics.FromImage(bmpMyHighlight))
				g.DrawRectangle(new Pen(Color.Red), recBorder);
			sz = recBorder.Size;
		}

		public void draw()
		{
			if (mainForm.eMode != eMode && eMode != enuMode.any)
				return;
			if (bmpMyself == null || bmpMyHighlight == null)
				setImage();

			Bitmap bmpTemp = new Bitmap(picBox.Image);
			using (Graphics g = Graphics.FromImage(bmpTemp))
				g.DrawImage(bmpMyself, pt);

			picBox.Image = bmpTemp; picBox.Refresh();
		}

		public void highlight()
		{
			if (mainForm.eMode != eMode && eMode != enuMode.any)
				return;

			if (bmpMyself == null || bmpMyHighlight == null)
				setImage();

			Bitmap bmpTemp = new Bitmap(picBox.Image);
			using (Graphics g = Graphics.FromImage(bmpTemp))
				g.DrawImage(bmpMyHighlight, pt);

			picBox.Image = bmpTemp;
		}

		public void erase()
		{
			Bitmap bmpTemp = new Bitmap(picBox.Image);
			using (Graphics g = Graphics.FromImage(bmpTemp))
				g.FillRectangle(brWhite, new Rectangle(pt, sz));

			picBox.Image = bmpTemp;
		}
	}

	public class classNote
	{
		public enuNote eNote;
		enuSuspects eSuspect;
		enuCards eCard;
		formClue_2022 mainForm;
		PictureBox picBox;
		public enuMode eMode;
		public Point pt;
		Bitmap bmpMyself, bmpMyHighlight;
		
		static Bitmap[] bmpSuspects;
		static Bitmap[] bmpNotes;
		static Bitmap bmpHighlight;

		public bool bolUpdateImage = true;

		public classNote(formClue_2022 MainForm, ref PictureBox picField, enuMode Mode, enuSuspects Suspect, enuCards Card)
		{
			mainForm = MainForm;
			picBox = picField;
			eMode = Mode;
			eSuspect = Suspect;
			eCard = Card;

			if (bmpSuspects == null)
				initImages();

			placeButton();
		}

		void initImages()
		{
			bmpSuspects = new Bitmap[(int)enuSuspects._numSuspects];
			bmpSuspects[(int)enuSuspects.ColMustard] = new Bitmap(Resources.noteBox_ColMustard); bmpSuspects[(int)enuSuspects.ColMustard].MakeTransparent();
			bmpSuspects[(int)enuSuspects.MissScarlet] = new Bitmap(Resources.noteBox_MissScarlet); bmpSuspects[(int)enuSuspects.MissScarlet].MakeTransparent();
			bmpSuspects[(int)enuSuspects.MrsPeacock] = new Bitmap(Resources.noteBox_MrsPeacock); bmpSuspects[(int)enuSuspects.MrsPeacock].MakeTransparent();
			bmpSuspects[(int)enuSuspects.MrsWhite] = new Bitmap(Resources.noteBox_MrsWhite); bmpSuspects[(int)enuSuspects.MrsWhite].MakeTransparent();
			bmpSuspects[(int)enuSuspects.ProfPlum] = new Bitmap(Resources.noteBox_ProfPlum); bmpSuspects[(int)enuSuspects.ProfPlum].MakeTransparent();
			bmpSuspects[(int)enuSuspects.RevGreen] = new Bitmap(Resources.noteBox_RevGreen); bmpSuspects[(int)enuSuspects.RevGreen].MakeTransparent();

			bmpNotes = new Bitmap[(int)enuNote._numNotes];
			bmpNotes[(int)enuNote.blank] = new Bitmap(Resources.noteBox_blank); bmpNotes[(int)enuNote.blank].MakeTransparent();
			bmpNotes[(int)enuNote.check] = new Bitmap(Resources.noteBox_check); bmpNotes[(int)enuNote.check].MakeTransparent();
			bmpNotes[(int)enuNote.question] = new Bitmap(Resources.noteBox_questionMark); bmpNotes[(int)enuNote.question].MakeTransparent();
			bmpNotes[(int)enuNote.X] = new Bitmap(Resources.noteBox_X); bmpNotes[(int)enuNote.X].MakeTransparent();

			bmpHighlight = new Bitmap(Resources.noteBox_highlight); bmpHighlight.MakeTransparent();
		}

		void placeButton()
		{
			int intY = 0;
			switch (eCard)
			{
				case enuCards.ColMustard:
					intY = 39;
					break;

				case enuCards.ProfPlum:
					intY = 65;
					break;

				case enuCards.RevGreen:
					intY = 91;
					break;

				case enuCards.MrsPeacock:
					intY = 119;
					break;

				case enuCards.MissScarlet:
					intY = 145;
					break;

				case enuCards.MrsWhite:
					intY = 171;
					break;

				case enuCards.Knife:
					intY = 221;
					break;

				case enuCards.Candlestick:
					intY = 247;
					break;

				case enuCards.Revolver:
					intY = 273;
					break;

				case enuCards.Rope:
					intY = 301;
					break;

				case enuCards.LeadPipe:
					intY = 327;
					break;

				case enuCards.Wrench:
					intY = 353;
					break;

				case enuCards.Hall:
					intY = 403;
					break;

				case enuCards.Lounge:
					intY = 429;
					break;

				case enuCards.DiningRoom:
					intY = 455;
					break;

				case enuCards.Kitchen:
					intY = 483;
					break;

				case enuCards.BallRoom:
					intY = 509;
					break;

				case enuCards.Conservatory:
					intY = 535;
					break;

				case enuCards.BilliardRoom:
					intY = 563;
					break;

				case enuCards.Library:
					intY = 589;
					break;

				case enuCards.Study:
					intY = 615;
					break;
			}

			int intX = 240 + (int)eSuspect * 25;

			pt = new Point(intX, intY);
			setMyImages();
		}

		public enuSuspects Suspect
		{
			get { return eSuspect; }
		}

		public enuCards Card
		{
			get { return eCard; }
		}

		public enuNote Note
		{
			get { return eNote; }
			set
			{
				if (eNote != value)
				{
					eNote = value;
					//setMyImages();
					//draw();
					bolUpdateImage = true;
				}
			}
		}

		public void draw()
		{
			if (mainForm.eMode != eMode && eMode != enuMode.any)
				return;
			if (bmpMyself == null || bmpMyHighlight == null || bolUpdateImage)
				setMyImages();
			
			Bitmap bmpTemp = new Bitmap(picBox.Image);
			using (Graphics g = Graphics.FromImage(bmpTemp))
				g.DrawImage(bmpMyself, pt);

			picBox.Image = bmpTemp; picBox.Refresh();
		}

		public void highlight()
		{
			if (mainForm.eMode != eMode && eMode != enuMode.any)
				return;

			if (bmpMyself == null || bmpMyHighlight == null || bolUpdateImage)
				setMyImages();

			Bitmap bmpTemp = new Bitmap(picBox.Image);
			using (Graphics g = Graphics.FromImage(bmpTemp))
				g.DrawImage(bmpMyHighlight, pt);

			picBox.Image = bmpTemp;
		}

		public void setMyImages()
		{
			bolUpdateImage = false;
			bmpMyself = new Bitmap(25, 25);
			using (Graphics g = Graphics.FromImage(bmpMyself))
			{
				Rectangle recSrc = new Rectangle(pt.X, pt.Y, 25, 25);
				Rectangle recDest = new Rectangle(0, 0, 25, 25);
				g.DrawImage(mainForm.bmpNotebook, recDest, recSrc, GraphicsUnit.Pixel);
				g.DrawImage(bmpSuspects[(int)eSuspect], new Point(0, 0));
				g.DrawImage(bmpNotes[(int)eNote], new Point(0, 0));
			}

			bmpMyHighlight = new Bitmap(bmpMyself);
			using (Graphics g = Graphics.FromImage(bmpMyHighlight))
				g.DrawImage(bmpHighlight, new Point(0, 0));
		}
	}

	public class classRotatedImage
	{
		Bitmap[] bmp = new Bitmap[16];

		public void loadBaseImages(string strFilename)
		{
			if (System.IO.File.Exists(strFilename))
			{
				FileStream fs = new FileStream(strFilename, FileMode.Open);

				BinaryFormatter formatter = new BinaryFormatter();

				for (int intBaseImageCounter = 0; intBaseImageCounter < 4; intBaseImageCounter++)
				{
					bmp[intBaseImageCounter] = (Bitmap)formatter.Deserialize(fs);
				}

				fs.Close();
			}
		}

		public void saveBaseImages(string strFilename)
		{
			if (System.IO.File.Exists(strFilename))
				System.IO.File.Delete(strFilename);

			FileStream fs = new FileStream(strFilename, FileMode.Create);

			BinaryFormatter formatter = new BinaryFormatter();

			for (int intBaseImageCounter = 0; intBaseImageCounter < 4; intBaseImageCounter++)
			{
				if (bmp[intBaseImageCounter] == null)
					bmp[intBaseImageCounter] = getImage(intBaseImageCounter);
				formatter.Serialize(fs, bmp[intBaseImageCounter]);
			}

			fs.Close();
		}

		public enum enuFlipRotateType { rotate270, rotate180, rotate90};
		public Bitmap getImage(enuFlipRotateType eFlipRotate) { return getImage((int)eFlipRotate); }
		public Bitmap getImage(int intIndex)
		{
			if (bmp[0] == null)
				return null;

			if (bmp[intIndex] != null)
				return bmp[intIndex];

			if (intIndex < 4)
			{
				bmp[intIndex] = rotate(bmp[0], Math.PI / 8.0 * (double)intIndex);
			}
			else
			{
				int intBaseIndex = intIndex % 4;
				bmp[intIndex] = new Bitmap(getImage(intBaseIndex));
				int intQuarterRotations = (int)Math.Floor((double)intIndex / 4.0);

				switch (intQuarterRotations)
				{
					case 1:
						bmp[intIndex].RotateFlip(RotateFlipType.Rotate270FlipNone);
						break;

					case 2:
						bmp[intIndex].RotateFlip(RotateFlipType.Rotate180FlipNone);
						break;

					case 3:
						bmp[intIndex].RotateFlip(RotateFlipType.Rotate90FlipNone);
						break;

				}
			}
			bmp[intIndex].MakeTransparent();
			return bmp[intIndex];
		}

		public void createBaseImage(Bitmap bmpBaseImage)
		{
			bmp[0] = bmpBaseImage;
			using (Graphics g = Graphics.FromImage(bmp[0]))
				g.DrawRectangle(new Pen(Color.White, 2), new Rectangle(0, 0, bmp[0].Width - 1, bmp[0].Height - 1));

			bmp[0].MakeTransparent();
		}

		public void createBaseImage(string strFilename)
		{
			if (System.IO.File.Exists(strFilename))
			{
				bmp[0] = new Bitmap(strFilename);
				using (Graphics g = Graphics.FromImage(bmp[0]))
					g.DrawRectangle(new Pen(Color.White, 2), new Rectangle(0, 0, bmp[0].Width - 1, bmp[0].Height - 1));

				bmp[0].MakeTransparent();
			}
		}

		public struct udtPixilateColorFind
		{
			public Color clr;
			public int numFound;
		}

		private void addPixilateColorFound(ref udtPixilateColorFind[] udrPixilateColorFind, Color clrFound)
		{
			if (udrPixilateColorFind == null)
			{
				udrPixilateColorFind = new udtPixilateColorFind[1];
				udrPixilateColorFind[0] = new udtPixilateColorFind();
				udrPixilateColorFind[0].clr = clrFound;
				udrPixilateColorFind[0].numFound = 1;
			}
			else
			{
				for (int intClrCounter = 0; intClrCounter < udrPixilateColorFind.Length; intClrCounter++)
					if (udrPixilateColorFind[intClrCounter].clr == clrFound)
					{
						udrPixilateColorFind[intClrCounter].numFound++;
						return;
					}
				Array.Resize<udtPixilateColorFind>(ref udrPixilateColorFind, udrPixilateColorFind.Length + 1);
				udrPixilateColorFind[udrPixilateColorFind.Length - 1] = new udtPixilateColorFind();
				udrPixilateColorFind[udrPixilateColorFind.Length - 1].clr = clrFound;
				udrPixilateColorFind[udrPixilateColorFind.Length - 1].numFound = 1;
			}
		}
		void reorderPixilateColorFound(ref udtPixilateColorFind[] udrPixilateColorFind)
		{
			int intBestFind;
			for (int intOuterLoop = 0; intOuterLoop < udrPixilateColorFind.Length - 1; intOuterLoop++)
			{
				intBestFind = intOuterLoop;
				for (int intInnerLoop = intOuterLoop + 1; intInnerLoop < udrPixilateColorFind.Length; intInnerLoop++)
				{
					if (udrPixilateColorFind[intInnerLoop].numFound > udrPixilateColorFind[intBestFind].numFound)
						intBestFind = intInnerLoop;
				}
				if (intBestFind != intOuterLoop)
				{
					udtPixilateColorFind udrTemp = udrPixilateColorFind[intOuterLoop];
					udrPixilateColorFind[intOuterLoop] = udrPixilateColorFind[intBestFind];
					udrPixilateColorFind[intBestFind] = udrTemp;
				}
			}
		}
		Bitmap rotate(Bitmap bmpInput, double dblAngleRotation)
		{
			int intMinSquare = bmpInput.Width > bmpInput.Height ?
								3 * bmpInput.Width
								: 3 * bmpInput.Height;
			Color clrHole = Color.YellowGreen;// some color assumed NOT in the input bmp

			Bitmap bmpCopy = new Bitmap(intMinSquare, intMinSquare);
			Point ptTL;
			Point ptBR;
			Point ptCopyCenter = new Point(bmpCopy.Width / 2, bmpCopy.Height / 2);
			Point ptOriginalCenter = new Point(bmpInput.Width / 2, bmpInput.Height / 2);
			using (Graphics g = Graphics.FromImage(bmpCopy))
			{
				g.FillRectangle(new SolidBrush(clrHole), new Rectangle(new Point(0, 0), bmpCopy.Size));
				ptTL = new Point(ptCopyCenter.X, ptCopyCenter.Y);
				ptBR = new Point(ptCopyCenter.X, ptCopyCenter.Y);

				for (int intX = 0; intX < bmpInput.Width; intX++)
				{
					for (int intY = 0; intY < bmpInput.Height; intY++)
					{
						int intDX = ptOriginalCenter.X - intX;
						int intDY = ptOriginalCenter.Y - intY;
						classMath.classRadialCoor udrOriginalRad = new classMath.classRadialCoor(classMath.arcTan(intDX, intDY), Math.Sqrt(intDX * intDX + intDY * intDY));
						classMath.classRadialCoor udrCopyRad = new classMath.classRadialCoor(udrOriginalRad.angle - dblAngleRotation, udrOriginalRad.radius);
						Point ptCopy = new Point((int)(ptCopyCenter.X + udrCopyRad.radius * Math.Cos(udrCopyRad.angle)),
												 (int)(ptCopyCenter.Y + udrCopyRad.radius * Math.Sin(udrCopyRad.angle)));

						try { bmpCopy.SetPixel(ptCopy.X, ptCopy.Y, bmpInput.GetPixel(intX, intY)); }
						catch (Exception) { }

						// keep track of limits of output image
						if (ptCopy.X < ptTL.X)
							ptTL.X = ptCopy.X;
						if (ptCopy.Y < ptTL.Y)
							ptTL.Y = ptCopy.Y;
						if (ptCopy.X > ptBR.X)
							ptBR.X = ptCopy.X;
						if (ptCopy.Y > ptBR.Y)
							ptBR.Y = ptCopy.Y;
					}
				}
			}

			// write image to output array
			Size szOfImage = new Size(ptBR.X - ptTL.X, ptBR.Y - ptTL.Y);
			Rectangle recSrc = new Rectangle(ptTL, szOfImage);
			Rectangle recDest = new Rectangle(new Point(0, 0), szOfImage);

			// fill the blanks missed when rotating image
			// scanning x from 0 to width created a problem in the fill-blank
			for (int intX = ptTL.X; intX < ptBR.X; intX++)
				for (int intY = ptTL.Y; intY < ptBR.Y; intY++)
				{
					Color clrTest = bmpCopy.GetPixel(intX, intY);
					if (clrTest.A == clrHole.A
						&& clrTest.R == clrHole.R
						&& clrTest.G == clrHole.G
						&& clrTest.B == clrHole.B)
					{
						udtPixilateColorFind[] udrColorFind = new udtPixilateColorFind[0];
						if (intX > 0 && intX < bmpCopy.Width - 2 && intY > 0 && intY < bmpCopy.Height - 2)
						{
							Point ptUp = new Point(intX, intY - 1);
							Point ptDown = new Point(intX, intY + 1);
							Point ptLeft = new Point(intX - 1, intY);
							Point ptRight = new Point(intX + 1, intY);
							Point ptUL = new Point(intX - 1, intY - 1);
							Point ptUR = new Point(intX + 1, intY - 1);
							Point ptDR = new Point(intX + 1, intY + 1);
							Point ptDL = new Point(intX - 1, intY + 1);

							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptUp.X, ptUp.Y));
							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptDown.X, ptDown.Y));
							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptLeft.X, ptLeft.Y));
							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptRight.X, ptRight.Y));
							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptDL.X, ptDL.Y));
							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptDR.X, ptDR.Y));
							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptUL.X, ptUL.Y));
							addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptUR.X, ptUR.Y));
							reorderPixilateColorFound(ref udrColorFind);
							if (udrColorFind[0].numFound >= 2)
								try { bmpCopy.SetPixel(intX, intY, udrColorFind[0].clr); }
								catch (Exception) { }
							else
							{
								int intDX = ptCopyCenter.X - intX;
								int intDY = ptCopyCenter.Y - intY;
								classMath.classRadialCoor udrOriginalRad = new classMath.classRadialCoor(classMath.arcTan(intDX, intDY), Math.Sqrt(intDX * intDX + intDY * intDY));
								classMath.classRadialCoor udrCopyRad = new classMath.classRadialCoor(udrOriginalRad.angle + dblAngleRotation, udrOriginalRad.radius);
								Point ptCopy = new Point((int)(ptOriginalCenter.X + udrCopyRad.radius * Math.Cos(udrCopyRad.angle)),
														 (int)(ptOriginalCenter.Y + udrCopyRad.radius * Math.Sin(udrCopyRad.angle)));

								if (ptCopy.X >= 0 && ptCopy.X < bmpCopy.Width && ptCopy.Y >= 0 && ptCopy.Y < bmpCopy.Height)
									try { bmpCopy.SetPixel(intX, intY, bmpInput.GetPixel(ptCopy.X, ptCopy.Y)); }
									catch (Exception) { }
							}
						}
					}
				}
			if (recDest.Width < 1)
				recDest.Width = 1;
			if (recDest.Height < 1)
				recDest.Height = 1;
			Bitmap bmpTemp = new Bitmap(recDest.Width, recDest.Height);

			using (Graphics g = Graphics.FromImage(bmpTemp))
			{
				g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, bmpTemp.Width, bmpTemp.Height));
				bmpCopy.MakeTransparent(bmpCopy.GetPixel(0, 0));
				g.DrawImage(bmpCopy, recDest, recSrc, GraphicsUnit.Pixel);
			}
			bmpTemp.RotateFlip(RotateFlipType.Rotate180FlipNone);
			return bmpTemp;
		}

	}

	public class buttonColoredEnabled : System.Windows.Forms.Button
	{
		public buttonColoredEnabled()
		{
            EnabledChanged += ButtonColoredEnabled_EnabledChanged;
		}

		public Color clrForeground_Enabled = Color.Black;
		public Color clrForeground_Disabled = Color.Gray;
		public Color clrBackground_Enabled = Color.Yellow;
		public Color clrBackground_Disabled = Color.LightGray;

        private void ButtonColoredEnabled_EnabledChanged(object sender, EventArgs e)
        {
            if (Enabled)
			{
				ForeColor = clrForeground_Enabled;
				BackColor = clrBackground_Enabled;
			}
			else
			{
				ForeColor = clrForeground_Disabled;
				BackColor = clrBackground_Disabled;
			}
        }
    }


    #region "enumerated types"

    public enum enuAccuseAnimationMode
    {
        endAccusation,
        drawAccusation,
        prepareToShowCards,
        showCards,
        hideCards,
        retractCards,
        withdrawAccusingSuspect,
        showNewspaper
    }
    enum enuBettyBoop_Animations
    {
        Boxing_Left,
        Boxing_Right,
        Cross_Left,
        Cross_Right,
        FrontStep_Left,
        FrontStep_Right,
        Jab_Left,
        Jab_Right,
        Kick_Axe_Left,
        Kick_Axe_Right,
        kick_backFoot_Left,
        kick_backFoot_Right,
        Stand_Left,
        Stand_Right,
        Walk_Left,
        Walk_Right,
        _numAnimations
    };

    enum enuBettyBoop_Limbs
    {
        MasterLimb,         //0
        Crane,          //1
        Crane_Axis,         //2
        Torso_bottom,           //3
        Thigh_Left,         //4
        Shin_Left,          //5
        Foot_Left,          //6
        Thigh_Right,            //7
        Shin_Right,         //8
        Foot_Right,         //9
        Torso_Top,          //10
        Arm_Left,           //11
        Forearm_Left,           //12
        Hand_Left,          //13
        Arm_Right,          //14
        Forearm_Right,          //15
        Hand_Right,         //16
        Head,           //17
        Skirt_Front,            //18
        SkirtFront_Extra,           //19
        _numBettyBoopLimbs
    };
    enum enuwaldo_Animations
    {
        wave,
        wriggle_dance,
        _numAnimations
    };
    enum enuwaldo_Limbs
    {
        MasterLimb,         //0
        masterlimb,         //1
        torso,          //2
        head,           //3
        arm_left,           //4
        forearm_left,           //5
        hand_left,          //6
        arm_right,          //7
        forearm_right,          //8
        hand_right,         //9
        hips,           //10
        leg_left,           //11
        shin_left,          //12
        foot_left,          //13
        Leg_right,          //14
        shin_right,         //15
        foot_right,         //16
        _numwaldoLimbs
    };
    public enum enuAILevel { stupid, dull, average, bright, genius, _numAILevels };
    public enum enuButtons { MakeSuggestion_Cancel, MakeSuggestion_Ok, RespondToSuggestion_Ok, MouseOver, _numButtons };
    public enum enuCards
    {
        MissScarlet = 0, ColMustard, MrsWhite, RevGreen, MrsPeacock, ProfPlum,
        Knife, Candlestick, Revolver, Rope, LeadPipe, Wrench,
        Study, Hall, Lounge, DiningRoom, Kitchen, BallRoom, Conservatory, BilliardRoom, Library,
        _numCards, Unknown, NoCardShown
    };
    public enum enuCardType { weapon = 0, room, Suspect, _numCardTypes };
    public enum enuDealCardsMode
    {
        getReady,
        SortCardsIntotypes,
        gatherTypes,

        spreadWeaponCardsFaceUp,
        flipWeaponcards,
        shuffleWeaponCards,
        gatherFaceDownWeapons,
        spreadWeapondsCardsFaceDown,
        selectWeapon,
        gatherFaceDownWeapons_LessMurderWeapon,

        spreadSuspectCardsFaceUp,
        flipSuspectcards,
        shuffleSuspectCards,
        gatherFaceDownSuspects,
        spreadSuspectdsCardsFaceDown,
        selectSuspect,
        gatherFaceDownSuspects_LessMurderSuspect,

        spreadRoomCardsFaceUp,
        flipRoomcards,
        shuffleRoomCards,
        gatherFaceDownRooms,
        spreadRoomdsCardsFaceDown,
        selectRoom,
        gatherFaceDownRooms_LessMurderRoom,

        shuffleCards,
        joinCardsAfterShuffle,
        dealToPlayers,
        moveMurderCardsToCenter,
        endDealCardsAnimation
    };
    public enum enuDir { north = 0, east, south, west, secretPassage };
    public enum enuFloor { tile = 0, room, door, invalid };

    public enum enuIntroAnimationMode
    {
        moveToBawdyMansion,
        moveToRat,
        moveToTheButlerDidIt,
        moveToCKLovesTalise,
        moveToSpider,
        moveToCheese,
        moveToCat,
        moveToWaldo,
        moveToBettyBoop,
        moveToWrittenBy,
        moveToChristKennedy,
        moveToYear,
        moveToEnd,
        _numIntroMode
    };

    public enum enuIntroAnimationSprites
    {
        waldo,
        BettyBoop,
        _NumIntroAnimationSprites
    };

    public enum enuMode
    {
        idle,
        dealCards,
        Accuse,
        Accuse_Animation,
        chooseCharacter,
        warnPlayerNextTurn,
        beginTurn,
        gameOver,
        rollDie_begin,
        rollDie_animate,
        rollDie_end,
        showAllowableMoves,
        animateMove,
        Suggest,
        AISuggestionComplete,
        animateIntroduction,
        animateSummonSuspect,
        animateSummonWeapon,
        animateSecretPassage,
        respondToSuggestion,
        playerChoosesCardToShow,
        playerTurnIdle,
        endTurn,
        any
    };
    public enum enuNote { blank, X, check, question, _numNotes, shown };
    public enum enuRooms { Study, Hall, Lounge, DiningRoom, Kitchen, BallRoom, Conservatory, BilliardRoom, Library, _numRooms, start, tiles };
    public enum enuSuspects { MissScarlet = 0, ColMustard, MrsWhite, RevGreen, MrsPeacock, ProfPlum, _numSuspects };
    public enum enuWeapons { Knife = 0, Candlestick, Revolver, Rope, LeadPipe, Wrench, _numWeapons };

    #endregion

    #region "structures"
    public class classMurder
    {
        public enuSuspects eSuspect = (enuSuspects)0;
        public enuRooms eRoom = (enuRooms)0;
        public enuWeapons eWeapon = (enuWeapons)0;
    }

    public class classAnimationSummons
    {
        public Point ptStart = new Point();
        public Point ptEnd = new Point();
        public Point ptMidway = new Point();
        public int intStepCounter;
        public int intMaxSteps;
        public double dblAngleBetweenPoints;
        public double dblDistanceBetweenPoints;

        public bool bolMoveToCenterOfScreen;
    }

    public class classAnimationSecretPassge
    {
        public Point ptStart = new Point();
        public Point ptEnd = new Point();
        public Point ptMidway = new Point();
        public int intStepCounter;
        public int intMaxSteps;
        public double dblAngleBetweenPoints;
        public double dblDistanceBetweenPoints;

        public bool bolMoveToCenterOfScreen;
        public enuRooms eRoom_Start = (enuRooms)0;
        public enuRooms eRoom_End= (enuRooms)0;
    }

    public class classSuggestionAnimation
    {
        public int intProveSuggestionCycleCounter;
    }

    public class classAnimationInfo
    {
        public Point ptStart = new Point();
        public Point ptEnd=new Point();
        public Point ptPos= new Point();
        public int intStep;
        public int intMaxSteps;

        public double dblTravelAngle;
        public double dblTravelDistance;
        public double dblTravelInitialVelocity;
        public double dblTravelAcceleration;
        public Point velTravel = new Point();

        public double dblAngleFacing;
        public double dblAngleTurning;
        public double dblAngleTurningAttenuation;

        public double dblSizeFactor;

        public Bitmap bmpGray = null;
        public Bitmap bmp= null;
    }

    public class classAccusation_Animation
    {
        public classCard[] cAnimatedCards;
        public int intAnimationStep;
        public bool bolInit;
        public Bitmap bmpAccusationBoard = null;
        public Bitmap bmpShadedAccusationBoard= null;
        public Bitmap bmpAccusationForegroundGray= null;
        public Bitmap bmpAccusationForeground= null ;
        public enuAccuseAnimationMode _eMode = (enuAccuseAnimationMode)0;
        public classMurder  udrAccusation = new classMurder ();
        public List<classAnimationInfo> lstElements = new List<classAnimationInfo>();
        public List<classAnimationInfo> lstUdrFloodlights = new List<classAnimationInfo>();
		public classAccusation_Animation_RotatingNewspaper cNewspaper = new classAccusation_Animation_RotatingNewspaper();
        public enuMode eRestoreMode = (enuMode)0;
    }


    public class classIntro_Animation
    {
        public int intAnimationStep;
        public bool bolInit;
        public enuIntroAnimationMode eMode = enuIntroAnimationMode._numIntroMode;
        public classIntro_Animation_Board cBoardUnderLense = new classIntro_Animation_Board();
        public Bitmap bmpBoard = null;
        public classIntro_MagnifyingGlass cMagnifyingGlass = new classIntro_MagnifyingGlass();
		public List<classIntro_Animation_Sprites> lstSprites = new List<classIntro_Animation_Sprites>();
    }
    public class classIntro_Animation_Sprites
    {
        public classAnimationInfo udrAniInfo = new classAnimationInfo();
        public classSpriteData cSpriteData = new classSpriteData();
    }


    public class classIntro_Animation_Board
    {
        public classIntro_Animation_BoardParcel[,] cArrayParcels;
        public Size szArray = new Size();
        public Size szParcels = new Size();
    }

    public class classIntro_Animation_BoardParcel
    {
        public Bitmap bmp = null;
        public Rectangle rec = new Rectangle();
    }

    public class classIntro_MagnifyingGlass
    {
        public Point ptStart = new Point();
        public Point ptEnd = new Point();
        public Point ptPos= new Point();
        public int intStep;
        public int intMaxSteps;

        public int intHoverStep;
        public int intHoverMax;

        public double dblTravelAngle;
        public double dblTravelDistance;
        public Point velTravel = new Point();

        public double dblSizeFactor;
        public double dblSizeFactor_Start;
        public double dblSizeFactor_End;

        public Bitmap bmpLense = null;
        public Bitmap bmpHandle = null;
        public Color clrBackground;
        public Color clrLense;
        public Point ptCenterLense = new Point();
    }

    public class classAccusation_Animation_RotatingNewspaper
    {
        public classRotatedImage cBmp = new classRotatedImage();
        public int intImage;
        public Point ptPos = new Point();
        public double dblSizeFactor;
    }

    public class classMoveAnimationInfo
    {
        public string strPath;
        public int intAnimationStep;

        public Bitmap bmpAnimationBoard = null;
        public Point ptMouseTile = new Point();
        public Point ptAnimationMove = new Point();
		public Point ptImage = new Point();
        public Rectangle recPiece = new Rectangle();

		public classSuspect cSus = null;
    }

    public class classRollDieInfo
    {
        public int intDieValue;
        public int intDieWidth;
        public int intMaxVel;
        public int intVelFactor;
        public int intImageIndex;
        public Bitmap bmpCurrent = null;
        public double dblVelocityAttenuationFactor;
        public int intRightMost;
        public int intLowerMost;
        public double dblVel;
        public double dblAngle;
        public double dblXVel;
        public double dblYVel;
        public int intRollCount;
        public int intRollAnimation;
        public Point ptDie = new Point();
    }

    /// <summary>
    /// used to track sequence of suspects that follow me in order of play
    /// </summary> 
    public class classSuggestionAI_perSuspect
    {
        public enuSuspects eSuspect = enuSuspects._numSuspects;
        public List<classSuggestionAI_CardFrequency> lstUdrRoomsMystery = new List<classSuggestionAI_CardFrequency>();          // list of mystery Rooms which this suspect may have
        public List<classSuggestionAI_CardFrequency> lstUdrWeaponCardsMystery = new List<classSuggestionAI_CardFrequency>();        // list of mystery Weapons which this suspect may have
        public List<classSuggestionAI_CardFrequency> lstUdrSuspectCardsMystery = new List<classSuggestionAI_CardFrequency>();       // list of mystery Suspects which this suspect may have
    }

    /// <summary>
    /// number of suspects who may have any given card
    /// </summary>
    public class classSuggestionAI_CardFrequency
    {
        public enuCards eCards;
        public int intNumMystery;
    }

    /// <summary>
    /// information used to make a more informed suggestion
    /// </summary>
    public class classSuggestionAI
    {
        public List<classSuggestionAI_perSuspect> lstSuspectMysteryInfo = new List<classSuggestionAI_perSuspect>(); // sequence of suspects that follow me in order of play 
																												// suspect's name, list of rooms cards suspect may have, list of weapons cards (ibid), list of suspect cards (ibid)
        public List<classSuggestionAI_CardFrequency> lstUdrRoomCardsMysteryFrequency = new List<classSuggestionAI_CardFrequency>();     // array of room cards ordered in number of suspects which may have these cards
        public List<classSuggestionAI_CardFrequency> lstUdrWeaponMysteryFrequency= new List<classSuggestionAI_CardFrequency>();        //     same :   weapon cards  
        public List<classSuggestionAI_CardFrequency> lstUdrSuspectMysteryFrequency = new List<classSuggestionAI_CardFrequency>();       //		same : Suspect cards

    }

    public class classTypeOrder
    {
		public List<classCard> lstWeapons = new List<classCard>();
        public List<classCard> lstSuspects = new List<classCard>();
        public List<classCard> lstRooms = new List<classCard>();
    }

    public class classAnimateDealCards
    {
        public enuDealCardsMode _eMode;
        public List<classCard> lstCardsCurrentAnimation;
        public classTypeOrder udrTypeOrder;
        public int intAnimationCounter;
        public string strCards;
        public bool bolInit;
        public bool bolQuitAnimation;
        public classAnimateDealCards_Shuffle udrShuffle;
    }

    public class classAnimateDealCards_Shuffle
    {
        public Point ptCentralShufflePos = new Point();
        public int intMaxDistance;
        public int intTimeShuffled;
        public int intMaxShuffle;
    }

    #endregion

}