rm(list=ls())
library(RColorBrewer)

########################
# tic.tac.toe function #
########################

tic.tac.toe <- function(name="Name", mode=0, type=0){
  
  place.na <<- matrix(1:9, 3, 3)
  value <<- matrix(-3, 3, 3)
  k <<- 1 ; r <<- 0
  
  #########################
  # Plot Tic-Tac-Toe form #
  #########################
  
  image(1:3, 1:3, matrix(sample(9), 3, 3), asp=c(1, 1), 
        xaxt="n", yaxt="n", xlab="", ylab="", frame=F, col=brewer.pal(9, "Set3"))
  segments(c(0.5,0.5,1.5,2.5), c(2.5,1.5,0.5,0.5), 
           c(3.5,3.5,1.5,2.5), c(2.5,1.5,3.5,3.5), lwd=8, col=gray(0.3))
  segments(c(0.5,0.5,0.5,3.5), c(0.52,3.47,0.5,0.5), 
           c(3.5,3.5,0.5,3.5), c(0.52,3.47,3.5,3.5), lwd=8, col=gray(0.3))
  
  ###########
  # 1P & 2P #
  ###########
  
  if(mode==0) title(list(paste(name, "'s Tic-Tac-Toe !"), cex=2), 
                    "2P : Human v.s. Human", font.sub=2, cex.sub=2)
  if(mode==1) title(list(paste(name, "'s Tic-Tac-Toe !"), cex=2), 
                    "1P : Human v.s. AI (Easy)", font.sub=2, cex.sub=2)
  if(mode==2) title(list(paste(name, "'s Tic-Tac-Toe !"), cex=2), 
                    "1P : Human v.s. AI (Hard)", font.sub=2, cex.sub=2)
  
  #########
  # O & X #
  #########
  
  if(type==0){symbol <- "O" ; symbol.op <- "X"}
  if(type==1){symbol <- "X" ; symbol.op <- "O"}
  out <- list(name=name, mode=mode, type=type, symbol=symbol, symbol.op=symbol.op)
}

##########################
# identification of line #
##########################

line <- function(){
  
  for(i in 1:3){
    total.1 <- 0 ; total.2 <- 0
    for(j in 1:3){
      total.1 <- total.1 + value[i, j]
      total.2 <- total.2 + value[j, i]
    }
    if(total.1==0 | total.2==0 | total.1==3 | total.2==3){
      break
    }
  }
  total.3 <- value[1, 1] + value[2, 2] + value[3, 3]
  total.4 <- value[1, 3] + value[2, 2] + value[3, 1]
  
  if(total.1==0 | total.2==0 | total.3==0 | total.4==0 | total.1==3 | total.2==3 | total.3==3 | total.4==3){
    place.na[!is.na(place.na)] <<- NA
    if(total.1==0 | total.2==0 | total.3==0 | total.4==0){
      title(sub=list("You Win ! Game Over !", col="red", font=2, cex=2.5), line=2)
    }else{
      title(sub=list("You Are a Loser !", col="darkblue", font=2, cex=2.5), line=2)
    }
  }
  
  if(all(is.na(place.na))){
    if(total.1==0 | total.2==0 | total.3==0 | total.4==0 | total.1==3 | total.2==3 | total.3==3 | total.4==3){
      if(total.1==0 | total.2==0 | total.3==0 | total.4==0){
        title(sub=list("You Win ! Game Over !", col="orange", font=2, cex=2.5), line=2)
      }else{
        title(sub=list("You Are a Loser !", col="darkblue", font=2, cex=2.5), line=2)
      }
    }else{
      title(sub=list("Draw ! Please try again !", col="blue", font=2, cex=2.5), line=2)
    }
  }
}

#############
# AI attack #
#############

attack <- function(){
  ### Identify rows and columns
  for(i in 1:3){
    total.1 <- 0 ; total.2 <- 0
    for(j in 1:3){
      total.1 <- total.1 + value[i, j]
      total.2 <- total.2 + value[j, i]
    }
    if(total.1==-1 | total.2==-1){
      break
    }
  }
  total.3 <- value[1, 1] + value[2, 2] + value[3, 3]
  total.4 <- value[1, 3] + value[2, 2] + value[3, 1]
  
  if(total.1==-1){
    text(i, which(value[i,]!=1), symbol.op, cex=6, font=2)
    place.na[i, which(value[i,]!=1)] <<- NA
    value[i, which(value[i,]!=1)] <<- 1
  }else if(total.2==-1){
    text(which(value[,i]!=1), i, symbol.op, cex=6, font=2)
    place.na[which(value[,i]!=1), i] <<- NA
    value[which(value[,i]!=1), i] <<- 1
  }else if(total.3==-1){
    r.1 <- which(c(value[1, 1], value[2, 2], value[3, 3])!=1)
    text(r.1, r.1, symbol.op, cex=6, font=2)
    place.na[r.1, r.1] <<- NA
    value[r.1, r.1] <<- 1
  }else if(total.4==-1){
    r.2 <- which(c(value[1, 3], value[2, 2], value[3, 1])!=1)
    text(r.2, -r.2+4, symbol.op, cex=6, font=2)
    place.na[r.2, -r.2+4] <<- NA
    value[r.2, -r.2+4] <<- 1
  }
}

#############
# AI defend #
#############

defend <- function(){
  ### Identify rows and columns
  for(i in 1:3){
    total.1 <- 0 ; total.2 <- 0
    for(j in 1:3){
      total.1 <- total.1 + value[i, j]
      total.2 <- total.2 + value[j, i]
    }
    if(total.1==-3 | total.2==-3){
      break
    }
  }
  total.3 <- value[1, 1] + value[2, 2] + value[3, 3]
  total.4 <- value[1, 3] + value[2, 2] + value[3, 1]
  
  if(total.1==-3){
    text(i, which(value[i,]!=0), symbol.op, cex=6, font=2)
    place.na[i, which(value[i,]!=0)] <<- NA
    value[i, which(value[i,]!=0)] <<- 1
  }else if(total.2==-3){
    text(which(value[,i]!=0), i, symbol.op, cex=6, font=2)
    place.na[which(value[,i]!=0), i] <<- NA
    value[which(value[,i]!=0), i] <<- 1
  }else if(total.3==-3){
    r.1 <- which(c(value[1, 1], value[2, 2], value[3, 3])!=0)
    text(r.1, r.1, symbol.op, cex=6, font=2)
    place.na[r.1, r.1] <<- NA
    value[r.1, r.1] <<- 1
  }else if(total.4==-3){
    r.2 <- which(c(value[1, 3], value[2, 2], value[3, 1])!=0)
    text(r.2, -r.2+4, symbol.op, cex=6, font=2)
    place.na[r.2, -r.2+4] <<- NA
    value[r.2, -r.2+4] <<- 1
  }else{
    rn <- sample(place.na[!is.na(place.na)], 1)
    text(rn-3*rn%/%3.5, rn%/%3.5+1, symbol.op, cex=6, font=2)
    place.na[rn-3*rn%/%3.5, rn%/%3.5+1] <<- NA
    value[rn-3*rn%/%3.5, rn%/%3.5+1] <<- 1
  }
}

################
# aim function #
################

aim <- function(x, y, tic.tac.toe=ttt){
  
  mode <- tic.tac.toe$mode
  symbol <<- tic.tac.toe$symbol
  symbol.op <<- tic.tac.toe$symbol.op
  x <<- x ; y <<- y
  
  ################
  # mode=0 -> 2P #
  ################
  
  if(mode==0){
    turn <- rep(c(0, 1), length.out=9)
    if(is.na(place.na[x, y])){
      cat("This square had been chosen !")
    }else{
      
      if(turn[k]==0){
        text(x, y, symbol, cex=6, font=2)
        place.na[x, y] <<- NA
        value[x, y] <<- 0
      }
      if(turn[k]==1){
        text(x, y, symbol.op, cex=6, font=2)
        place.na[x, y] <<- NA
        value[x, y] <<- 1
      }
      k <<- k + 1
    }
  }
  
  ######################
  # mode=1 -> AI(easy) #
  ######################
  
  if(mode==1){
    if(is.na(place.na[x, y])){
      cat("This square had been chosen !")
    }else{
      text(x, y, symbol, cex=6, font=2)
        place.na[x, y] <<- NA
        value[x, y] <<- 0
        line()
        
        for(i in 1:3){
          total.1 <- 0 ; total.2 <- 0
          for(j in 1:3){
            total.1 <- total.1 + value[i, j]
            total.2 <- total.2 + value[j, i]
          }
          if(total.1==-1 | total.2==-1){
            break
          }
        }
        total.3 <- value[1, 1] + value[2, 2] + value[3, 3]
        total.4 <- value[1, 3] + value[2, 2] + value[3, 1]
        
        if(all(is.na(place.na))){
          line()
        }else if(total.1==-1 | total.2==-1 | total.3==-1 | total.4==-1){
          attack()
        }else{
          defend()
        }
    }
  }
  
  
  ######################
  # mode=2 -> AI(hard) #
  ######################
  
  if(mode==2){
    
    if(is.na(place.na[x, y])){
      cat("This square had been chosen !")
    }else{
      
      #################
      # AI First turn #
      #################
      
      if(sum(is.na(place.na))==0){
        
        text(x, y, symbol, cex=6, font=2)
        place.na[x, y] <<- NA
        value[x, y] <<- 0
        
        if(is.na(place.na[2, 2])==F){
          text(2, 2, symbol.op, cex=6, font=2)
          place.na[2, 2] <<- NA
          value[2, 2] <<- 1
        }else{
          corner.1 <- sample(c(1, 3), 1) ; corner.2 <- sample(c(1, 3), 1)
          text(corner.1, corner.2, symbol.op, cex=6, font=2)
          place.na[corner.1, corner.2] <<- NA
          value[corner.1, corner.2] <<- 1
        }
        
        ##################
        # AI Second turn #
        ##################
        
      }else if(sum(is.na(place.na))==2){
        text(x, y, symbol, cex=6, font=2)
        place.na[x, y] <<- NA
        value[x, y] <<- 0
        
        for(i in 1:3){
          total.1 <- 0 ; total.2 <- 0
          for(j in 1:3){
            total.1 <- total.1 + value[i, j]
            total.2 <- total.2 + value[j, i]
          }
          if(total.1==-3 | total.2==-3){
            break
          }
        }
        total.3 <- value[1, 1] + value[2, 2] + value[3, 3]
        total.4 <- value[1, 3] + value[2, 2] + value[3, 1]
        
        if(total.1==-3 | total.2==-3 | total.3==-3 | total.4==-3){
          defend()
        }else{
          total.1 <- value[2, 1] + value[2, 2] + value[2, 3]
          total.2 <- value[1, 2] + value[2, 2] + value[3, 2]
          total.3 <- value[1, 1] + value[2, 2] + value[3, 3]
          total.4 <- value[1, 3] + value[2, 2] + value[3, 1]
          if(total.1==1 | total.2==1 | total.3==1 | total.4==1){
            if((value[2, 2]==1 & total.3==1) | (value[2, 2]==1 & total.4==1)){
              vector.side <- c(place.na[2, 1], place.na[1, 2], place.na[3, 2], place.na[2, 3])
              rn <- sample(vector.side[!is.na(vector.side)], 1)
              text(rn-3*rn%/%3.5, rn%/%3.5+1, symbol.op, cex=6, font=2)
              place.na[rn-3*rn%/%3.5, rn%/%3.5+1] <<- NA
              value[rn-3*rn%/%3.5, rn%/%3.5+1] <<- 1
            }else{
              matrix.cor <- place.na[c(1, 3), c(1, 3)]
              rn <- sample(matrix.cor[!is.na(matrix.cor)], 1)
              text(rn-3*rn%/%3.5, rn%/%3.5+1, symbol.op, cex=6, font=2)
              place.na[rn-3*rn%/%3.5, rn%/%3.5+1] <<- NA
              value[rn-3*rn%/%3.5, rn%/%3.5+1] <<- 1
            }
          }else{
            if((x==1 & y==2) | (x==3 & y==2)){
              rn <- sample(c(1, 3), 1)
              text(x, rn, symbol.op, cex=6, font=2)
              place.na[x, rn] <<- NA
              value[x, rn] <<- 1
            }else if((x==2 & y==3) | (x==2 & y==1)){
              rn <- sample(c(1, 3), 1)
              text(rn, y, symbol.op, cex=6, font=2)
              place.na[rn, y] <<- NA
              value[rn, y] <<- 1
            }else if((x==1 & y==1) | (x==1 & y==3) | (x==3 & y==1) | (x==3 & y==3)){
              text(-x+4, -y+4, symbol.op, cex=6, font=2)
              place.na[-x+4, -y+4] <<- NA
              value[-x+4, -y+4] <<- 1
            }
          }
        }
        
        #################
        # AI Other turn #
        #################
        
      }else{
        text(x, y, symbol, cex=6, font=2)
        place.na[x, y] <<- NA
        value[x, y] <<- 0
        line()
        
        for(i in 1:3){
          total.1 <- 0 ; total.2 <- 0
          for(j in 1:3){
            total.1 <- total.1 + value[i, j]
            total.2 <- total.2 + value[j, i]
          }
          if(total.1==-1 | total.2==-1){
            break
          }
        }
        total.3 <- value[1, 1] + value[2, 2] + value[3, 3]
        total.4 <- value[1, 3] + value[2, 2] + value[3, 1]
        
        if(all(is.na(place.na))){
          line()
        }else if(total.1==-1 | total.2==-1 | total.3==-1 | total.4==-1){
          attack()
        }else{
          defend()
        }
      }
    }
  }
  line()
}

##################
# click function #
##################

click <- function(tic.tac.toe=ttt){
  name <- tic.tac.toe$name
  mode <- tic.tac.toe$mode
  type <- tic.tac.toe$type
  
  while(length(place.na)==9){
    mouse.at <- locator(n = 1, type = "n") 
    #cat(mouse.at$x,"\t",  mouse.at$y, "\n")
    x.at <- round(mouse.at$x)
    y.at <- round(mouse.at$y)
    #cat(x.at,"\t",  y.at, "\n")
    if(all(is.na(place.na))){
      ttt <<- tic.tac.toe(name, mode, type)
    }else if(x.at > 3.5 | x.at < 0.5 | y.at > 3.5 | y.at < 0.5){
      r <<- r + 1
      title(sub=list("Click outside:Quit / inside:Restart", col="deeppink", font=2, cex=2), line=2)
      if(r==2){
        dev.off()
        break
      }
    }else{
      if(r==1){
        ttt <<- tic.tac.toe(name, mode, type)
      }else{
        aim(x.at, y.at)
      }
    }
  }
}

#################
# Start Game !! #
#################

start <- function(name="Name", mode=0, type=0){
  x11()
  ttt <<- tic.tac.toe(name, mode, type)
  click()
}

# start("Darren", mode=2, type=1)