#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>

//Portadress, ändra om det inte fungerar... (0x378, 0x278 eller 0x3BC är standard.)
#define PORTBASE 0x3BC

//Portadresser, DON'T TOUCH! 
#define DATA PORTBASE + 0
#define STATUS PORTBASE + 1
#define CONTROL PORTBASE + 2

//Funktionsdeklarationer
int targetCtrl(int number, int timeLeft, int *numbHits);
short hit(int number);
int setTarget(int prevTarget);
int random();

int main(void)
{
	_outp(DATA, 1);					//Tänder röd lysdiod (inget spel igång)

	int numbHits; 					//Antalet träffar
	int target = random();			//Kallar på slumptalsgeneratorn (för att få ett värde att skicka till setTarget).
	int timePassed; 			    //Hur lång tid som gått
	int playTime; 					//Hur lång tid som får gå
	const int paus = 200;			//Så att man lätt kan kalibrera pausen mellan skjutningarna
	char choice;

	do {
		numbHits = 0;
		timePassed = 0;
		system("CLS");
		printf("How long do you wish to play (in seconds)? ");
		scanf("%d", &playTime);			//Bestämmer hur lång tid man ska spela
		playTime = playTime * 1000;		//Gör om det till millisekunder (lättare att räkna)
		_outp(DATA, 0);

		while(timePassed < playTime){	//Kontrollerar så att man inte spelar för länge
			target = setTarget(target);	//Ser till så att man inte hamnar på samma mål två gånger
			timePassed += targetCtrl(target, playTime - timePassed, &numbHits); 
										//Ultimata funktionen. Kollar allt, hjärtat!
			sleep(paus);				//Paus innan man får nästa target tilldelat 
			timePassed += paus;			//Ökar tiden som gått
		}
		_outp(DATA, 1);					//Tänder röd lysdiod (spelet är slut)
		printf("Hits: %d\n\n", numbHits);//Skriver ut hur många träffar du gjort
		
		printf("New game? (y/n)");
		choice = getch();
	} while (choice == 'y');
	printf("\n\n");
	system("PAUSE");
	return 0;
}

int targetCtrl(int number, int timeLeft, int *numbHits){
	short hitTrue = 0;  			//Istället för bool, kollar om man träffar
	int timeUsed = 0; 				//Hur lång tid som har gått

	int temp = pow(2, number+1); 	//Vilken diod som ska tändas

	_outp(DATA, _inp(DATA) | temp);
									//Tänder slumpat target
	int tries = 0;
	while((hitTrue != 1) && (timeLeft > 0) && (++tries <= 5)){
		_outp(DATA, _inp(DATA) & 253);//Släcker grön lampa
		hitTrue = hit(number);		//kollar om man träffat
		if (hitTrue == 1) {
			printf("Number of hits: %d\n", ++*numbHits);//Skriv ut aktuellt antal träffar.
		} else {
			sleep(500);				//Paus så att datorn reagerar om målet träffats
			timeUsed += 500;		//Ökar tiden som använts
			timeLeft -= 500;		//Minskar kvarvarande tid
		}
	}
	_outp(DATA, _inp(DATA) & (255-temp));//Släcker samma target	
	return timeUsed;				//returnernar tiden som använts
}

short hit(int number){				//Använder samma slumpat tal som föregående funktion
	short indata;
	short check = 0;				//Ersättning för bool
	indata = _inp(STATUS);			//Läser in aktiv data från targets
	if(number == 1){				//Target 1
		if((indata & 16) != 0)
			check = 1;
	}
	else if(number == 5){			//Target 5
		if((indata & 16) != 0)
			check = 1;
	}
	else if(number == 2){			//Target 2
		if((indata & 32) != 0)
			check = 1;
	}
	else if(number == 6){			//Target 6
		if((indata & 32) != 0)
			check = 1;
	}
	else if(number == 3){			//Target 3
		if((indata & 64) != 0)
			check = 1;
	}
	else if(number == 4){			//Target 4
		if((indata & 128) == 0) {	//Target 4 är inverterad, därav inverterad kod
			check = 1;
		}
	}
	else{							//Något har gått fel (jädra slumpgenerator...)
		printf("ERROR!");
	}
	if(check == 1){					//Kollar om man träffat
		printf("HIT! ");
		_outp(DATA, _inp(DATA) | 2);//Tänder grön lampa (Träff registrerad)
	}
	return(check);					//Returnerar 0 eller 1, d.v.s true eller false
}

int setTarget(int prevTarget){		//Kontrollerar så att man inte får samma mål 2 ggr
	int newTarget = random();		//Nya målet
	while(newTarget == prevTarget){	//Slumpar fram ett nytt tal så länge det är samma som innan
		newTarget = random();		//Slumpar fram ett tal
	}
	if(newTarget <= 4){				//Target 1-4
		_outp(CONTROL, 1);			//Ställer in switchen
	}
	else{							//Target 5-6
		_outp(CONTROL, 0);			//Ställer in switchen
	}
	printf("Active target: %d\n",newTarget);
	return newTarget;				//Returnerar värdet
}

//Slumptalsgenerator
int random()
{
	static int slumpx = 1;
	slumpx = (slumpx * 25173 + 13849) % 65536;	//"Magisk formel"
	int rand = 1+(slumpx + 32768)%6;			//Gör om till ett tal mellan 1 och 6
	return(rand);
}
