sync on
sync rate 60
 
disable escapekey
 
color backdrop rgb(0,0,0)
global blackimage = 1
get image blackimage, 0, 0, screen width(), screen height(), 1
 
global greenimage = 2
create bitmap 1, 10, 10
box 0, 0, 10, 10, rgb(0, 255, 0), rgb(0, 255, 0), rgb(0, 255, 0), rgb(0, 255, 0)
get image greenimage, 0, 0, 10, 10
delete bitmap 1
 
global redimage = 3
create bitmap 1, 10, 10
box 0, 0, 10, 10, rgb(255, 0, 0), rgb(255, 0, 0), rgb(255, 0, 0), rgb(255, 0, 0)
get image redimage, 0, 0, 10, 10
delete bitmap 1
 
`board
type boardtype
   objid
   xpos
   ypos
   piece$
   player
endtype
 
dim board(3,3) as boardtype
 
overlap = 1
 
for x = 1 to 3
   for y = 1 to 3
      board(x,y).objid = freeid()
      make object cube board(x,y).objid, 10 + overlap
      ghost object on board(x,y).objid
      position object board(x,y).objid, x*10 - 20, y*10 - 20, 0
      board(x,y).xpos = x*10 - 20
      board(x,y).ypos = y*10 - 20
   next y
next x
`/board
 
`pieces
type piecetype
   objoid
   objxid
   type$
endtype
 
dim piece(3,3) as piecetype
 
osize = 6
xsize = 8
 
for x = 1 to 3
   for y = 1 to 3
      `O
      piece(x,y).objoid = freeid()
      make object sphere piece(x,y).objoid, osize
 
      set object ambient piece(x,y).objoid, 0
      exclude object on piece(x,y).objoid
 
      `X
      piece(x,y).objxid = freeid()
      make object box piece(x,y).objxid, xsize, xsize/5, xsize/5
 
      make mesh from object 1, piece(x,y).objxid
      zrotate object piece(x,y).objxid, 135
 
      add limb piece(x,y).objxid, 1, 1
      rotate limb piece(x,y).objxid, 1, 0, 0, 90  
      delete mesh 1
 
      set object ambient piece(x,y).objxid, 0
      exclude object on piece(x,y).objxid
   next y
next x
 
`/pieces
 
`camera
position camera 0, 0, -30
point camera 0,0,0
`/camera
 
`does the computer go first?
global computerfirst = 0
 
menuplace:
gosub menu
 
`if the computer gets to go first
if computerfirst = 1
   `place it's first piece in any one of the four corners
   select (rnd(3) + 1)
      case 1
         place_piece(1, 1, "X", 1)
      endcase
      case 2
         place_piece(1, 3, "X", 1)
      endcase
      case 3
         place_piece(3, 1, "X", 1)
      endcase
      case 4
         place_piece(3, 3, "X", 1)
      endcase
   endselect
endif
 
`records what the human player does
dim playermove(4) as string
global currentplayermove = 0
 
global placed = 0
global playertype$
global computertype$
 
if computerfirst = 1
   playertype$ = "O"
   computertype$ = "X"
else
   playertype$ = "X"
   computertype$ = "O"
endif
 
do
   center text screen width()/2, 30, "Place your " + playertype$
 
   if placed = 0
      gosub selectsquare
   endif
 
   gosub check_for_win
 
   if placed = 1
      gosub computerturn
   endif
 
   gosub check_for_win
 
   if escapekey() = 1
      gosub clearpieces
      goto menuplace
   endif
 
   sync   
loop
 
function place_piece(x as integer, y as integer, type$, computer)
   if type$ = "O"
      tempid = piece(x,y).objoid
   endif
   if type$ = "X"
      tempid = piece(x,y).objxid
   endif
 
   exclude object off tempid
 
   if computer = 1
      texture object tempid, redimage
      board(x,y).player = 1
   else
      texture object tempid, greenimage
      board(x,y).player = -10
   endif
 
   position object tempid, board(x,y).xpos, board(x,y).ypos, 0
 
   board(x,y).piece$ = type$
endfunction
 
 
`this function goes through the objects and finds the first object id that is not used
function freeid() 
   id = 0 
   i = 0 
   repeat
      inc i 
      if object exist(i) = 0 then id = i 
   until id > 0 `go until we find a "empty" i and assign it to id
   lastfreeobject = id
endfunction id
 
computerturn:
   computerplayed = 0
 
   `first check to see if we can win
 
   `horizontals
   for y = 1 to 3
      `if we have two on a row
      if (board(1,y).player + board(2,y).player + board(3,y).player) = 2
         for x = 1 to 3
            if board(x,y).piece$ = "" and computerplayed = 0
               place_piece(x, y, computertype$, 1)
               computerplayed = 1
            endif
         next x
      endif
   next y
   `verticals
   for x = 1 to 3
      `if we have two on a column
      if (board(x,1).player + board(x,2).player + board(x,3).player) = 2
         for y = 1 to 3
            if board(x,y).piece$ = "" and computerplayed = 0
               place_piece(x, y, computertype$, 1)
               computerplayed = 1
            endif
         next y
      endif
   next x
   `diagonals
   if (board(1,1).player + board(2,2).player + board(3,3).player) = 2
      for i = 1 to 3
         if board(i,i).piece$ = "" and computerplayed = 0
            place_piece(i, i, computertype$, 1)
            computerplayed = 1
         endif
      next i
   endif
   if (board(1,3).player + board(2,2).player + board(3,1).player) = 2
      if board(1,3).piece$ = "" and computerplayed = 0
         place_piece(1, 3, computertype$, 1)
         computerplayed = 1
      endif
      if board(3,1).piece$ = "" and computerplayed = 0
         place_piece(3, 1, computertype$, 1)
         computerplayed = 1
      endif
      if board(2,2).piece$ = "" and computerplayed = 0
         place_piece(2, 2, computertype$, 1)
         computerplayed = 1
      endif
   endif
 
   `if we haven't moved yet, see if we need to block the human player
   `horizontals
   for y = 1 to 3
      if board(1,y).player + board(2,y).player + board(3,y).player = -20
         for x = 1 to 3
            if board(x,y).piece$ = "" and computerplayed = 0
               place_piece(x, y, computertype$, 1)
               computerplayed = 1
            endif
         next x
      endif
   next y
   `verticals
   for x = 1 to 3
      if board(x,1).player + board(x,2).player + board(x,3).player = -20
         for y = 1 to 3
            if board(x,y).piece$ = "" and computerplayed = 0
               place_piece(x, y, computertype$, 1)
               computerplayed = 1
            endif
         next y
      endif
   next x
 
   `diagonals
   if (board(1,1).player + board(2,2).player + board(3,3).player) = -20
      for i = 1 to 3
         if board(i,i).piece$ = "" and computerplayed = 0
            place_piece(i, i, computertype$, 1)
            computerplayed = 1
         endif
      next i
   endif
   if (board(1,3).player + board(2,2).player + board(3,1).player) = -20
      if board(1,3).piece$ = "" and computerplayed = 0
         place_piece(1, 3, computertype$, 1)
         computerplayed = 1
      endif
      if board(3,1).piece$ = "" and computerplayed = 0
         place_piece(3, 1, computertype$, 1)
         computerplayed = 1
      endif
      if board(2,2).piece$ = "" and computerplayed = 0
         place_piece(2, 2, computertype$, 1)
         computerplayed = 1
      endif
   endif
 
 
   `now if we haven't moved we need to use some strategy
   if computerplayed = 0
      `if the computer is the X
      if computerfirst = 1
         if playermove(0) = "Corner"
            if currentplayermove = 1 or currentplayermove = 2
               `play a open corner square
               if board(1,1).piece$ = ""
                  place_piece(1, 1, computertype$, 1)
                  computerplayed = 1
               else
                  if board(1,3).piece$ = ""
                     place_piece(1, 3, computertype$, 1)
                     computerplayed = 1
                  else
                     if board(3,3).piece$ = ""
                        place_piece(3, 3, computertype$, 1)
                        computerplayed = 1
                     else
                        if board(3,1).piece$ = ""
                           place_piece(3, 1, computertype$, 1)
                           computerplayed = 1
                        endif
                     endif
                  endif
               endif
               `/play a open corner square
            endif
         endif
 
         if playermove(0) = "Edge"
            if currentplayermove = 1
               `play the center
               place_piece(2, 2, computertype$, 1)
               computerplayed = 1
            endif
            if currentplayermove = 2
               `play a corner not bordered by a human edge piece
               if board(1,1).piece$ = "" and board(1,2).piece$ <> playertype$ and board(2,1).piece$ <> playertype$
                  place_piece(1, 1, computertype$, 1)
                  computerplayed = 1
               else
                  if board(3,1).piece$ = "" and board(2,1).piece$ <> playertype$ and board(3,2).piece$ <> playertype$
                     place_piece(3, 1, computertype$, 1)
                     computerplayed = 1
                  else
                     if board(3,3).piece$ = "" and board(2,3).piece$ <> playertype$ and board(3,2).piece$ <> playertype$
                        place_piece(3, 3, computertype$, 1)
                        computerplayed = 1
                     else
                        if board(1,3).piece$ = "" and board(1,2).piece$ <> playertype$ and board(2,3).piece$ <> playertype$
                           place_piece(1, 3, computertype$, 1)
                           computerplayed = 1
                        endif
                     endif
                  endif
               endif
            endif
         endif
         if playermove(0) = "Center"
            if currentplayermove = 1
               `play the opposite corner from our original play
               if board(1,1).player = 1
                  place_piece(3, 3, computertype$, 1)
                  computerplayed = 1
               endif
               if board(1,3).player = 1
                  place_piece(3, 1, computertype$, 1)
                  computerplayed = 1
               endif
               if board(3,1).player = 1
                  place_piece(1, 3, computertype$, 1)
                  computerplayed = 1
               endif
               if board(3,3).player = 1
                  place_piece(1, 1, computertype$, 1)
                  computerplayed = 1
               endif
            endif      
         endif
 
      endif
 
 
      `if the computer is the O
      if computerfirst = 0
         if playermove(0) <> "Center" `the human player played somewhere besides the center
            if currentplayermove = 1
               `play the center
               if board(2,2).piece$ = ""
                  place_piece(2, 2, computertype$, 1)
                  computerplayed = 1
               endif
               `/play the center
            endif
 
            if currentplayermove = 2
               if (playermove(0) = "Corner" and playermove(1) = "Edge") or (playermove(1) = "Corner" and playermove(0) = "Edge")
                  if board(1,1).piece$ = playertype$
                     place_piece(3, 3, computertype$, 1)
                     computerplayed = 1
                  endif
                  if board(1,3).piece$ = playertype$
                     place_piece(3, 1, computertype$, 1)
                     computerplayed = 1
                  endif
                  if board(3,1).piece$ = playertype$
                     place_piece(1, 3, computertype$, 1)
                     computerplayed = 1
                  endif
                  if board(3,3).piece$ = playertype$
                     place_piece(1, 1, computertype$, 1)
                     computerplayed = 1
                  endif
               endif
 
               if playermove(0) = "Corner" and playermove(1) = "Corner"
                  select (rnd(3)+1)
                     case 1
                        place_piece(1, 2, computertype$, 1)
                        computerplayed = 1
                     endcase
                     case 2
                        place_piece(2, 1, computertype$, 1)
                        computerplayed = 1
                     endcase
                     case 3
                        place_piece(3, 2, computertype$, 1)
                        computerplayed = 1
                     endcase
                     case 4
                        place_piece(2, 3, computertype$, 1)
                        computerplayed = 1
                     endcase  
                  endselect
               endif
 
               if playermove(0) = "Edge" and playermove(1) = "Edge"
                  if board(1,1).piece$ = "" and board(2,1).piece$ = playertype$ and board(1,2).piece$ = playertype$
                     place_piece(1, 1, computertype$, 1)
                     computerplayed = 1
                  endif
                  if board(3,1).piece$ = "" and board(2,1).piece$ = playertype$ and board(3,2).piece$ = playertype$
                     place_piece(3, 1, computertype$, 1)
                     computerplayed = 1
                  endif
                  if board(3,3).piece$ = "" and board(2,3).piece$ = playertype$ and board(3,2).piece$ = playertype$
                     place_piece(3, 3, computertype$, 1)
                     computerplayed = 1
                  endif
                  if board(1,3).piece$ = "" and board(1,2).piece$ = playertype$ and board(2,3).piece$ = playertype$
                     place_piece(1, 3, computertype$, 1)
                     computerplayed = 1
                  endif
 
                  if board(1,2).piece$ = playertype$ and board(3,2).piece$ = playertype$
                     if rnd(1)
                        place_piece(2, 3, computertype$, 1)
                        computerplayed = 1
                     else
                        place_piece(2, 1, computertype$, 1)
                        computerplayed = 1
                     endif
                  endif
                  if board(2,3).piece$ = playertype$ and board(2,1).piece$ = playertype$
                     if rnd(1)
                        place_piece(1, 2, computertype$, 1)
                        computerplayed = 1
                     else
                        place_piece(3, 2, computertype$, 1)
                        computerplayed = 1
                     endif
                  endif
               endif
            endif
 
            if currentplayermove = 3
               if playermove(0) = "Edge" and playermove(1) = "Edge"
                  if board(1,2).piece$ = playertype$ and board(3,2).piece$ = playertype$
                     if board(2, 3).piece$ = computertype$
                        if rnd(1)
                           place_piece(1, 3, computertype$, 1)
                           computerplayed = 1
                        else
                           place_piece(3, 3, computertype$, 1)
                           computerplayed = 1
                        endif
                     endif
                     if board(2, 1).piece$ = computertype$
                        if rnd(1)
                           place_piece(1, 1, computertype$, 1)
                           computerplayed = 1
                        else
                           place_piece(3, 1, computertype$, 1)
                           computerplayed = 1
                        endif
                     endif
                  endif
                  if board(2,3).piece$ = playertype$ and board(2,1).piece$ = playertype$
                     if board(1, 2).piece$ = computertype$
                        if rnd(1)
                           place_piece(1, 3, computertype$, 1)
                           computerplayed = 1
                        else
                           place_piece(1, 1, computertype$, 1)
                           computerplayed = 1
                        endif
                     endif
                     if board(3, 2).piece$ = computertype$
                        if rnd(1)
                           place_piece(3, 1, computertype$, 1)
                           computerplayed = 1
                        else
                           place_piece(3, 3, computertype$, 1)
                           computerplayed = 1
                        endif
                     endif
                  endif
               endif
            endif
         else `the human player played to the center
            if currentplayermove = 1
               `play a random corner square
               select (rnd(3) + 1)
                  case 1
                     place_piece(1, 1, computertype$, 1)
                     computerplayed = 1
                  endcase
                  case 2
                     place_piece(1, 3, computertype$, 1)
                     computerplayed = 1
                  endcase
                  case 3
                     place_piece(3, 1, computertype$, 1)
                     computerplayed = 1
                  endcase
                  case 4
                     place_piece(3, 3, computertype$, 1)
                     computerplayed = 1
                  endcase
               endselect
               `/play a open corner square
            endif
 
 
            if currentplayermove = 2
               if playermove(1) = "Corner"
                  `play a open corner square
                  if board(1,1).piece$ = ""
                     place_piece(1, 1, computertype$, 1)
                     computerplayed = 1
                  else
                     if board(1,3).piece$ = ""
                        place_piece(1, 3, computertype$, 1)
                        computerplayed = 1
                     else
                        if board(3,3).piece$ = ""
                           place_piece(3, 3, computertype$, 1)
                           computerplayed = 1
                        else
                           if board(3,1).piece$ = ""
                              place_piece(3, 1, computertype$, 1)
                              computerplayed = 1
                           endif
                        endif
                     endif
                  endif
                  `/play a open corner square
               endif
            endif
 
         endif
      endif
   endif
 
   `if there is no possible strategy left, just pick a random square man!
   if computerplayed = 0
      found = 0
      repeat
         x = rnd(2) + 1 ` a 1 to 3 range
         y = rnd(2) + 1
         if board(x,y).piece$ = ""
            place_piece(x, y, computertype$, 1)
            computerplayed = 1
            found = 1
         endif
      until found = 1
   endif
 
   `reset this so the player can go again
   placed = 0
return
 
selectsquare:
   tempid = pick object(mousex(), mousey(), 1, 9)
 
   for i = 1 to 9
      ghost object on i
   next i
 
   if tempid > 0
      if tempid < 4
         x = 1
         y = tempid
         if board(x, y).piece$ = ""
            ghost object off tempid
            if mouseclick() = 1
               place_piece(x, y, playertype$, 0)
               placed = 1
               ghost object on tempid
            endif
         endif
      endif
 
      if tempid > 3 and tempid < 7
         x = 2
         y = tempid - 3
         if board(x, y).piece$ = ""
            ghost object off tempid
            if mouseclick() = 1
               place_piece(x, y, playertype$, 0)
               placed = 1
               ghost object on tempid
            endif
         endif
      endif
 
      if tempid > 6
         x = 3
         y = tempid - 6
         if board(x, y).piece$ = ""
            ghost object off tempid
            if mouseclick() = 1
               place_piece(x, y, playertype$, 0)
               placed = 1
               ghost object on tempid
            endif
         endif
      endif
 
      if placed = 1
         `if computerfirst = 1
            `player is the Os
            `if currentplayermove = 0
               if (x = 1 and y = 1) or (x = 1 and y = 3) or (x = 3 and y = 1) or (x = 3 and y = 3)
                  playermove(currentplayermove) = "Corner"
               endif
               if (x = 1 and y = 2) or (x = 2 and y = 1) or (x = 3 and y = 2) or (x = 2 and y = 3)
                  playermove(currentplayermove) = "Edge"
               endif
               if (x = 2 and y = 2)
                  playermove(currentplayermove) = "Center"
               endif
            `endif
 
         `else
            `player is the Xs
         `endif
 
         inc currentplayermove
      endif
 
   endif
return
 
check_for_win:
   `horizontals
   for y = 1 to 3
      if board(1, y).piece$ = playertype$ and board(2, y).piece$ = playertype$ and board(3, y).piece$ = playertype$
         humanwin = 1
      endif
      if board(1, y).piece$ = computertype$ and board(2, y).piece$ = computertype$ and board(3, y).piece$ = computertype$
         computerwin = 1
      endif
   next y
   `verticals
   for x = 1 to 3
      if board(x, 1).piece$ = playertype$ and board(x, 2).piece$ = playertype$ and board(x, 3).piece$ = playertype$
         humanwin = 1
      endif
      if board(x, 1).piece$ = computertype$ and board(x, 2).piece$ = computertype$ and board(x, 3).piece$ = computertype$
         computerwin = 1
      endif
   next x
   `diagonals
   if board(1, 1).piece$ = playertype$ and board(2, 2).piece$ = playertype$ and board(3, 3).piece$ = playertype$
      humanwin = 1
   endif
   if board(1, 1).piece$ = computertype$ and board(2, 2).piece$ = computertype$ and board(3, 3).piece$ = computertype$
      computerwin = 1
   endif
   if board(1, 3).piece$ = playertype$ and board(2, 2).piece$ = playertype$ and board(3, 1).piece$ = playertype$
      humanwin = 1
   endif
   if board(1, 3).piece$ = computertype$ and board(2, 2).piece$ = computertype$ and board(3, 1).piece$ = computertype$
      computerwin = 1
   endif
 
   if humanwin = 1
      `the human won!
      `what! impossible! :P
      sync `this sync is nessecary to make the last piece played shown
      center text screen width()/2, screen height()/2, "You win!"
      sync
      wait key
      gosub clearpieces
      goto menuplace
   endif
 
   if computerwin = 1
      `the computer won!
      sync `this sync is nessecary to make the last piece played shown
      center text screen width()/2, screen height()/2, "The computer won!"
      sync
      wait key
      gosub clearpieces
      goto menuplace
   endif
 
 
   `Check for a tie!
   empty = 0
   for x = 1 to 3
      for y = 1 to 3
         if board(x, y).piece$ = "" then empty = 1   
      next y
   next x
   if empty = 0
      `ze cat got the game
      sync `this sync is nessecary to make the last piece played shown
      center text screen width()/2, screen height()/2, "The cat got the game..."
      sync
      wait key
      gosub clearpieces
      goto menuplace
   endif
return
 
clearpieces:
   for x = 1 to 3
      for y = 1 to 3
         board(x,y).piece$ = ""
         board(x,y).player = 0
         exclude object on piece(x,y).objoid
         exclude object on piece(x,y).objxid
      next y
   next x
 
   humanwin = 0
   computerwin = 0
return 
 
menu:
   clear entry buffer
 
   if escapekey() = 1 then escapehold = 1
   do
      cls
      paste image blackimage, 0, 0
      center text screen width()/2, screen height()/2, "Which do you want to play as? X or O? (X goes first)"
      center text screen width()/2, screen height()/2 + 20, entry$()
 
      if right$(entry$(), 1) = "O" or right$(entry$(), 1) = "o"  or right$(entry$(), 1) = "0" 
         computerfirst = 1
         exit
      else
         if right$(entry$(), 1) = "X" or right$(entry$(), 1) = "x"
            computerfirst = 0
            exit
         else
            if right$(entry$(), 1) <> "" and escapekey() = 0
               cls
               paste image blackimage, 0, 0
               center text screen width()/2, screen height()/2, "Please enter either X or O"
               sync
               wait 1000
               clear entry buffer
               paste image blackimage, 0, 0
            endif
         endif
      endif
 
      if escapekey() = 1 and escapehold = 0 then end
 
      if escapekey() = 0 then escapehold = 0
 
      sync
   loop
return