/*
Monty Hall by Dale Swanson October 10th, 2007
Simulates the monty hall problem
http://en.wikipedia.org/wiki/Monty_Hall_problem
*/

using namespace std;
#include <iostream>
#include <fstream>
#include <math.h>

char basen[100] = "V"; //needed for fnamecomb
char ext[10] = ".csv"; //needed for fnamecomb
char fname[100]; //needed for fnamecomb

bool doors[10]; //represents the doors 0 = nothing, 1 = prize
int doorcount; //for the index in the doors array
int prizedoor; //which door has the prize
int record[10]; //keep a record of  wins loses, 1 wins, 2 loses, 3 games played.
int playerdoor; //which door the player picks
int opendoor; //which door the host will open
bool strat; //strategy, if the player switches 1, or not 0
int newplayerdoor; //new door the player picks
int numrounds = 10000; //how many rounds to play
int game; // the current round
bool displaygame; //display each game results or not


int ran(int min, int max) //returns a random number between a min, and b max, careful with number > 32k
{// custom random number gen, for no reason
	int skip; //stores ammount of times we skip numbers
	int range; //the range from min to max
	int randresult = 0; //this is your real random number that will be used to return
	int temp; //used to switch min and max if they aren't in order
	
	if (max < min)
	{//if max is less than min we switch them
		temp = max; //put max in temp so we can over write max with min
		max = min;
		min = temp;
	}
	
	range = (max - min) + 1;
	if (rand() == 138) srand(rand() + clock()); 
	//1 in 32k odds to reseed the RNG uses both a rand number and the clock (clock isn't seconds, it's system ticks, faster than seconds) 
	if ((rand() + clock()) % 6 == 1) 
	//basicly 1 in 5 chance of looping a wasting some random numbers
	{
		for (skip = ((clock() % 4) + ((rand() + clock()) % 7) + (rand() % 18) + 9); skip > 0; skip--)//comes up with a number to loop from about 10 to 70 times
		{
			rand(); //wastes some random numbers
		}
	}
	randresult = min + int(range * rand() / (RAND_MAX + 1));
	//randresult = int((rand() % int(max - min + 1)) + min);
   return randresult;
}

void fnamecomb() //combines basen + the time + ext into fname
{//requires the global char's basen, ext, fname
	time_t tsec; //sets time to tsec
	time(&tsec);
	int tnum;
	char sttim[100];
	tnum = int(tsec);
	
	itoa(tnum, sttim, 10); //sets the string sttime to the value of the current time
	strcpy (fname, basen); //combines the 3
	strcat (fname, sttim);
	strcat (fname, ext);
	return;
}

void settings()
{//explains program and has user set inital varibles
	cout<<"\nThis will simulate the monty hall problem:\nhttp://en.wikipedia.org/wiki/Monty_Hall_problem";
	cout<<"\nThe monty hall problem works like this, you are on a game show, and must pick 1 door out of 3.";
	cout<<"\nOne of the doors has a prize, the other two don't.";
	cout<<"\nAfter you pick your door the host opens one of the other doors with no prize, the host always opens a prizeless door.";
	cout<<"\nAt this point you can either stick with your orginal guess, or change to the other unopened door.";
	cout<<"\nYou would think that the odds would be the same no matter what you did,\ns but actually you should always switch, as it raises your odds to 66%.";
	cout<<"\nThis is because the host must open a prizeless door, thus if you have picked one prizeless door (most likely you did), ";
	cout<<"\nthen he must elminate the only other prizeless door.";
	cout<<"\nSo, every time you pick a prizeless door at start (66% of the time), and you switch you must end up winning.";
	cout<<"\n\nEnter the number of games you want to simulate: ";
	cin>>numrounds; //get the number of rounds to simulate, 10,000 is normal
	cout<<"\nDo you want to display the results of each game - 1, or just the summery - 0? ";
	cin>>displaygame; //get summery view - 0, or each game - 1
}

void setup()
{//pick the door the prize will go behind
	for (doorcount = 1; doorcount < 10; doorcount++)
	{//clear all doors
		doors[doorcount] = 0;
	}
	prizedoor = ran(1, 3);//pick which door will have the prize
	doors[prizedoor] = 1; //put the prize behind that door
}

void pick()
{//player picks his door
	playerdoor = ran (1, 3); //player pics random door
	opendoor = ran (1, 3); //the door to open is picked randomly
	while (1 == 1)
	{//loop until the door to open is not the same as the players, and not the prize door
		if (opendoor != prizedoor && opendoor != playerdoor)
		{//check to see if the door to open is prizedoor or players door, if not then exit loop
			break; //if the door is good exit loop
		}
		else
		{//if it's a bad door repick it
			opendoor = ran (1, 3);
		}
	}
}

void open()
{//open one of the doors to player
	if (strat)
	{//if the strategy is 1 switch then switch doors
		newplayerdoor = ran (1, 3); //new player door
		while (1 == 1)
		{//loop until players new door is good
			if (newplayerdoor != opendoor && newplayerdoor != playerdoor)
			{
				break; //when players new door is good exit
			}
			else
			{
				newplayerdoor = ran (1, 3);
			}
		}
	}
	else
	{//if the players strategy is to stick with his door then just stick with it
		newplayerdoor = playerdoor;
	}
	
	if(displaygame) cout<<"\nPlayer - "<<playerdoor<<", opened - "<<opendoor<<", newplayer - "<<newplayerdoor<<", prize - "<<prizedoor;
	for (doorcount = 1; doorcount <= 3; doorcount++)
	{//display the door contents
		if(displaygame) cout<<", door "<<doorcount<<" - "<<doors[doorcount];
	}
	if (newplayerdoor == prizedoor)
	{//win
		record[1]++; //win count
	}
	else
	{//lose
		record[2]++; //loss count
	}
	record[3]++; //games count
}

void display()
{//show the summery
	cout<<"\nGames - "<<record[3]<<", Wins - "<<record[1]<<", Losses - "<<record[2];
	cout<<", strategy - ";
	if (strat) 
	{
		cout<<"Switch";
	}
	else
	{
		cout<<"Don't Switch";
	}
}

void clear()
{//clear out the doors and record arrays
	for (doorcount = 1; doorcount < 10; doorcount++)
	{//clear all doors
		doors[doorcount] = 0;
	}
	for (doorcount = 1; doorcount < 10; doorcount++)
	{//clear all doors
		record[doorcount] = 0;
	}
}

int main()
{
    time_t sseconds; //start seconds, will be used to seed the rng
	time_t cseconds; //current seconds
    time(&sseconds); //get our seed for rng
    srand((unsigned int) sseconds); //seed rng
	
	settings();
	
	strat = 0;
	for (game = 1; game <= numrounds; game++)
	{
		setup();
		pick();
		open();
	}
	display();
	
	clear();
	
	strat = 1;
	for (game = 1; game <= numrounds; game++)
	{
		setup();
		pick();
		open();
	}
	display();
	
	
	cout<<"\nDone...\n";
    system("PAUSE");
    return EXIT_SUCCESS;
}