Jack P. Oakley Portfolio Game Programmer/Designer

Connect Four

This Scheme program shows iteration, recursion, compound statements, variable and list manipulation.  It allows for the user to play against another player, vs a basic AI (that does more than just random moves),  control an AI vs AI match, or switch it up at any time.

#lang Scheme
; Connect Four by Jack P. Oakley
; This program defines an AI to play connect four
; This connect four can be played between two people, two AIs, or one of each

;******************************************************************************
; JPOGame global variable:                                                    *
; PURPOSE: Contain current status of the game board                           *
;******************************************************************************
(define JPOGame '( "X" (" " " " " " " " " " " " " ")
                       (" " " " " " " " " " " " " ")
                       (" " " " " " " " " " " " " ")
                       (" " " " " " " " " " " " " ")
                       (" " " " " " " " " " " " " ")
                       (" " " " " " " " " " " " " ")
                  )
)

;******************************************************************************
; JPOStartGame function:                                                      *
; PURPOSE: Initializes the game state                                         *
; IN: none                                                                    *
; OUT: returns true, displays text to show the game has been reset            *
;******************************************************************************
(define (JPOStartGame)
	(set! JPOGame '( "X" (" " " " " " " " " " " " " ")
                             (" " " " " " " " " " " " " ")
                             (" " " " " " " " " " " " " ")
                             (" " " " " " " " " " " " " ")
                             (" " " " " " " " " " " " " ")
                             (" " " " " " " " " " " " " ")
                       )
	)
	(display "New Game Begins, board reset ")
	#t
)

;******************************************************************************
; JPOMarkMove function:                                                       *
; PURPOSE: Allows the player to choose their move                             *
; IN: integer representing the column of a chosen move                        *
; OUT: returns the chosen column                                              *
;******************************************************************************
(define (JPOMarkMove Col)
	(if (equal?
			(JPOGetCell (cdr JPOGame) 1 Col)
			" "
		)
		(set! JPOGame
			(cons
				(if (equal?
						(car JPOGame)
						"X"
					)
					"O"
					"X"
				)
				(JPOSetCell (cdr JPOGame) 1 Col (car JPOGame))
			)
		)
		(if (equal?
				(JPOGetCell (cdr JPOGame) 2 Col)
				" "
			)
			(set! JPOGame
				(cons
					(if (equal?
							(car JPOGame)
							"X"
						)
						"O"
						"X"
					)
					(JPOSetCell (cdr JPOGame) 2 Col (car JPOGame))
				)
			)
			(if (equal?
					(JPOGetCell (cdr JPOGame) 3 Col)
					" "
				)
				(set! JPOGame
					(cons
						(if (equal?
								(car JPOGame)
								"X"
							)
							"O"
							"X"
						)
						(JPOSetCell (cdr JPOGame) 3 Col (car JPOGame))
					)
				)
				(if (equal?
						(JPOGetCell (cdr JPOGame) 4 Col)
						" "
					)
					(set! JPOGame
						(cons
							(if (equal?
									(car JPOGame)
									"X"
								)
								"O"
								"X"
							)
							(JPOSetCell (cdr JPOGame) 4 Col (car JPOGame))
						)
					)
					(if (equal?
							(JPOGetCell (cdr JPOGame) 5 Col)
							" "
						)
						(set! JPOGame
							(cons
								(if (equal?
										(car JPOGame)
										"X"
									)
									"O"
									"X"
								)
								(JPOSetCell (cdr JPOGame) 5 Col (car JPOGame))
							)
						)
						(set! JPOGame
							(cons
								(if (equal?
										(car JPOGame)
										"X"
									)
									"O"
									"X"
								)
								(JPOSetCell (cdr JPOGame) 6 Col (car JPOGame))
							)
						)
					)
				)
			)
		)
	)
	Col
)

;******************************************************************************
; JPOShowGame function:                                                       *
; PURPOSE: Shows the current state of the game board to the player            *
; IN: none                                                                    *
; OUT: returns true, displays the game state                                  *
;******************************************************************************
(define (JPOShowGame)
	(begin
                (newline)
		(display " |---------------------------|") (newline)
		(display " | ") (display (JPOGetCell (cdr JPOGame) 6 1)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 6 2)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 6 3)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 6 4)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 6 5)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 6 6)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 6 7)) (display " |") (newline)
		(display " |---------------------------|") (newline)
		(display " | ") (display (JPOGetCell (cdr JPOGame) 5 1)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 5 2)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 5 3)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 5 4)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 5 5)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 5 6)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 5 7)) (display " |") (newline)
		(display " |---------------------------|") (newline)
		(display " | ") (display (JPOGetCell (cdr JPOGame) 4 1)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 4 2)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 4 3)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 4 4)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 4 5)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 4 6)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 4 7)) (display " |") (newline)
		(display " |---------------------------|") (newline)
		(display " | ") (display (JPOGetCell (cdr JPOGame) 3 1)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 3 2)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 3 3)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 3 4)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 3 5)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 3 6)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 3 7)) (display " |") (newline)
		(display " |---------------------------|") (newline)
		(display " | ") (display (JPOGetCell (cdr JPOGame) 2 1)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 2 2)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 2 3)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 2 4)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 2 5)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 2 6)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 2 7)) (display " |") (newline)
		(display " |---------------------------|") (newline)
		(display " | ") (display (JPOGetCell (cdr JPOGame) 1 1)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 1 2)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 1 3)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 1 4)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 1 5)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 1 6)) (display " | ")
		(display (JPOGetCell (cdr JPOGame) 1 7)) (display " | ") (newline)
		(display " |---------------------------|") (newline)
		#t
	)
)

;******************************************************************************
; JPOMakeMove function:                                                       *
; PURPOSE: Marks a move chosen by the AI                                      *
; IN: none                                                                    *
; OUT: returns the chosen column                                              *
;******************************************************************************
(define (JPOMakeMove)
	(JPOMarkMove
		(JPOChooseMove)
	)
)

;******************************************************************************
; JPOChooseMove function:                                                     *
; PURPOSE: Logic that runs the AI move choice                                 *
; IN: none                                                                    *
; OUT: returns the chosen column                                              *
;******************************************************************************
(define (JPOChooseMove)
	(if (equal?
			(JPOIsEmpty (cdr JPOGame))
			#t
		)
		4
		(if (equal?
				(JPOIsBestFirstMove (cdr JPOGame))
				#t
			)
			6
			(if (>
					(JPOCheckWins 7)
					0
				)
				(JPOCheckWins 7)
				(if (>
						(JPOCheckTripBlocks 7)
						0
					)
					(JPOCheckTripBlocks 7)
					(if (>
							(JPOCheckBlocks 7)
							0
						)
						(JPOCheckBlocks 7)
						(if (>
								(JPOCheckDoubleLinks 7)
								0
							)
							(JPOCheckDoubleLinks 7)
							(if (> 
									(JPOCheckLinks 7)
									0
								)
								(JPOCheckLinks 7)
								(JPOMakeRandom 
									(+ 
										(random 7)
										1
									)
								)
							)
						)
					)
				)
			)
		)
	)
)

;******************************************************************************
; JPOMakeRandom function:                                                     *
; PURPOSE: The AI makes a random legal move                                   *
; IN: integer of the column to start looking (for recursion)                  *
; OUT: returns the chosen column                                              *
;******************************************************************************
(define (JPOMakeRandom Col)
	(if (equal? 
			(JPOLegalMoveP Col)
			#t
		)
		Col
		(JPOMakeRandom 
			(+ 
				(random 7)
				1
			)
		)
	)
)

;******************************************************************************
; JPOCheckWins function:                                                      *
; PURPOSE: Checks to see if any column will result in a win                   *
; IN: integer representing the column of a potential move                     *
; OUT: returns a column that results in a win or 0 if no win is available     *
;******************************************************************************
(define (JPOCheckWins Col)
	(if (<= 
			Col 
			0
		)
		0
		(if (equal?
				(JPOWillWinP Col)
				#t
			)
			Col
			(JPOCheckWins (- Col 1))
		)
	)
)

;******************************************************************************
; JPOCheckBlocks function:                                                    *
; PURPOSE: Checks to see if any column will result in a block                 *
; IN: integer representing the column of a potential move                     *
; OUT: returns a column that results in a block or 0 if no block is available *
;******************************************************************************
(define (JPOCheckBlocks Col)
	(if (<= 
			Col 
			0
		)
		0
		(if (equal?
				(JPOWillBlock Col)
				#t
			)
			Col
			(JPOCheckBlocks (- Col 1))
		)
	)
)

;******************************************************************************
; JPOCheckLinks function:                                                     *
; PURPOSE: Checks to see if any column will result in a link to a prev. move  *
; IN: integer representing the column of a potential move                     *
; OUT: returns a column that results in a link or 0 if no link is available   *
;******************************************************************************
(define (JPOCheckLinks Col)
	(if (<= 
			Col 
			0
		)
		0
		(if (equal?
				(JPOWillLink Col)
				#t
			)
			Col
			(JPOCheckLinks (- Col 1))
		)
	)
)

;******************************************************************************
; JPOIsEmpty function:                                                        *
; PURPOSE: Checks to see if the board is empty                                *
; IN: game board matrix                                                       *
; OUT: returns boolean of whether board is empty or not                       *
;******************************************************************************
(define (JPOIsEmpty Matrix)
	(if (and
			(equal? 
				(JPOGetCell Matrix 1 1)
				" "
			)
			(equal?	
				(JPOGetCell Matrix 1 2)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 3)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 4)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 5)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 6)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 7)
				" "
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOIsBestFirstMove function:                                                *
; PURPOSE: Checks to see if the opponent played a particular move as opening  *
; IN: game board matrix                                                       *
; OUT: returns boolean of whether board the move was made or not              *
;******************************************************************************
(define (JPOIsBestFirstMove Matrix)
	(if (and
			(equal? 
				(JPOGetCell Matrix 1 1)
				" "
			)
			(equal?	
				(JPOGetCell Matrix 1 2)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 3)
				" "
			)
			(equal?
					(JPOGetCell Matrix 1 4)
					"X"
			)
			(equal?
				(JPOGetCell Matrix 1 5)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 6)
				" "
			)
			(equal?
				(JPOGetCell Matrix 1 7)
				" "
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOLegalMoveP function:                                                     *
; PURPOSE: Checks to see if a move is legal                                   *
; IN: integer representing a column                                           *
; OUT: returns boolean of legality of chosen column                           *
;******************************************************************************
(define (JPOLegalMoveP Col)
	(if (equal?
			(JPOGetCell (cdr JPOGame) 6 Col)
			" "
		)
		#t
		#f
  )
)

;******************************************************************************
; JPOWinP function:                                                           *
; PURPOSE: Checks to see if given column resulted in a win                    *
; IN: integer representing the column of the last move                        *
; OUT: returns boolean of last move being a win                               *
;******************************************************************************
(define (JPOWinP Col)
	(if (equal? 
			(car JPOGame)
			"X"
		)
		(JPOWasWin 6 Col "O")
		(JPOWasWin 6 Col "X")
	)
)

;******************************************************************************
; JPOWasWin function:                                                         *
; PURPOSE: recursive helper function for JPOWinP to check each row in column  *
; IN: integer for row, column, string of last player's turn                   *
; OUT: returns boolean of last move being a win                               *
;******************************************************************************
(define (JPOWasWin Row Col Piece)
	(if (equal? 
			(JPOGetCell (cdr JPOGame) Row Col)
			" "
		)
		(JPOWasWin (- Row 1) Col Piece)
		(JPOWinSucceed Row Col Piece)
	)
)

;******************************************************************************
; JPOWinSucceed function:                                                     *
; PURPOSE: helper function for JPOWasWin to check each win possibility        *
; IN: integer for row, column, string of last player's turn                   *
; OUT: returns boolean of last move being a win                               *
;******************************************************************************
(define (JPOWinSucceed Row Col Piece)
	(if (or 
			(and
				(>= Col 4)
				(equal? 
					Piece
					(JPOGetCell (cdr JPOGame) Row (- Col 3))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (- Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece			
				)
			)
			(and
				(>= Col 3)
				(<= Col 6)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) Row (- Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
			)
			(and
				(>= Col 2)
				(<= Col 5)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 2))	
				)
			)
			(and
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 3))	
				)
			)
			(and
				(>= Row 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 1) Col)	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 2) Col)	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 3) Col)	
				)
			)
			(and
				(<= Row 3)
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 3) (+ Col 3))	
				)
			)
			(and
				(<= Row 3)
				(>= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 3) (- Col 3))	
				)
			)
			(and
				(>= Row 4)
				(>= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 3) (- Col 3))	
				)
			)
			(and
				(>= Row 4)
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 3) (+ Col 3))	
				)
			)
			(and
				(<= Row 4)
				(>= Row 2)
				(<= Col 5)
				(>= Col 2)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 		
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2))	
				)
			)
			(and
				(<= Row 5)
				(>= Row 3)
				(<= Col 6)
				(>= Col 3)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 				
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
			)
			(and
				(<= Row 5)
				(>= Row 3)
				(<= Col 5)
				(>= Col 2)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2))	
				)
			)
			(and
				(<= Row 4)
				(>= Row 2)
				(<= Col 6)
				(>= Col 3)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2))	
				)
				(equal?
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					Piece 			
				)
				(equal? 
					Piece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOWillWinP function:                                                       *
; PURPOSE: Determines if a given column will result in a win for curr. player *
; IN: integer for column                                                      *
; OUT: returns boolean of move being a win                                    *
;******************************************************************************
(define (JPOWillWinP Col)
	(if (equal? 
			(JPOGetCell (cdr JPOGame) 1 Col)
			" "
		)
		(JPOFindWin 1 Col)
		(if (equal?
				(JPOGetCell (cdr JPOGame) 2 Col)
				" "
			)
			(JPOFindWin 2 Col)
			(if (equal?
					(JPOGetCell (cdr JPOGame) 3 Col)
					" "
				)
				(JPOFindWin 3 Col)
					(if (equal?
							(JPOGetCell (cdr JPOGame) 4 Col)
							" "
						)
						(JPOFindWin 4 Col)
						(if (equal?
								(JPOGetCell (cdr JPOGame) 5 Col)
								" "
							)
							(JPOFindWin 5 Col)
							(if (equal?
									(JPOGetCell (cdr JPOGame) 6 Col)
									" "
								)
								(JPOFindWin 6 Col)
								#f
							)
						)
					)
				)
			)
		)
	)
;)

;******************************************************************************
; JPOFindWin function:                                                        *
; PURPOSE: determine if a given row and column will result in a win           *
; IN: integer for row, column                                                 *
; OUT: returns boolean of given move being a win                              *
;******************************************************************************
(define (JPOFindWin Row Col)
	(if (or 
			(and
				(>= Col 4)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 3))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
			)
			(and
				(>= Col 3)
				(<= Col 6)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
			)
			(and
				(>= Col 2)
				(<= Col 5)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 2))	
				)
			)
			(and
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 3))	
				)
			)
			(and
				(>= Row 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) Col)	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) Col)	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 3) Col)	
				)
			)
			(and
				(<= Row 3)
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 3) (+ Col 3))	
				)
			)
			(and
				(<= Row 3)
				(>= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 3) (- Col 3))	
				)
			)
			(and
				(>= Row 4)
				(>= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 3) (- Col 3))	
				)
			)
			(and
				(>= Row 4)
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 3) (+ Col 3))	
				)
			)
			(and
				(<= Row 4)
				(>= Row 2)
				(<= Col 5)
				(>= Col 2)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2))	
				)
			)
			(and
				(<= Row 5)
				(>= Row 3)
				(<= Col 6)
				(>= Col 3)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
			)
			(and
				(<= Row 5)
				(>= Row 3)
				(<= Col 5)
				(>= Col 2)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2))	
				)
			)
			(and
				(<= Row 4)
				(>= Row 2)
				(<= Col 6)
				(>= Col 3)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOWillBlock function:                                                      *
; PURPOSE: determines if given column will result in a block                  *
; IN: integer for column                                                      *
; OUT: returns boolean of column resulting in a block                         *
;******************************************************************************
(define (JPOWillBlock Col)
	(if (equal? 
			(JPOGetCell (cdr JPOGame) 1 Col)
			" "
		)
		(JPOFindBlock 
			1 
			Col 
			(if (equal? 
					(car JPOGame) 
					"X"
				) 
				"O" 
				"X"
			)
		)
		(if (equal?
				(JPOGetCell (cdr JPOGame) 2 Col)
				" "
			)
			(JPOFindBlock 
				2 
				Col 
				(if (equal? 
						(car JPOGame) 
						"X"
					) 
					"O" 
					"X"
				)
			)
			(if (equal?
					(JPOGetCell (cdr JPOGame) 3 Col)
					" "
				)
				(JPOFindBlock 
					3 
					Col 
					(if (equal? 
							(car JPOGame) 
							"X"
						) 
						"O" 
						"X"
					)
				)
				(if (equal?
						(JPOGetCell (cdr JPOGame) 4 Col)
						" "
					)
					(JPOFindBlock 
						4 
						Col 
						(if (equal? 
								(car JPOGame) 
								"X"
							) 
							"O" 
							"X"
						)
					)
					(if (equal?
							(JPOGetCell (cdr JPOGame) 5 Col)
							" "
						)
						(JPOFindBlock 
							5 
							Col 
							(if (equal? 
									(car JPOGame) 
									"X"
								) 
								"O" 
								"X"
							)
						)
						(if (equal?
								(JPOGetCell (cdr JPOGame) 6 Col)
								" "
							)
							(JPOFindBlock 
								6 
								Col 
								(if (equal? 
										(car JPOGame) 
										"X"
									) 
									"O" 
									"X"
								)
							)
							#f
						)
					)
				)
			)
		)
	)
)

;******************************************************************************
; JPOFindBlock function:                                                      *
; PURPOSE: determines if given row and column will result in a block          *
; IN: integer for row, column, string of opponent's piece                     *
; OUT: returns boolean of move resulting in a block                           *
;******************************************************************************
(define (JPOFindBlock Row Col OppPiece)
	(if (or 
			(and
				(>= Col 3)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (- Col 2))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
			)
			(and
				(>= Col 2)
				(<= Col 6)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
			)
			(and
				(<= Col 5)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 2))	
				)
			)
			(and
				(>= Row 3)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) Col)	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 2) Col)	
				)
			)
			(and
				(<= Row 4)
				(<= Col 5)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2))	
				)
			)
			(and
				(<= Row 4)
				(>= Col 3)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2))	
				)
			)
			(and
				(>= Row 3)
				(>= Col 3)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2))	
				)
			)
			(and
				(>= Row 3)
				(<= Col 5)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2))	
				)
			)
			(and
				(<= Row 5)
				(>= Row 2)
				(<= Col 6)
				(>= Col 2)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
			)
			(and
				(<= Row 5)
				(>= Row 2)
				(<= Col 6)
				(>= Col 2)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOWillLink function:                                                       *
; PURPOSE: determines if given column will result in a link                   *
; IN: integer for column                                                      *
; OUT: returns boolean of column resulting in a link                          *
;******************************************************************************
(define (JPOWillLink Col)
	(if (equal? 
			(JPOGetCell (cdr JPOGame) 1 Col)
			" "
		)
		(JPOFindLink 1 Col)
		(if (equal?
				(JPOGetCell (cdr JPOGame) 2 Col)
				" "
			)
			(JPOFindLink 2 Col)
			(if (equal?
					(JPOGetCell (cdr JPOGame) 3 Col)
					" "
				)
				(JPOFindLink 3 Col)
					(if (equal?
							(JPOGetCell (cdr JPOGame) 4 Col)
							" "
						)
						(JPOFindLink 4 Col)
						(if (equal?
								(JPOGetCell (cdr JPOGame) 5 Col)
								" "
							)
							(JPOFindLink 5 Col)
							(if (equal?
									(JPOGetCell (cdr JPOGame) 6 Col)
									" "
								)
								(JPOFindLink 6 Col)
								#f
							)
						)
					)
				)
			)
		)
	)
;)

;******************************************************************************
; JPOFindLink function:                                                       *
; PURPOSE: determines if given row and column will result in a link           *
; IN: integer for row, column                                                 *
; OUT: returns boolean of move resulting in a link                            *
;******************************************************************************
(define (JPOFindLink Row Col)
	(if (or 
			(and
				(>= Row 2)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) Col)	
				)
			)
			(and
				(>= Col 2)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
			)
			(and
				(<= Col 6)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
			)
			(and
				(<= Row 5)
				(<= Col 6)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
			)
			(and
				(<= Row 5)
				(>= Col 2)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
			)
			(and
				(>= Row 2)
				(>= Col 2)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
			)
			(and
				(>= Row 2)
				(<= Col 6)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOCheckDoubleLink function:                                                *
; PURPOSE: recursively go through each column searching for links of 2        *
; IN: integer for column                                                      *
; OUT: returns integer of column that has links of 2, 0 if none               *
;******************************************************************************
(define (JPOCheckDoubleLinks Col)
	(if (<= 
			Col 
			0
		)
		0
		(if (equal?
				(JPOWillDoubleLink Col)
				#t
			)
			Col
			(JPOCheckDoubleLinks (- Col 1))
		)
	)
)

;******************************************************************************
; JPOWillDoubleLink function:                                                 *
; PURPOSE: determines if given column will result in a link of 2              *
; IN: integer for column                                                      *
; OUT: returns boolean of column resulting in a link of 2                     *
;******************************************************************************
(define (JPOWillDoubleLink Col)
	(if (equal? 
			(JPOGetCell (cdr JPOGame) 1 Col)
			" "
		)
		(JPOFindDoubleLink 1 Col)
		(if (equal?
				(JPOGetCell (cdr JPOGame) 2 Col)
				" "
			)
			(JPOFindDoubleLink 2 Col)
			(if (equal?
					(JPOGetCell (cdr JPOGame) 3 Col)
					" "
				)
				(JPOFindDoubleLink 3 Col)
					(if (equal?
							(JPOGetCell (cdr JPOGame) 4 Col)
							" "
						)
						(JPOFindDoubleLink 4 Col)
						(if (equal?
								(JPOGetCell (cdr JPOGame) 5 Col)
								" "
							)
							(JPOFindDoubleLink 5 Col)
							(if (equal?
									(JPOGetCell (cdr JPOGame) 6 Col)
									" "
								)
								(JPOFindDoubleLink 6 Col)
								#f
							)
						)
					)
				)
			)
		)
	)
;)

;******************************************************************************
; JPOFindDoubleLink function:                                                 *
; PURPOSE: determines if given row and column will result in a link of 2      *
; IN: integer for row, column                                                 *
; OUT: returns boolean of move resulting in a link of 2                       *
;******************************************************************************
(define (JPOFindDoubleLink Row Col)
	(if (or 
			(and
				(>= Row 3)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) Col)	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) Col)	
				)
			)
			(and
				(>= Col 3)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 2))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
			)
			(and
				(<= Col 5)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
				(equal?
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 2))	
				)
			)
			(and
				(<= Row 4)
				(<= Col 5)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2))	
				)
			)
			(and
				(<= Row 4)
				(>= Col 3)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2))	
				)
			)
			(and
				(>= Row 3)
				(>= Col 3)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2))	
				)
			)
			(and
				(>= Row 3)
				(<= Col 5)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2))	
				)
			)
			(and
				(>= Col 2)
				(<= Col 6)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
			)
			(and
				(>= Row 2)
				(<= Row 5)
				(>= Col 2)
				(<= Col 6)				
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
			)
			(and
				(>= Row 2)
				(<= Row 5)
				(>= Col 2)
				(<= Col 6)				
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					(car JPOGame) 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOCheckTripBlocks function:                                                *
; PURPOSE: Checks to see if any column will result in a block of 3            *
; IN: integer representing the column of a potential move                     *
; OUT: returns a column that results in a block of 3 or 0 if none             *
;******************************************************************************
(define (JPOCheckTripBlocks Col)
	(if (<= 
			Col 
			0
		)
		0
		(if (equal?
				(JPOWillTripBlock Col)
				#t
			)
			Col
			(JPOCheckTripBlocks (- Col 1))
		)
	)
)

;******************************************************************************
; JPOWillTripBlock function:                                                  *
; PURPOSE: determines if given column will result in a block of 3             *
; IN: integer for column                                                      *
; OUT: returns boolean of column resulting in a block of 3                    *
;******************************************************************************
(define (JPOWillTripBlock Col)
	(if (equal? 
			(JPOGetCell (cdr JPOGame) 1 Col)
			" "
		)
		(JPOFindTripBlock 
			1 
			Col 
			(if (equal? 
					(car JPOGame) 
					"X"
				) 
				"O" 
				"X"
			)
		)
		(if (equal?
				(JPOGetCell (cdr JPOGame) 2 Col)
				" "
			)
			(JPOFindTripBlock 
				2 
				Col 
				(if (equal? 
						(car JPOGame) 
						"X"
					) 
					"O" 
					"X"
				)
			)
			(if (equal?
					(JPOGetCell (cdr JPOGame) 3 Col)
					" "
				)
				(JPOFindTripBlock 
					3 
					Col 
					(if (equal? 
							(car JPOGame) 
							"X"
						) 
						"O" 
						"X"
					)
				)
				(if (equal?
						(JPOGetCell (cdr JPOGame) 4 Col)
						" "
					)
					(JPOFindTripBlock 
						4 
						Col 
						(if (equal? 
								(car JPOGame) 
								"X"
							) 
							"O" 
							"X"
						)
					)
					(if (equal?
							(JPOGetCell (cdr JPOGame) 5 Col)
							" "
						)
						(JPOFindTripBlock 
							5 
							Col 
							(if (equal? 
									(car JPOGame) 
									"X"
								) 
								"O" 
								"X"
							)
						)
						(if (equal?
								(JPOGetCell (cdr JPOGame) 6 Col)
								" "
							)
							(JPOFindTripBlock 
								6 
								Col 
								(if (equal? 
										(car JPOGame) 
										"X"
									) 
									"O" 
									"X"
								)
							)
							#f
						)
					)
				)
			)
		)
	)
)

;******************************************************************************
; JPOFindTripBlock function:                                                  *
; PURPOSE: determines if given row and column will result in a block of 3     *
; IN: integer for row, column, string of opponent's piece                     *
; OUT: returns boolean of move resulting in a block of 3                      *
;******************************************************************************
(define (JPOFindTripBlock Row Col OppPiece)
	(if (or 
			(and
				(>= Col 4)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (- Col 3))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (- Col 2))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (- Col 1))	
				)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
			)
			(and
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 1))	
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 2))	
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) Row (+ Col 3))	
				)
			)
			(and
				(>= Row 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) Col)	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 2) Col)	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 2) Col)	
				)
			)
			(and
				(<= Row 3)
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 3) (+ Col 3))	
				)
			)
			(and
				(<= Row 3)
				(>= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (+ Row 3) (- Col 3))	
				)
			)
			(and
				(>= Row 4)
				(>= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 3) (- Col 3))	
				)
			)
			(and
				(>= Row 4)
				(<= Col 4)
				(equal?
					(JPOGetCell (cdr JPOGame) Row Col)
					" "				
				)
				(equal? 
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2))	
				)
				(equal?
					OppPiece 
					(JPOGetCell (cdr JPOGame) (- Row 3) (+ Col 3))	
				)
			)
		)
		#t
		#f
	)
)

;******************************************************************************
; JPOGetCell function:                                                        *
; PURPOSE: recursively navigate by row to specified cell and return its item  *
; IN: integer for row,column, list for game board                             *
; OUT: returns string of item at specified location                           *
;******************************************************************************
(define (JPOGetCell Matrix Row Column)
	(if (<= 
			Row
			1
		)
		(JPOGetItem (car Matrix) Column)
		(JPOGetCell (cdr Matrix) (- Row 1) Column)
	)
)

;******************************************************************************
; JPOGetCell function:                                                        *
; PURPOSE: recursively navigate by column to specified cell to return its item*
; IN: integer for column, list for row                                        *
; OUT: returns string of item at specified location                           *
;******************************************************************************
(define (JPOGetItem Row Column)
	(if (<=
			Column
			1
		)
		(car Row)
		(JPOGetItem (cdr Row) (- Column 1))
	)
)

;******************************************************************************
; JPOSetCell function:                                                        *
; PURPOSE: recursively navigate by row to specified cell and update its item  *
; IN: integer for row,column, list for game board, string for item            *
; OUT: returns list of updated game board                                     *
;******************************************************************************
(define (JPOSetCell Matrix Row Column Item)
	(if (<= 
			Row
			1
		)
		(cons
			(JPOSetItem (car Matrix) Column Item)
			(cdr Matrix)
		)
		(cons
			(car Matrix)
			(JPOSetCell (cdr Matrix) (- Row 1) Column Item)
		)
	)
)

;******************************************************************************
; JPOSetCell function:                                                        *
; PURPOSE: recursively navigate by column to specified cell to update its item*
; IN: integer for column, list for row, string for item                       *
; OUT: returns list of updated game board                                     *
;******************************************************************************
(define (JPOSetItem Row Column Item)
	(if (<=
			Column
			1
		)
		(cons 
			Item
			(cdr Row)
		)
		(cons 
			(car Row)
			(JPOSetItem (cdr Row) (- Column 1) Item)
		)
	)
)

;******************************************************************************
; Menu function:                                                              *
; PURPOSE: Display user menu and obtain player choice                         *
; IN: none                                                                    *
; OUT: returns integer of chosen menu option                                  *
;******************************************************************************
(define (Menu)
        (define column -1)
        (newline)
        (display "Choose an option:") (newline)
        (display "[1] Start New Game (Start Over)") (newline)
        (display "[2] Make a move") (newline)
        (display "[3] Have AI make a move") (newline)
        (display "[4] Check if last move was a win") (newline)
        (display "[5] Quit") (newline)
        (define choice (read))
        (if (= choice 1)
            (JPOStartGame)
            (if (= choice 2)
                (begin
                   (display "Please enter a column for the move (1-7): ")
                   (set! column (read))
                   (JPOMarkMove column)
                )
                (if (= choice 3)
                    (display (JPOMakeMove))
                    (if (= choice 4)
                        (begin
                          (display "Enter the column number of the last move (1-7): ")
                          (set! column (read))
                          (display (JPOWinP column))
                        )
                        5
                    )
                )
            )
        )
        (JPOShowGame)
        choice
)

;******************************************************************************
; PlayGame function:                                                          *
; PURPOSE: Runs recursive loop of game                                        *
; IN: integer of choice                                                       *
; OUT: none                                                                   *
;******************************************************************************
(define (PlayGame choice)
        (if (= choice 5)
            (display "Have a wonderful day!")
            (PlayGame (Menu))
        )
)

;******************************************************************************
; Driving Code:                                                               *
; PURPOSE: Handles input/output and function calls                            *
;******************************************************************************
(display "Connect Four") (newline)
(display "This game allows two players, player vs AI, or two AIs to battle each other in a game of Connect Four.")
(newline) (newline)
(PlayGame 0)


;-----Test Code Beyond Here-----

;(JPOStartGame) ; nothing much#t
;(JPOShowGame) 
;(JPOIsEmpty (cdr JPOGame))
;(JPOMarkMove 1)
;(JPOMarkMove 2)
;(JPOMarkMove 3)
;(JPOMarkMove 4)
;(JPOMarkMove 5)
;(JPOMarkMove 6)
;(JPOMarkMove 7)
;(JPOShowGame)
;(JPOFindWin 1 4)
;(JPOMakeMove)
;(JPOShowGame)