/*  main.c

  Chitris v1.0 - c0ding by cH!cu$ - e-mail: thechicus@gmail.com
  -------------------------------------------------------------

  Note di sviluppo
  ----------------
  Gli spazi vuoti hanno valore 0, quelli occupati  dal primo  giocatore hanno valore 1 e quelli
  occupati dal secondo giocatore hanno valore 2. Nella posizione 0 dell'array TrisTable vi è il
  PlayerID del vincitore, mentre le posizioni da 1 a 9 gestiscono la griglia del tris. 

  Questo programma è stato concepito per avere come interfaccia di input il tastierino numerico
  (a causa della sua somiglianza dei suoi suoi 9 tasti con il campo di tris), tuttavia sembra
  che su alcuni computer il tastierino numerico non funzioni nell'input in console. In tal caso
  bisogna utilizzare i tasti numerici da 1 a 9.
  
  (Compatibile con MSVC++ 6 e DJGPP)
  
  Licenza
  -------
  Potete  distribuire, copiare, modificare  o  usare il mio codice nei vostri programmi a patto 
  che io via dia il permesso. Per chiedermelo mandatemi un e-mail.
*/

/* HEADERS */
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>


/* Si definiscono  delle  costanti  che  indicano  in  modo  letterale una posizione nell'array 
   TrisTable(quello contenente le informazione sulla griglia del tris. */
#define UP_LEFT		*(TrisTable+1)
#define UP			*(TrisTable+2)
#define UP_RIGHT	*(TrisTable+3)
#define LEFT		*(TrisTable+4)
#define CENTER		*(TrisTable+5)
#define RIGHT		*(TrisTable+6)
#define DOWN_LEFT	*(TrisTable+7)
#define DOWN		*(TrisTable+8)
#define DOWN_RIGHT	*(TrisTable+9)


/* PROTOTIPI */
int IsPosFree(int nPos);
int HowManyPlayers(void);
void EnterPos(int PlayerID);
int IsTris(int PlayerID);
void DelBackChars(int nCharsToDelete);
void Info(void);
void DrawTrisTable (int *TrisTableArray);
char GetPlayerChar(int PlayerID);
void EnterPosAI (int PlayerID);

/* VARIABILI */
int TrisTable[10];

/* MAIN */
int main(void) {
	int nPlayers, x, nMoves = 0, turn = 1;
	
	for(x = 0; x <= 9; x++)
		*(TrisTable+x) = 0;

	Info();

	printf("Quanti giocatori?\n\n"
			"\t1) Human vs CPU\n"
			"\t2) Human vs Human\n\n"
			"Cosa scegli? (1 o 2) "); nPlayers = HowManyPlayers();

	do {
		system("cls");

		Info();

		DrawTrisTable(TrisTable);

		if (IsTris(1)) {
			printf("\n\nGiocatore 1 ha vinto!\n");
			getch();
			nMoves = 0;
			turn = 1;
			for(x = 0; x <= 9; x++)
				*(TrisTable+x) = 0;
			break;
		}

		if (IsTris(2)) {
			printf("\n\nGiocatore 2 ha vinto!\n");
			getch();
			nMoves = 0;
			turn = 1;
			for(x = 0; x <= 9; x++)
				*(TrisTable+x) = 0;
			break;
		}

		/* Nessun evento di tris dopo 9 mosse? parità */
		if (nMoves == 9) {
			printf("\n\nParit\x85.\n");
			getch();
			nMoves = 0;
			turn = 1;
			for(x = 0; x <= 9; x++)
				*(TrisTable+x) = 0;
			break;
		}

		printf("?");

		if (nPlayers == 1) {
			/* Human vs CPU */
			if (turn == 1) {
				EnterPos(1);
				nMoves++;
				turn = 2;
			} else {
				EnterPosAI(2);
				nMoves++;
				turn = 1;
			}
		} else if (nPlayers == 2) {
			/* Human vs Human */
			if (turn == 1) {
				EnterPos(1);
				nMoves++;
				turn = 2;
			} else {
				EnterPos(2);
				nMoves++;
				turn = 1;
			}
		}
	} while(1);
	return 0;
}

int IsPosFree(int nPos) {
	switch(nPos) {
		case 1: if (DOWN_LEFT == 0) return 1; else break;
		case 2: if (DOWN == 0) return 1; else break;
		case 3: if (DOWN_RIGHT == 0) return 1; else break;
		case 4: if (LEFT == 0) return 1; else break;
		case 5: if (CENTER == 0) return 1; else break;
		case 6: if (RIGHT == 0) return 1; else break;
		case 7: if (UP_LEFT == 0) return 1; else break;
		case 8: if (UP == 0) return 1; else break;
		case 9: if (UP_RIGHT == 0) return 1; else break;
	}
	return 0;
}

int IsTris(int PlayerID) {
	if(UP_LEFT == PlayerID) {
		if(UP == PlayerID && UP_RIGHT == PlayerID ||
		   LEFT == PlayerID && DOWN_LEFT == PlayerID ||
		   CENTER == PlayerID && DOWN_RIGHT == PlayerID) return 1;
	}
	
	if(UP == PlayerID) {
		if(CENTER == PlayerID && DOWN == PlayerID) return 1;
	}
	
	if(LEFT == PlayerID) {
		if(CENTER == PlayerID && RIGHT == PlayerID) return 1;
	}
	
	if(DOWN_LEFT == PlayerID) {
		if(DOWN == PlayerID && DOWN_RIGHT == PlayerID) return 1;
	}
	
	if(UP_RIGHT == PlayerID) {
		if(CENTER == PlayerID && DOWN_LEFT == PlayerID || 
		   RIGHT == PlayerID && DOWN_RIGHT == PlayerID) return 1;
	}	
	return 0;
}

int HowManyPlayers(void) {
	char cChar;
	int nPlayers = 0;

	int i = 0;

	do {
		do {
			cChar = getch();
			if (i < 0) i = 0;
			if (i > 1) i = 1;
			
			if (cChar == '\b') {
				if (i > 0) DelBackChars(1);
				i--;
			
			} else if (cChar >= '1' && cChar <= '2') {
				
				if (i < 1) {
					nPlayers = cChar - '0';
					putch(cChar);
					i++;
				}
			}
		} while (i == 0);
	} while (cChar != '\r');

	return nPlayers;
}

void EnterPos(int PlayerID) {
	char cChar;
	int nPos = 0;
	int i = 0;

		do {
			cChar = getch();
			if (i < 0) i = 0;
			if (i > 1) i = 1;
			
			if (cChar == '\b') {
				if (i > 0) DelBackChars(1);
				i--;
			
			} else if (cChar >= '1' && cChar <= '9') {
				
				if (i < 1) {
					nPos = cChar - '0';
					if (IsPosFree(nPos)) {
						switch(nPos) {
							case 1:	DOWN_LEFT = PlayerID; break;
							case 2: DOWN = PlayerID; break;
							case 3: DOWN_RIGHT = PlayerID; break;
							case 4: LEFT = PlayerID; break;
							case 5: CENTER = PlayerID; break;
							case 6: RIGHT = PlayerID; break;
							case 7: UP_LEFT = PlayerID; break;
							case 8: UP = PlayerID; break;
							case 9: UP_RIGHT = PlayerID; break;
						}
						i++;
					}
				}
			}
		} while (i == 0);
}

void DelBackChars(int nCharsToDelete) {
	int n;

	for (n = 0; n < nCharsToDelete; n++)
		putch('\b');
	
	for (n = 0; n < nCharsToDelete; n++)
		putch(' ');

	for (n = 0; n < nCharsToDelete; n++)
		putch('\b');
}

void DrawTrisTable (int *TrisTableArray) {
	printf( "\n\n%c | %c | %c\n"
			"---------\n"
			"%c | %c | %c\n"
			"---------\n"
			"%c | %c | %c\n\n",
			GetPlayerChar(*(TrisTableArray+1)), GetPlayerChar(*(TrisTableArray+2)), GetPlayerChar(*(TrisTableArray+3)),
			GetPlayerChar(*(TrisTableArray+4)), GetPlayerChar(*(TrisTableArray+5)), GetPlayerChar(*(TrisTableArray+6)),
			GetPlayerChar(*(TrisTableArray+7)), GetPlayerChar(*(TrisTableArray+8)), GetPlayerChar(*(TrisTableArray+9))
		);
}

void Info(void) {
	printf("#Chitris v1.0 - c0ded by cH!cu$ - thechicus@gmail\n"
		   "-------------------------------------------------\n"
		   "Per giocare usa il tastierino numerico. Se non funziona usa i tasti numeri da 1 a 9. \n\n");
}
char GetPlayerChar(int PlayerID) {
	if (PlayerID == 1) {
		return 'O';
	}
	
	if (PlayerID == 2) {
		return 'X';
	}
	return ' ';
}

void EnterPosAI (int PlayerID) {
	int enemy;
	
	if (PlayerID == 1) enemy = 2; else enemy = 1;

	/* 1) Attacco */
	if(UP_LEFT == PlayerID && UP == PlayerID && UP_RIGHT == 0) {
		UP_RIGHT = PlayerID;
	} else if(UP == PlayerID && UP_RIGHT == PlayerID && UP_LEFT == 0) {
		UP_LEFT = PlayerID;
	} else if(LEFT == PlayerID && CENTER == PlayerID && RIGHT == 0) {
		RIGHT = PlayerID;
	} else if(CENTER == PlayerID && RIGHT == PlayerID && LEFT == 0) {
		LEFT = PlayerID;
	} else if(DOWN_LEFT == PlayerID && DOWN == PlayerID && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(DOWN == PlayerID && DOWN_RIGHT == PlayerID && DOWN_LEFT == 0) {
		DOWN_LEFT = PlayerID;
	} else if(UP_LEFT == PlayerID && CENTER == PlayerID && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(CENTER == PlayerID && DOWN_RIGHT == PlayerID && UP_LEFT == 0) {
		UP_LEFT = PlayerID;
	} else if(UP_RIGHT == PlayerID && CENTER == PlayerID && DOWN_LEFT == 0) {
		DOWN_LEFT = PlayerID;
	} else if(DOWN_LEFT == PlayerID && CENTER == PlayerID && UP_RIGHT == 0) {
		UP_RIGHT = PlayerID;
	} else if(UP_LEFT == PlayerID && UP_RIGHT == PlayerID && UP == 0) {
		UP = PlayerID;
	} else if(LEFT == PlayerID && RIGHT == PlayerID && CENTER == 0) {
		CENTER = PlayerID;
	} else if(DOWN_LEFT == PlayerID && DOWN_RIGHT == PlayerID && DOWN == 0) {
		DOWN = PlayerID;
	} else if(UP_LEFT == PlayerID && DOWN_LEFT == PlayerID && LEFT == 0) {
		LEFT = PlayerID;
	} else if(UP == PlayerID && DOWN == PlayerID && CENTER == 0) {
		CENTER = PlayerID;
	} else if(UP_RIGHT == PlayerID && DOWN_RIGHT == PlayerID && RIGHT == 0) {
		RIGHT = PlayerID;
	} else if(UP_LEFT == PlayerID && CENTER == PlayerID && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(LEFT == PlayerID && DOWN_LEFT == PlayerID && UP_LEFT == 0) {
		UP_LEFT = PlayerID;
	} else if(CENTER == PlayerID && DOWN == PlayerID && UP == 0) {
		UP = PlayerID;
	} else if(RIGHT == PlayerID && DOWN_RIGHT == PlayerID && UP_RIGHT == 0) {
		UP_RIGHT = PlayerID;
	} else if(UP_LEFT == PlayerID && LEFT == PlayerID && DOWN_LEFT == 0) {
		DOWN_LEFT = PlayerID;
	} else if(UP == PlayerID && CENTER == PlayerID && DOWN == 0) {
		DOWN = PlayerID;
	} else if(UP_RIGHT == PlayerID && RIGHT == PlayerID && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(UP_LEFT == PlayerID && DOWN_RIGHT == PlayerID && CENTER == 0) {
		CENTER = PlayerID;
	} else if(UP_RIGHT == PlayerID && DOWN_LEFT == PlayerID && CENTER == 0) {
		CENTER = PlayerID;
	} else if(UP_RIGHT == PlayerID && DOWN_LEFT == PlayerID && LEFT == 0) {
		LEFT = PlayerID;
	
	/* 2) Difesa */
	} else if(UP_LEFT == enemy && UP == enemy && UP_RIGHT == 0) {
		UP_RIGHT = PlayerID;
	} else if(UP == enemy && UP_RIGHT == enemy && UP_LEFT == 0) {
		UP_LEFT = PlayerID;
	} else if(LEFT == enemy && CENTER == enemy && RIGHT == 0) {
		RIGHT = PlayerID;
	} else if(CENTER == enemy && RIGHT == enemy && LEFT == 0) {
		LEFT = PlayerID;
	} else if(DOWN_LEFT == enemy && DOWN == enemy && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(DOWN == enemy && DOWN_RIGHT == enemy && DOWN_LEFT == 0) {
		DOWN_LEFT = PlayerID;
	} else if(UP_LEFT == enemy && CENTER == enemy && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(CENTER == enemy && DOWN_RIGHT == enemy && UP_LEFT == 0) {
		UP_LEFT = PlayerID;
	} else if(UP_RIGHT == enemy && CENTER == enemy && DOWN_LEFT == 0) {
		DOWN_LEFT = PlayerID;
	} else if(DOWN_LEFT == PlayerID && CENTER == enemy && UP_RIGHT == 0) {
		UP_RIGHT = PlayerID;
	} else if(UP_LEFT == enemy && UP_RIGHT == enemy && UP == 0) {
		UP = PlayerID;
	} else if(LEFT == enemy && RIGHT == enemy && CENTER == 0) {
		CENTER = PlayerID;
	} else if(DOWN_LEFT == enemy && DOWN_RIGHT == enemy && DOWN == 0) {
		DOWN = PlayerID;
	} else if(UP_LEFT == enemy && DOWN_LEFT == enemy && LEFT == 0) {
		LEFT = PlayerID;
	} else if(UP == enemy && DOWN == enemy && CENTER == 0) {
		CENTER = PlayerID;
	} else if(UP_RIGHT == enemy && DOWN_RIGHT == enemy && RIGHT == 0) {
		RIGHT = PlayerID;
	} else if(UP_LEFT == enemy && CENTER == enemy && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(LEFT == enemy && DOWN_LEFT == enemy && UP_LEFT == 0) {
		UP_LEFT = PlayerID;
	} else if(CENTER == enemy && DOWN == enemy && UP == 0) {
		UP = PlayerID;
	} else if(RIGHT == enemy && DOWN_RIGHT == enemy && UP_RIGHT == 0) {
		UP_RIGHT = PlayerID;
	} else if(UP_LEFT == enemy && LEFT == enemy && DOWN_LEFT == 0) {
		DOWN_LEFT = PlayerID;
	} else if(UP == enemy && CENTER == enemy && DOWN == 0) {
		DOWN = PlayerID;
	} else if(UP_RIGHT == enemy && RIGHT == enemy && DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(UP_LEFT == enemy && DOWN_RIGHT == enemy && CENTER == 0) {
		CENTER = PlayerID;
	} else if(UP_RIGHT == enemy && DOWN_LEFT == enemy && CENTER == 0) {
		CENTER = PlayerID;
	} else if(UP_RIGHT == enemy && DOWN_LEFT == enemy && LEFT == 0) {
		LEFT = PlayerID;

	/* Prime mosse di partenza */
	} else if(CENTER == 0) {
		CENTER = PlayerID;
	} else if(UP_LEFT == 0){
		UP_LEFT = PlayerID;
	} else if(DOWN_RIGHT == 0) {
		DOWN_RIGHT = PlayerID;
	} else if(RIGHT == 0) {
		RIGHT = PlayerID;
	} else if(UP == 0) {
		UP = PlayerID;
	} else if(DOWN == 0) {
		DOWN = PlayerID;
	} else if(UP_RIGHT == 0) {
		UP_RIGHT = PlayerID;
	} else if(DOWN_LEFT == 0) {
		DOWN_LEFT = PlayerID;
	} else if(LEFT == 0) {
		LEFT = PlayerID;
	}
}
