Microsoft Small Basic

Program Listing: JKB381
' TicTacToe MIX
' RANDOM vs
' RANDOMX only for O vs
' RUNANDSTOP vs
' MONTECARLO vs
' HUMAN
logicO = "MONTECARLO"
logicX = "HUMAN"
tiO = 0 ' times O win
tiX = 0 ' times X win
tiD = 0 ' times draw
tiG = 0 ' times games
tiGmax = 100
tiW = 10 ' times work out for MONTECARLO
GraphicsWindow.BrushColor = "SteelBlue"
seed = 0
debug = "False"

nextgame:
GraphicsWindow.Clear()
If tiG > 0 Then
ShowResult()
EndIf
s = 0
ClearBoard() ' board <- 0
SaveBoard() ' current board <- board
ShowBoard()

loop:
' turn O
GetPutList()
s = s + 1
If logicO = "RANDOM" Then
Random()
ElseIf logicO = "RANDOMX" Then
RandomX()
ElseIf logicO = "RUNANDSTOP" Then
RunAndStop()
ElseIf logicO = "MONTECARLO" Then
WorkOut() 'determine a from put list by MONTECARLO method
ElseIf logicO = "HUMAN" Then
Human()
EndIf
c[x][y] = 1
Record()
RestoreBoard() ' board <- current board
ShowBoard()
CheckGameEnd()
If game <> "continue" Then
Goto exit
EndIf

'MONTECARLO X
GetPutList()
s = s + 1
If logicX = "RANDOM" Then
Random()
ElseIf logicX = "RANDOMX" Then
RandomX()
ElseIf logicX = "RUNANDSTOP" Then
RunAndStop()
ElseIf logicX = "MONTECARLO" Then
WorkOut() 'determine a from put list by MONTECARLO method
ElseIf logicX = "HUMAN" Then
Human()
EndIf
c[x][y] = 2
Record()
RestoreBoard() ' board <- current board
ShowBoard()
CheckGameEnd()
If game <> "continue" Then
Goto exit
EndIf

Goto loop

exit:
GraphicsWindow.DrawText(10, 10, game)
If game = "O win" then
tiO = tiO + 1
ElseIf game = "X win" then
tiX = tiX + 1
Else
tiD = tiD + 1
EndIf
tiG = tiG + 1
If game = "O win" then
Program.Delay(500)
Else
Program.Delay(500)
EndIf
If tiG < tiGmax Then
Goto nextgame
EndIf
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FillRectangle(400, 20, 150, 150)
GraphicsWindow.BrushColor = "SteelBlue"
ShowResult()

Sub Human
x = px[1]
y = py[1]
ShowPointer()
currentmouse:
Program.Delay(100)
mx = GraphicsWindow.MouseX
my = GraphicsWindow.MouseY
GetPosition()
HidePointer()
ShowPointer()
If Mouse.isLeftButtonDown Then
Goto checkput
Else
Goto currentmouse
EndIf
checkput:
For a = 1 To p
If px[a] = x And py[a] = y Then
Goto returnmouse
EndIf
EndFor
Goto currentmouse
returnmouse:
HidePointer()
x = px[a]
y = py[a]
EndSub

Sub ShowPointer
cx = x
cy = y
GraphicsWindow.PenColor = "DeepSkyBlue"
GraphicsWindow.DrawRectangle(60 + (3 - x) * 100, 60 + (3 - y) * 100, 80, 80)
GraphicsWindow.PenColor = "Black"
EndSub

Sub HidePointer
GraphicsWindow.PenColor = "White"
GraphicsWindow.DrawRectangle(60 + (3 - cx) * 100, 60 + (3 - cy) * 100, 80, 80)
GraphicsWindow.PenColor = "Black"
EndSub

Sub GetPosition
If mx < 150 Then
x = 3
ElseIf mx < 250 Then
x = 2
Else
x = 1
EndIf
If my < 150 Then
y = 3
ElseIf my < 250 Then
y = 2
Else
y = 1
EndIf
EndSub

Sub Record
rx[s] = x
ry[s] = y
EndSub

Sub ShowRecord
For i = 1 to s
TextWindow.Write("[" + rx[i] + "][" + ry[i] + "],")
EndFor
TextWindow.WriteLine("")
EndSub

Sub ShowPutList
For i = 1 To p
TextWindow.Write("px[" + i + "]=" + px[i])
TextWindow.WriteLine(",py[" + i + "]=" + py[i])
EndFor
EndSub

Sub SavePutList
n = p
For i = 1 To n
sx[i] = px[i]
sy[i] = py[i]
EndFor
EndSub

Sub RestorePutList
p = n
For i = 1 To p
px[i] = sx[i]
py[i] = sy[i]
EndFor
EndSub

Sub SaveBoard
For y = 3 To 1 Step -1
For x = 3 To 1 Step -1
c[x][y] = b[x][y]
EndFor
EndFor
EndSub

Sub RestoreBoard
For y = 3 To 1 Step -1
For x = 3 To 1 Step -1
b[x][y] = c[x][y]
EndFor
EndFor
EndSub

Sub WorkOut
SavePutList()
ss = s ' save stage

For i = 1 To n ' instead of p
win[i] = 0 ' result clear
EndFor
For g = 1 To tiW * n
s = ss - 1 ' temporaly stage
RestoreBoard() ' board <- current board
turn = "O"
If Math.Remainder(s, 2) = 0 Then
turn = "X"
Goto nextX
EndIf

nextO:
' RANDOM O
GetPutList()
s = s + 1
RunAndStop()
If s = ss Then
f = a ' first put
EndIf
b[x][y] = 1
CheckGameEnd()
If game <> "continue" Then
Goto endgame
EndIf

nextX:
' RANDOM X
GetPutList()
s = s + 1
RunAndStop()
If s = ss Then
f = a ' first put
EndIf
b[x][y] = 2
CheckGameEnd()
If game <> "continue" Then
Goto endgame
EndIf

Goto nextO

endgame:
If game = turn + " win" then
win[f] = win[f] + 3 * (10 - s)
ElseIf game = "draw" then
win[f] = win[f] + (10 - s)
Else
win[f] = win[f] + 2 * (10 - s)
EndIf
EndFor

max = 0
For i = 1 to n ' instead of p
If win[i] >= max Then
max = win[i]
a = i
EndIf
EndFor
RestorePutList()
s = ss ' restore stage
x = px[a]
y = py[a]
EndSub

Sub Random
a = Math.GetRandomNumber(p)
If debug Then
seed = seed + 1
If seed > p Then
seed = 1
EndIf
a = seed
EndIf
x = px[a]
y = py[a]
EndSub

Sub RandomX
If s = 1 Then
x = 2
y = 2
Else
Random()
EndIf
EndSub

Sub RunAndStop
' clear run and stop candidate
For i = 1 To p
run[i] = 0
stop[i] = 0
EndFor
' set next of candidate
For i = 1 To p
x0 = px[i]
If x0 = 1 Then
x1 = 2
x2 = 3
ElseIf x0 = 2 Then
x1 = 1
x2 = 3
Else
x1 = 1
x2 = 2
EndIf
y0 = py[i]
If y0 = 1 Then
y1 = 2
y2 = 3
ElseIf y0 = 2 Then
y1 = 1
y2 = 3
Else
y1 = 1
y2 = 2
EndIf
'
If b[x1][y0] = b[x2][y0] Then
' horizontal run or stop found
If b[x1][y0] = 1 Then
' O O
If Math.Remainder(s, 2) = 1 Then
' turn O
run[i] = run[i] + 1
Else
' turn X
stop[i] = stop[i] + 1
EndIf
EndIf
If b[x1][y0] = 2 Then
' X X
If Math.Remainder(s, 2) = 1 Then
' turn O
stop[i] = stop[i] + 1
Else
' turn X
run[i] = run[i] +1
EndIf
EndIf
EndIf
If b[x0][y1] = b[x0][y2] Then
' vartical run found
If b[x0][y1] = 1 Then
' O O
If Math.Remainder(s, 2) = 1 Then
' turn O
run[i] = run[i] +1
Else
' turn X
stop[i] = stop[i] + 1
EndIf
EndIf
If b[x0][y1] = 2 Then
' X X
If Math.Remainder(s, 2) = 1 Then
' turn O
stop[i] = stop[i] + 1
Else
' turn X
run[i] = run[i] +1
EndIf
EndIf
EndIf
If x0 = y0 And b[x1][y1] = b[x2][y2] Then
' down run or stop found
If b[x1][y1] = 1 Then
' O O
If Math.Remainder(s, 2) = 1 Then
' turn O
run[i] = run[i] + 1
Else
' turn X
stop[i] = stop[i] + 1
EndIf
EndIf
If b[x1][y1] = 2 Then
' X X
If Math.Remainder(s, 2) = 1 Then
' turn O
stop[i] = stop[i] + 1
Else
' turn X
run[i] = run[i] + 1
EndIf
EndIf
EndIf
If x0 + y0 = 4 And b[x1][y2] = b[x2][y1] Then
' up run or stop found
If b[x1][y2] = 1 Then
' O O
If Math.Remainder(s, 2) = 1 Then
' turn O
run[i] = run[i] + 1
Else
' turn X
stop[i] = stop[i] + 1
EndIf
EndIf
If b[x1][y2] = 2 Then
' X X
If Math.Remainder(s, 2) = 1 Then
' turn O
stop[i] = stop[i] + 1
Else
' turn X
run[i] = run[i] + 1
EndIf
EndIf
EndIf
EndFor
max = 0
For i = 1 To p
If run[i] > max Then
max = run[i]
a = i
EndIf
EndFor
If max > 0 Then
Goto returna
EndIf
For i = 1 To p
If stop[i] > max Then
max = stop[i]
a = i
EndIf
EndFor
If max > 0 Then
Goto returna
EndIf
Random()
returna:
x = px[a]
y = py[a]
EndSub

Sub ShowResult
GraphicsWindow.DrawText(400, 20, "O win: " + tiO + " (" + Math.Floor(tiO / tiG * 100) + "%)")
GraphicsWindow.DrawText(400, 40, "X win: " + tiX + " (" + Math.Floor(tiX / tiG * 100) + "%)")
GraphicsWindow.DrawText(400, 60, "draw : " + tiD + " (" + Math.Floor(tiD / tiG * 100) + "%)")
GraphicsWindow.DrawText(400, 80, "games: " + tiG)
GraphicsWindow.DrawText(400, 120, "O: " + logicO)
GraphicsWindow.DrawText(400, 140, "X: " + logicX)
EndSub

Sub CheckGameEnd
game = "continue"
If p <= 6 Then
If Math.Remainder(s, 2) = 1 Then
If b[3][3] = 1 And b[2][3] = 1 And b[1][3] = 1 Then
game = "O win"
EndIf
If b[3][2] = 1 And b[2][2] = 1 And b[1][2] = 1 Then
game = "O win"
EndIf
If b[3][1] = 1 And b[2][1] = 1 And b[1][1] = 1 Then
game = "O win"
EndIf
If b[3][3] = 1 And b[3][2] = 1 And b[3][1] = 1 Then
game = "O win"
EndIf
If b[2][3] = 1 And b[2][2] = 1 And b[2][1] = 1 Then
game = "O win"
EndIf
If b[1][3] = 1 And b[1][2] = 1 And b[1][1] = 1 Then
game = "O win"
EndIf
If b[3][3] = 1 And b[2][2] = 1 And b[1][1] = 1 Then
game = "O win"
EndIf
If b[3][1] = 1 And b[2][2] = 1 And b[1][3] = 1 Then
game = "O win"
EndIf
Else
If b[3][3] = 2 And b[2][3] = 2 And b[1][3] = 2 Then
game = "X win"
EndIf
If b[3][2] = 2 And b[2][2] = 2 And b[1][2] = 2 Then
game = "X win"
EndIf
If b[3][1] = 2 And b[2][1] = 2 And b[1][1] = 2 Then
game = "X win"
EndIf
If b[3][3] = 2 And b[3][2] = 2 And b[3][1] = 2 Then
game = "X win"
EndIf
If b[2][3] = 2 And b[2][2] = 2 And b[2][1] = 2 Then
game = "X win"
EndIf
If b[1][3] = 2 And b[1][2] = 2 And b[1][1] = 2 Then
game = "X win"
EndIf
If b[3][3] = 2 And b[2][2] = 2 And b[1][1] = 2 Then
game = "X win"
EndIf
If b[3][1] = 2 And b[2][2] = 2 And b[1][3] = 2 Then
game = "X win"
EndIf
EndIF
If p = 1 And game = "continue" Then
game = "draw"
EndIf
EndIf
EndSub

Sub GetPutList
p = 0
For a = 0 to 8
If b[Math.Remainder(a, 3) + 1][Math.Floor(a / 3) + 1] = 0 Then
p = p + 1
px[p] = Math.Remainder(a, 3) + 1
py[p] = Math.Floor(a / 3) + 1
EndIf
EndFor
EndSub

Sub ShowBoard
GraphicsWindow.DrawLine(50, 150, 350, 150)
GraphicsWindow.DrawLine(50, 250, 350, 250)
GraphicsWindow.DrawLine(150, 50, 150, 350)
GraphicsWindow.DrawLine(250, 50, 250, 350)
For y = 3 To 1 Step -1
For x = 3 To 1 Step -1
If b[x][y] = 1 Then
GraphicsWindow.DrawEllipse(65 + (3 - x) * 100, 65 + (3 - y) * 100, 70, 70)
ElseIf b[x][y] = 2 Then
GraphicsWindow.DrawLine(65 + (3 - x) * 100, 65 + (3 - y) * 100, 135 + (3 - x) * 100, 135 + (3 - y) * 100)
GraphicsWindow.DrawLine(135 + (3 - x) * 100, 65 + (3 - y) * 100, 65 + (3 - x) * 100, 135 + (3 - y) * 100)
EndIf
EndFor
EndFor
EndSub

Sub ClearBoard
b[3][3] = 0
b[2][3] = 0
b[1][3] = 0
b[3][2] = 0
b[2][2] = 0
b[1][2] = 0
b[3][1] = 0
b[2][1] = 0
b[1][1] = 0
EndSub