wwwRong

curses-ox

Dec 19th, 2019
400
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.71 KB | None | 0 0
  1. local curses = require "curses"
  2. local stdscr = curses.initscr ()
  3. local O = {false,false,false,false,false,false,false,false,false}
  4. local X = {false,false,false,false,false,false,false,false,false}
  5. local win = {{1,2,3},
  6.             {4,5,6},
  7.             {7,8,9},
  8.             {1,4,7},
  9.             {2,5,8},
  10.             {3,6,9},
  11.             {1,5,9},
  12.             {3,5,7}}
  13. local rnd = math.random
  14. local max = math.max
  15. local add = table.insert
  16. local unpak = table.unpack
  17. local concat = table.concat
  18. local finished = false
  19.  
  20. local function all(t1, t2)
  21.   return t1[t2[1]] and t1[t2[2]] and t1[t2[3]]
  22. end
  23.  
  24. local function any(t1, t2)
  25.   local t = 0
  26.   t = t + (t1[t2[1]] and 1 or 0)
  27.   t = t + (t1[t2[2]] and 1 or 0)
  28.   t = t + (t1[t2[3]] and 1 or 0)
  29.   return t
  30. end
  31.  
  32. local function randomChoice(args)
  33.     return args[rnd(#args)]
  34. end
  35.  
  36. local function checkWin(P)
  37.   for _, w in pairs(win) do
  38.     if all(P, w) then
  39.       return true
  40.     end
  41.   end
  42.   return false
  43. end
  44.  
  45. local function displayOX()
  46.   local map = {}
  47.   for i = 1, 9, 3 do
  48.     map[i] = O[i] and "[O]" or (X[i] and "[X]" or "[_]")
  49.     map[i+1] = O[i+1] and "[O]" or (X[i+1] and "[X]" or "[_]")
  50.     map[i+2] = O[i+2] and "[O]" or (X[i+2] and "[X]" or "[_]")
  51.     stdscr:mvaddstr (((i-1)/3)+5, 30, map[i]..map[i+1]..map[i+2])
  52.   end
  53.   stdscr:mvaddstr (9, 20, "Choose position [1-9]: ")
  54. end
  55.  
  56. local function reset()
  57.   for i = 1, 9 do
  58.     O[i], X[i] = false, false
  59.   end
  60.   stdscr:mvaddstr(11,32,"     ")
  61. end
  62.  
  63. local function calSOX(o,x)
  64.   local SO, SX = 0, 0
  65.   local criticalMove = {}
  66.   for _, w in pairs(win) do
  67.     local cO = any(o,w)
  68.     local cX = any(x,w)
  69.     if cX == 0 then
  70.       SO = SO + cO
  71.       if cO == 2 then
  72.         stdscr:mvaddstr(8,27,"critical {".. concat(w,",").."}")
  73.         criticalMove = w
  74.       end
  75.     end
  76.     if cO == 0 then
  77.       SX = SX + cX
  78.     end
  79.   end
  80.   return SO, SX, criticalMove
  81. end
  82.  
  83. local function evalOX(o,x)
  84.   local SO, SX, criticalMove =calSOX(o,x)
  85.   return (1 + SX - SO), criticalMove
  86. end
  87.  
  88. local function ai()
  89.   local validMove = {true,true,true,true,true,true,true,true,true}
  90.   for i = 1, 9 do
  91.     validMove[i] = not (O[i] or X[i]) and validMove[i]
  92.   end
  93.   for _, w in pairs(win) do
  94.     local cX = any(X,w)
  95.     for _, v in pairs(w) do
  96.       if cX == 2 and validMove[v] then
  97.         return v
  98.       end
  99.     end
  100.   end
  101.   local V = {-100,-100,-100,-100,-100,-100,-100,-100,-100}
  102.   for i, v in ipairs(validMove) do
  103.     if v then
  104.       local tempX, criticalMove = {unpak(X)}, {}
  105.       tempX[i] = v
  106.       V[i], criticalMove = evalOX(O,tempX)
  107.       if #criticalMove > 0 then
  108.         for _, c in pairs(criticalMove) do
  109.           if validMove[c] then
  110.             return c
  111.           end
  112.         end
  113.       end
  114.     end
  115.   end
  116.   local maxV = max(unpak(V))
  117.   local imaxV = {}
  118.   for i, v in pairs(V) do
  119.     if v == maxV then
  120.       add(imaxV,i)
  121.     end
  122.   end
  123.   return randomChoice(imaxV)
  124. end
  125.  
  126. local function main ()
  127.   stdscr:clear ()
  128.   stdscr:box (curses.ACS_VLINE, curses.ACS_HLINE)
  129.   while true do
  130.     ::input_here::
  131.     local c = stdscr:getch () --print(c)
  132.     if c > 48 and c < 58 then
  133.       c = tonumber(string.char (c))
  134.       if O[c] or X[c] then
  135.         if not finished then
  136.           stdscr:mvaddstr (9, 20, "Bad move: choose position [1-9]: ")
  137.         end
  138.         goto input_here
  139.       else
  140.         stdscr:mvaddstr (9, 20, "                                 ")
  141.       end
  142.     elseif c == 13 then
  143.       if finished then
  144.         reset()
  145.         finished = false
  146.         displayOX()
  147.       else
  148.         stdscr:mvaddstr (9, 20, "Bad move: choose position [1-9]: ")
  149.       end
  150.       goto input_here
  151.     elseif c == 27 then
  152.       break
  153.     else
  154.       if not finished then
  155.         stdscr:mvaddstr (9, 20, "Bad move: choose position [1-9]: ")
  156.       end
  157.       goto input_here
  158.     end
  159.     stdscr:mvaddstr(8,27,"                 ")
  160.     O[c] = true
  161.     displayOX()
  162.     local msg = "     "
  163.     local d = true
  164.     for i = 1, 9 do
  165.       d = (O[i] or X[i]) and d
  166.     end
  167.     if d then
  168.       msg = "Draw"
  169.       finished = true
  170.     elseif checkWin(O) then
  171.       msg = "O win"
  172.       finished = true
  173.     else
  174.       X[ai()] = true
  175.       displayOX()
  176.       if checkWin(X) then
  177.         msg = "X win"
  178.         finished = true
  179.       end
  180.     end
  181.     stdscr:mvaddstr(11,32,msg)
  182.     stdscr:move(9,43)
  183.   end
  184.   curses.endwin ()
  185. end
  186.  
  187. local function err (err)
  188.   curses.endwin ()
  189.   print "Caught an error:"
  190.   print (debug.traceback (err, 2))
  191.   os.exit (2)
  192. end
  193.  
  194. xpcall (main, err)
Add Comment
Please, Sign In to add comment