;Tic - Tac - Toe : Human vs Human
;By Rohit Kumar

;0 represents empty state
;1 represents human player
;2 represents computer player

;list structure ([row 1 col1 state] 12 13 21 22 23 31 32 33)

(defun CheckWin(GameState Player)  ;GameState is a list of 9 elements
	(if	(and (eq (nth 0 GameState) Player) (eq (nth 1 GameState) Player) (eq (nth 2 GameState) Player)) ;first row
	    	(setq temp T)
		(if	(and (eq (nth 3 GameState) Player) (eq (nth 4 GameState) Player) (eq (nth 5 GameState) Player)) ;second row
			(setq temp T)
			(if	(and (eq (nth 6 GameState) Player) (eq (nth 7 GameState) Player) (eq (nth 8 GameState) Player)) ;third row
				(setq temp T)
				(if	(and (eq (nth 0 GameState) Player) (eq (nth 3 GameState) Player) (eq (nth 6 GameState) Player)) ;first column
					(setq temp T)
					(if (and (eq (nth 1 GameState) Player) (eq (nth 4 GameState) Player) (eq (nth 7 GameState) Player)) ;second column
						(setq temp T)
						(if (and (eq (nth 2 GameState) Player) (eq (nth 5 GameState) Player) (eq (nth 8 GameState) Player)) ;third column
							(setq temp T)
							(if (and (eq (nth 0 GameState) Player) (eq (nth 4 GameState) Player) (eq (nth 8 GameState) Player)) ;diagonal 1 \
								(setq temp T)
								(if (and (eq (nth 2 GameState) Player) (eq (nth 4 GameState) Player) (eq (nth 6 GameState) Player)) ;diagonal 2 /
									(setq temp T)
								)
							)
						)
					)
				)
			)
		)
	)
)

(defun DisplayBoard (state)
	(format T "~d ~d ~d" (nth 0 state) (nth 1 state) (nth 2 state))
	(fresh-line)
	(format T "~d ~d ~d" (nth 3 state) (nth 4 state) (nth 5 state))
	(fresh-line)
	(format T "~d ~d ~d" (nth 6 state) (nth 7 state) (nth 8 state))
	(fresh-line)
)

(defun BoardFilled (state)
	(let (position)
		(dolist (position state)
			(if (eq position 0)
				(return-from BoardFilled nil)
			)
		)
		(return-from BoardFilled t)
	)
)

(defun PlayTICTACTOE ()
	(setq currentstate '(0 0 0 0 0 0 0 0 0))
	(loop
		(DisplayBoard currentstate)	
		(loop
			(print "Human User 1 Turn. Enter your move (1-9): ")
			(setq humaninput (read))
			(if (eq (nth (- humaninput 1) currentstate) 0) (return nil))
		)
		(setf (nth (- humaninput 1) currentstate) 1)
		(if	(CheckWin currentstate 1)
			(let (temp1)
				(print "Human User 1 Wins")
				(return-from PlayTICTACTOE)
			)
		)
		(if (BoardFilled currentstate)
			(let ()
				(print "Game is a Draw")
				(return-from PlayTicTacToe -1)
			)
		)
		(DisplayBoard currentstate)
		(loop
			(print "Human User 2 Turn. Enter your move (1-9): ")
			(setq humaninput (read))
			(if (eq (nth (- humaninput 1) currentstate) 0) (return))
		)
		(setf (nth (- humaninput 1) currentstate) 2)
		(if	(CheckWin currentstate 2)
			(let (temp1)
				(print "Human User 2 Wins")
				(return-from PlayTICTACTOE)
			)
		)
		(if (BoardFilled currentstate)
			(let ()
				(print "Game is a Draw")
				(return-from PlayTicTacToe -1)
			)
		)
	)
)
