Need help with learning AI

Blitz3D Forums/Blitz3D Beginners Area/Need help with learning AI

Okay, so for my science fair project, I'm programming a Tic-Tac-Toe AI opponent which starts out with no knowledge of the game, and learns as it goes along. I tried to implement a simple reinforcement learning system, but it doesn't give good enough results; it only wins 86% of its total games at most (at the beginning of the program, at around 100 games) against a random opponent, and then drops to 77-80% and stays there. I want the learning AI to win over 90% of the time, at least.

Here's the code I'm using (doesn't require any external files):

Graphics 640,480,0,2
SetBuffer BackBuffer()

AppTitle "Tic-Tac-Toe w/ Learning AI"


; Each state is defined in a type.

Type state
	Field stateID
	Field boardVals[8]
	Field cellWeights#[8]
	Field lossNum
End Type


; Variables and arrays

Dim currentBoard(8)				; current board
Global stateMap[8]				; state map for current game
Global moveMap[8]				; move map for current game

Global currentMoveVals#[8]		; move values for the last game (only used for debug display)

Global moveNum = 0				; move #
Global highState = 0			; the state ID of the last state created

Global winNum# = 0				; # of games won
Global totalGames# = 0			; total games played


; Main loop

While Not KeyHit(1)
	Cls
	
	If Not checkWin() > 0.5 Then
		; AI's turn			
		learningAI()
		updateStateMap()
		
		
		
		If Not checkWin() > 0.5 Then
			; Random opponent's turn
			randomMove(2)
			updateStateMap()
			
			checkWin()
		EndIf
	EndIf
	
	displayBoard()
	
	;Check if the game has reached an outcome; if so, give AI feedback and restart.
	
	If checkWin() > 0.5 Then 
		feedbackValues()
		If checkWin() = 1 Then winNum = winNum + 1
		If checkWin() = 2 Then lossNum = lossNum + 1
		totalGames = totalGames + 1
		
		;debugDisplay()			; Uncomment this line to enable the debug display at the end of each game.
		
		clearBoard()
		
		For x = 0 To 8
			stateMap[x] = 0
			moveMap[x] = 0
			currentMoveVals[x] = 0
		Next
		moveNum = 0
		
	EndIf
	
	; Display # of games won, total games, % of games won
	
	Text 40,20,"GAMES WON: " + winNum#
	Text 40,35,"TOTAL GAMES: " + totalGames
	If totalGames>0 Then Text 40,75,"% OF GAMES WON: " + (winNum# / totalGames#) * 100
		
	Flip 0
Wend



Function learningAI()
	stateMatched = False
		
	; The following for loop checks each state to see if it matches the current board. If it does,
	; it checks to see which cell has the most weight.
	For a.state = Each state	
		For x = 0 To 8
			If currentBoard(x) = a\boardVals[x] Then matchNum = matchNum+1
		Next
			
		If matchNum = 8 Then
			maxWeight = 0
			maxCell = 0
			
			; Find highest weight, and the corresponding cell for that weight.
			For x = 0 To 8
				weight = a\cellWeights[x]			
				If weight > maxWeight Then
					weight = maxWeight
					maxCell = x
				EndIf
				
			Next
			
			cellNum = maxCell		
			Exit
		EndIf	
	Next

	; Marks the highest-rated cell if the state has been matched in the state table. If it hasn't,
	; either move in the first unmarked spot or move randomly.
	If stateMatched = True Then	
		currentBoard(cellNum) = 1
		moveMap[moveNum] = cellNum
	Else	
		; Sometimes exploratory steps are taken, to increase the number of possible states the AI sees.
		If Rnd(0,1)>0.05 Then moveMap[moveNum] = firstMove(1) Else moveMap[moveNum] = randomMove(1)
	EndIf	
End Function
		

; Makes a random move. Takes the player # as a parameter (this function is used by both opponents).

Function randomMove(oppNum)
	count = 0
	
	Repeat
		count = count + 1
		ff = Rand(0,8)
	Until currentBoard(ff) = 0 Or count > 100
		
	If count < 100 Then currentBoard(ff) = oppNum
	
	Return ff
End Function


; Puts a piece in the first available spot.

Function firstMove(oppNum)
	For ff = 0 To 8
		If currentBoard(ff) = 0 Then 
			Exit
		EndIf
	Next
	
	If currentBoard(ff) = 0 Then 
		currentBoard(ff) = oppNum
	Else
		ff = 0
	EndIf
	
	Return ff
End Function


; Checks to see if the game has reached an outcome.

Function checkWin()
	For oppNum = 1 To 2
	
		; Horizontal/vertical check
		For x = 0 To 2			
			If currentBoard(x) = oppNum And currentBoard(x+3) = oppNum And currentBoard(x+6) = oppNum Then
				Return oppNum
			EndIf
			
			If currentBoard(x*3) = oppNum And currentBoard((x*3)+1) = oppNum And currentBoard((x*3)+2) = oppNum Then
				Return oppNum
			EndIf
		Next
		
		; Diagonal checks
		If currentBoard(0) = oppNum And currentBoard(4) = oppNum And currentBoard(8) = oppNum Then
			Return oppNum
		EndIf
		
		If currentBoard(2) = oppNum And currentBoard(4) = oppNum And currentBoard(6) = oppNum Then
			Return oppNum
		EndIf
	Next
	
	
	blankNum% = 0
	
	; Check to see how many blank spaces there are.
	For x = 0 To 8
		If currentBoard(x) = 0 Then blankNum = blankNum + 1
	Next
	
	; If all spaces are taken up, then game is a draw, so return 3; if not, go on and return 0.5.
	If blankNum = 0 Then Return 3
	
	Return 0.5
	
End Function


; Displays the board.

Function displayBoard()
	x2%=0
	y2%=0
	
	For x = 0 To 8
		number% = currentBoard(x)
			
		Select number
			Case 1
				lStr$ = "X"
			Case 2
				lStr$ = "O"
			Default
				lStr$ = " "		
		End Select
				
		Text 270+(x2*40),190+(y2*40),lStr$
		If x2<2 Then Text 290+(x2*40),190+(y2*40),"|"
		If y2<2 Then Text 270,210+(y2*40),"-----------"
			
		
		x2=x2+1
		
		If x2=3 Then
			y2=y2+1
			x2=0
		EndIf
	Next
End Function


; Clears the current board.

Function clearBoard()
	For x = 0 To 8
		currentBoard(x) = 0
	Next
End Function


; Updates the state map, identifying which states the current game has gone through, and also
; adding new states when they are encountered.

Function updateStateMap()
	moveNum = moveNum + 1
	
	stateMatched = False
	stateNum = 0
	
	; Search each state for a match to the current board. If there is a match, then update
	; the state map and return.
	For a.state = Each state
		For x = 0 To 8
			If currentBoard(x) = a\boardVals[x] Then matchNum = matchNum+1
			
			If matchNum = 9 Then
				stateNum = a\stateID
				stateMap[moveNum] = stateNum
				Return
			EndIf
		Next
		
	Next
	
	; If there is not a match, then initialize a new state, update the state map with this state,
	; and return.
	a.state = New state
	highState = highState + 1
			
	For x = 0 To 8
		a\boardVals[x] = currentBoard(x)
		a\cellWeights[x] = 0
		a\stateID = highState
	Next
	
	stateMap[moveNum] = highState
	
End Function


; Feedback function for end of game; adjusts the cell weights for all the states used in the
; previous game using the outcome of the game.

Function feedbackValues()
	For a.state = Each state
		For x = 0 To 8
			If a\stateID = stateMap[x] And a\stateID > 0 Then
				If checkWin() = 1 Then
					; Win feedback			[+3]		
					a\cellWeights[moveMap[x]] = a\cellWeights[moveMap[x]]+3
				Else	
					; Lose/draw feedback	[-5]
					a\cellWeights[moveMap[x]] = a\cellWeights[moveMap[x]]-5
				EndIf
				
				currentMoveVals[x] = a\cellWeights[moveMap[x]]
			EndIf
		Next
	Next	
End Function


; Debug

Function debugDisplay()
	For x = 0 To 8
		Text 300,10*x,stateMap[x]
		Text 400,10*x,moveMap[x]
		Text 500,10*x,currentMoveVals[x]
		Text 400,100,highState
	Next
	
	Flip
	Delay 500
End Function


If anyone could please help me figure out what I'm doing wrong here, it would be greatly appreciated.