Advertisement
partyboy1a

DenkiBlocks-WIP1.lua

Jan 4th, 2016
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.89 KB | None | 0 0
  1. -- Denki Blocks! Solver WIP1
  2. --
  3. -- UNFINISHED, not usable
  4. --
  5. dofile("SAT-solver-framework.lua")
  6. USE_MINISAT = true
  7.  
  8. --[[
  9. ROWS = 16
  10. COLUMNS = 16
  11. BITS = 8   -- math.ceil( ln(ROWS*COLS) / ln(2) )
  12.  
  13. LevelLayout = {
  14. "________________",
  15. "__rr_yyyyyy_bb__",
  16. "__rr________bb__",
  17. "XXXXXXX__XXXXXXX",
  18. "______X__X______",
  19. "__yy__X__X__yy__",
  20. "__yy__X__X__yy__",
  21. "______X__X______",
  22. "_bbbb_X__X_rrrr_",
  23. "______X__X______",
  24. "__yy__X__X__yy__",
  25. "__yy__X__X__yy__",
  26. "______X__X______",
  27. "XX__XXX__XXX__XX",
  28. "________________",
  29. "________________"
  30. }
  31.  
  32. ColorsToConnect = {
  33. r = {number=1,r=9,c=12}, y = {number=2,r=2,c=9}, b = {number=3,r=9,c=3}}
  34. OtherColors = {}
  35. MaximumTurns = 144
  36.  
  37. --]]
  38. ROWS = 4
  39. COLUMNS = 4
  40. BITS = 4
  41. LevelLayout = {
  42. "r__r",
  43. "_y_y",
  44. "___b",
  45. "rXb_"
  46. }
  47. ColorsToConnect = {
  48. r = {number=1,r=1,c=1}, y={number=2,r=2,c=2}, b={number=3,r=3,c=4}}
  49. OtherColors = {}
  50. MaximumTurns = 4
  51.  
  52. TotalColors = 0
  53. for _,_ in pairs(ColorsToConnect) do TotalColors = TotalColors + 1 end
  54. for _,_ in pairs(OtherColors) do TotalColors = TotalColors + 1 end
  55.  
  56. function CheckLayout()
  57.     local found = {}
  58.     for r = 1, ROWS do
  59.         assert(type(LevelLayout[r]) == "string", "type mismatch!")
  60.         assert(string.len(LevelLayout[r]) == COLUMNS, "string does not have the right length!")
  61.         for c = 1, COLUMNS do
  62.             local s = string.sub(LevelLayout[r],c,c)
  63.             assert(
  64.                 s == "_"
  65.                 or s == "X"
  66.                 or ColorsToConnect[ s ] ~= nil
  67.                 or OtherColors[ s ] ~= nil,
  68.                 "LevelLayout["..r.."]["..c.."] unknown color "..s.."!")
  69.             found[s] = true
  70.         end
  71.     end
  72.     local foundnum = {}
  73.     for key,val in pairs(ColorsToConnect) do
  74.         assert(found[key], "ColorsToConnect includes color "..key.." which is not in the puzzle!")
  75.         foundnum[val.number] = true
  76.     end
  77.     for i = 1, #ColorsToConnect do
  78.         assert(foundnum[i], "color number "..i.." should exist!")
  79.     end
  80.    
  81.     for key,val in pairs(OtherColors) do
  82.         assert(found[key], "OtherColors includes color "..key.." which is not in the puzzle!")
  83.         foundnum[val.number] = true
  84.     end
  85.     for i = 1, #OtherColors do
  86.         assert(foundnum[#ColorsToConnect + i], "color number "..(#ColorsToConnect+i).." should exist!")
  87.     end
  88. end
  89.  
  90. function CreateCNF()
  91.     CheckLayout()
  92.     assert(TotalColors == 3, "fail!")
  93.     --A : Before rotation is done
  94.     --R : which rotation should be done? < --- THIS IS THE ONLY UNRESTRICTED VARIABLE!! ALL INPUT IS DONE HERE!!
  95.     --B : After rotation is done
  96.    
  97.     --[[
  98.     A[1] : initial state
  99.    
  100.           R[1]        move!       R[2]        move!
  101.     A[1] -----> B[1] -----> A[2] -----> B[2] ------> ...
  102.    
  103.     A[n] : state after n-1 finished moves.
  104.     B[n] : check the winning condition in turn n-1, prepare the move
  105.  
  106.     --]]
  107.     NewVar("A", {
  108.         MaximumTurns + 1,
  109.         ROWS,
  110.         COLUMNS,
  111.         -- which color? zero? free? unmovable?
  112.            TotalColors  + 1   + 1   + 1})
  113.    
  114.     IS_ZERO = TotalColors + 1
  115.     IS_FREE = TotalColors + 2
  116.     IS_UNMOVABLE = TotalColors + 3
  117.     assert(#Var.A[1][1][1] == 6, "FAIL"..#Var.A[1][1][1])
  118.     print("parsing layout...")
  119.     -- Let's parse the layout!
  120.     for r = 1, ROWS do for c = 1, COLUMNS do
  121.         local s = string.sub(LevelLayout[r],c,c)
  122.         if s == "_" then
  123.             for entry = 1, #Var.A[1][r][c] do
  124.                 AddSimpleClause{Var.A[1][r][c][entry], entry == IS_FREE}
  125.             end
  126.         elseif s == "X" then
  127.             for entry = 1, #Var.A[1][r][c] do
  128.                 AddSimpleClause{Var.A[1][r][c][entry], entry == IS_UNMOVABLE}
  129.             end
  130.         else
  131.             local n = 0
  132.             if ColorsToConnect[s] ~= nil then
  133.                 n = ColorsToConnect[s]
  134.             else
  135.                 n = OtherColors[s]
  136.             end
  137.             assert(n ~= nil, "r="..r..",c="..c..",s="..s..", but n==nil!")
  138.             for entry = 1, #Var.A[1][r][c] do
  139.                 if entry == IS_ZERO then
  140.                     AddSimpleClause{Var.A[1][r][c][entry], r==n.r and c==n.c}
  141.                 else
  142.                     AddSimpleClause{Var.A[1][r][c][entry], n.number == entry}
  143.                 end
  144.             end
  145.         end
  146.     end end
  147.    
  148.     NewVar("R", {
  149.         MaximumTurns + 1,
  150.         2})
  151.    
  152.     NewVar("B", {
  153.         MaximumTurns + 1,
  154.         ROWS,
  155.         COLUMNS,
  156.         -- which color? zero? free? unmovable?
  157.            TotalColors  + 1   + 1   + 1
  158.        
  159.         -- these will be necessary for every single step because of the
  160.         -- possibility to connect multiple colors in the same turn
  161.         --
  162.         -- connected to zero? connection number. right less? down less?
  163.            + 1                + BITS             + BITS      + BITS
  164.         -- blocked? block number. right less? down less?                    
  165.            + 1      + BITS        + BITS      + BITS})
  166.    
  167.     print("rotation..."..total_number_of_clauses)
  168.     -- rotation helper function
  169.     local function h(rot1, rot2, r1, c1, r2, c2)
  170.         for t = 1, MaximumTurns + 1 do for entry = 1, #Var.A[1][1][1] do
  171.             AddIfThenClause(   
  172.                 "if ALL", {Var.R[t][1], rot1, Var.R[t][2], rot2, Var.A[t][r1][c1][entry], true},
  173.                 "then ALL", {Var.B[t][r2][c2][entry], true}
  174.             )
  175.             AddIfThenClause(
  176.                 "if ALL", {Var.R[t][1], rot1, Var.R[t][2], rot2, Var.A[t][r1][c1][entry], false},
  177.                 "then ALL", {Var.B[t][r2][c2][entry], false}
  178.             )
  179.         end end
  180.     end
  181.     for r = 1, ROWS do for c = 1, COLUMNS do
  182.         -- rotate 0 degrees
  183.         h(false, false, r, c, r, c)
  184.         -- 90 degrees right
  185.         h(false, true, r, c, c, ROWS + 1 - r)
  186.         -- 180 degrees right
  187.         h(true, false, r, c, ROWS + 1 - r, COLUMNS + 1 - c)
  188.         -- 270 degrees right
  189.         h(true, true,  r, c, COLUMNS + 1 - c, r)
  190.     end end
  191.    
  192.     IS_CONNECTED_TO_ZERO = TotalColors + 4
  193.     B_CONNECTION_NUMBER_OFFSET = TotalColors + 4 + 1
  194.     B_CONNECTION_NUMBER_COMPARE_RIGHT_OFFSET = B_CONNECTION_NUMBER_OFFSET + BITS
  195.     B_CONNECTION_NUMBER_COMPARE_DOWN_OFFSET = B_CONNECTION_NUMBER_OFFSET + BITS + BITS
  196.     IS_BLOCKED = TotalColors + 4 + 3*BITS + 1
  197.     B_BLOCK_NUMBER_OFFSET = TotalColors + 4 + 3*BITS + 1 + 1
  198.     B_BLOCK_NUMBER_COMPARE_RIGHT_OFFSET = B_BLOCK_NUMBER_OFFSET + BITS
  199.     B_BLOCK_NUMBER_COMPARE_DOWN_OFFSET  = B_BLOCK_NUMBER_OFFSET + BITS + BITS
  200.    
  201.     print("compare numbers..."..total_number_of_clauses)
  202.     -- compare number helper function
  203.     local function h(t,r1,c1,r2,c2,number_offset,compare_offset)
  204.         local V1 = Var.B[t][r1][c1]
  205.         local V2 = Var.B[t][r2][c2]
  206.        
  207.         -- n(V) := 1 * V[number_offset]   +  2 * V[number_offset+1]
  208.         --       + 4 * V[number_offset+2] +  8 * V[number_offset+3]
  209.         --       +16 * V[number_offset+4] + 32 * V[number_offset+5]
  210.         --       +64 * V[number_offset+6] +128 * V[number_offset+7]
  211.         --
  212.         local n = number_offset
  213.         local c = compare_offset
  214.        
  215.         -- n(V1) > n(V2) ?
  216.        
  217.         -- least significant bit
  218.         -- for the one-bit numbers a and b, a > b if and only if a == 1, b == 0
  219.         AddIfAndOnlyIfClause("ALL of", {V1[n], true, V2[n], false}, "if and only if", "ALL of", {V1[c], true})
  220.        
  221.         for b = 1, BITS - 1 do
  222.             -- x + n(V1) > x + n(V2)    <=> n(V1) > n(V2)
  223.             AddIfThenClause("if ALL", {V1[n+b], true, V2[n+b], true,   V1[c+b-1], true}, "then ALL", {V1[c+b], true})
  224.             AddIfThenClause("if ALL", {V1[n+b], true, V2[n+b], true,   V1[c+b-1], false}, "then ALL", {V1[c+b], false})
  225.             AddIfThenClause("if ALL", {V1[n+b], false, V2[n+b], false, V1[c+b-1], true}, "then ALL", {V1[c+b], true})
  226.             AddIfThenClause("if ALL", {V1[n+b], false, V2[n+b], false, V1[c+b-1], false}, "then ALL", {V1[c+b], false})
  227.            
  228.             -- x + n(V1) > n(V2) if x > n(V2)
  229.             AddIfThenClause("if ALL", {V1[n+b], true, V2[n+b], false}, "then ALL", {V1[c+b], true})
  230.             -- n(V1) <= x + n(V2) if x > n(V1)
  231.             AddIfThenClause("if ALL", {V1[n+b], false, V2[n+b], true}, "then ALL", {V1[c+b], false})
  232.         end
  233.     end
  234.     for t = 1, MaximumTurns + 1 do for r = 1, ROWS do for c = 1, COLUMNS - 1 do
  235.         h(t, r, c, r, c+1, B_CONNECTION_NUMBER_OFFSET, B_CONNECTION_NUMBER_COMPARE_RIGHT_OFFSET)
  236.         h(t, r, c, r, c+1, B_BLOCK_NUMBER_OFFSET, B_BLOCK_NUMBER_COMPARE_RIGHT_OFFSET)
  237.     end end end
  238.     for t = 1, MaximumTurns + 1 do for r = 1, ROWS - 1 do for c = 1, COLUMNS do
  239.         h(t, r, c, r+1, c, B_CONNECTION_NUMBER_OFFSET, B_CONNECTION_NUMBER_COMPARE_DOWN_OFFSET)
  240.         h(t, r, c, r+1, c, B_BLOCK_NUMBER_OFFSET, B_BLOCK_NUMBER_COMPARE_DOWN_OFFSET)
  241.     end end end
  242.    
  243.     for t = 1, MaximumTurns + 1 do r = 1, ROWS do for b = 0, BITS-1 do
  244.         AddSimpleClause{Var.B[t][r][COLUMNS][B_BLOCK_NUMBER_COMPARE_RIGHT_OFFSET + b], false}
  245.     end end end
  246.     for t = 1, MaximumTurns + 1 do c = 1, COLUMNS do for b = 0, BITS-1 do
  247.         AddSimpleClause{Var.B[t][ROWS][c][B_BLOCK_NUMBER_COMPARE_DOWN_OFFSET + b], false}
  248.     end end end
  249.    
  250.     -- check if the tile to the right has the same color
  251.     NewVar("RSC", {
  252.         MaximumTurns + 1,
  253.         ROWS,
  254.         COLUMNS - 1})
  255.    
  256.     -- check if the tile to the bottom has the same color
  257.     NewVar("DSC", {
  258.         MaximumTurns + 1,
  259.         ROWS - 1,
  260.         COLUMNS})
  261.    
  262.     print("check same color..."..total_number_of_clauses)
  263.     local function h(V,t,r1,c1,r2,c2)
  264.         AddIfThenClause(
  265.             "if ALL", {V[t][r1][c1], true},
  266.             "then ALL", {
  267.                 Var.B[t][r1][c1][IS_FREE], false,
  268.                 Var.B[t][r1][c1][IS_UNMOVABLE], false,
  269.                 Var.B[t][r2][c2][IS_FREE], false,
  270.                 Var.B[t][r2][c2][IS_UNMOVABLE], false})
  271.                
  272.         for col = 1, TotalColors do
  273.             AddSimpleClause{
  274.                 V[t][r1][c1], false,
  275.                 Var.B[t][r1][c1][col], false,
  276.                 Var.B[t][r1][c1][col], true}
  277.             AddSimpleClause{
  278.                 V[t][r1][c1], false,
  279.                 Var.B[t][r1][c1][col], true,
  280.                 Var.B[t][r2][c2][col], false}
  281.             AddSimpleClause{
  282.                 V[t][r1][c1], true,
  283.                 Var.B[t][r1][c1][col], false,
  284.                 Var.B[t][r2][c2][col], false}
  285.         end
  286.     end
  287.     -- 6420 clauses... for each turn!
  288.     for t = 1, MaximumTurns + 1 do for r = 1, ROWS do for c = 1, COLUMNS do    
  289.         if c < COLUMNS then h(Var.RSC,t,r,c,r,c+1) end
  290.         if r < ROWS then    h(Var.DSC,t,r,c,r+1,c) end
  291.     end end end
  292.    
  293.     --[[
  294.         now the "blocked" check and the "connection" check
  295.         tile r,c is blocked if
  296.             - tile r,c+1 is either unmovable or blocked
  297.             or
  298.             - it has the same color as tile r+1,c which is blocked
  299.             or
  300.             - it has the same color as tile r-1,c which is blocked
  301.             or
  302.             - it has the same color as tile r,c-1 which is blocked
  303.        
  304.         it would be a valid assignment to declare all tiles to be blocked up to now.
  305.         to make sure that all movable tiles get moved, the following is done:
  306.        
  307.             - every tile gets a "blockedness" number
  308.             - (1) if tile r,c+1 is unmovable, or if c == COLUMNS, then tile r,c is blocked
  309.             - (2) if tiles r1,c1 and r2,c2 are neighbors of the same color, then
  310.                     tile r1,c1 is blocked if and only if tile r2,c2 is blocked
  311.                 and tile r1,c1 is connected to the reference tile if and only if tile r2,c2 is connected to the reference tile
  312.             - (3) if tile r,c is blocked then:
  313.                 -  c == COLUMNS
  314.                 or
  315.                 - tile r,c+1 is unmovable
  316.                 or
  317.                 - the left, upper or lower neighbor has the same color
  318.                         and a lower blockedness number
  319.                 or
  320.                 - the right neighbor has a lower blockedness number
  321.                
  322.                   if tile r,c is connected to zero then:
  323.                 - it is the zero tile
  324.                 or
  325.                 - the left, right, top, or bottom neighbor
  326.                    has the same color AND a lower connection number
  327.             - (4) the reference tile of each color is connected to itself
  328.     --]]
  329.    
  330.     print("check blocked...(1)"..total_number_of_clauses)
  331.     --(1)
  332.     for t = 1, MaximumTurns + 1 do for r = 1, ROWS do
  333.         AddSimpleClause{Var.B[t][r][COLUMNS][IS_BLOCKED], true}
  334.         --(4)
  335.         for c = 1, COLUMNS do
  336.             AddSimpleClause{Var.B[t][r][c][IS_ZERO], false, Var.B[t][r][c][IS_CONNECTED_TO_ZERO], true}
  337.         end
  338.     end end
  339.     for t = 1, MaximumTurns + 1 do for r = 1, ROWS do for c = 1, COLUMNS - 1 do
  340.         AddIfThenClause("if ALL", {Var.B[t][r][c+1][IS_UNMOVABLE], true}, "then ALL", {Var.B[t][r][c][IS_BLOCKED], true})
  341.     end end end
  342.    
  343.     print("check blocked...(2)"..total_number_of_clauses)
  344.     --(2)
  345.     for t = 1, MaximumTurns + 1 do for r = 1, ROWS do for c = 1, COLUMNS - 1 do
  346.         AddIfThenClause("if ALL", {Var.RSC[t][r][c], true, Var.B[t][r][c][IS_BLOCKED], true}, "then ALL", {Var.B[t][r][c+1][IS_BLOCKED], true})
  347.         AddIfThenClause("if ALL", {Var.RSC[t][r][c], true, Var.B[t][r][c][IS_BLOCKED], false}, "then ALL", {Var.B[t][r][c+1][IS_BLOCKED], false})
  348.         AddIfThenClause("if ALL", {Var.RSC[t][r][c], true, Var.B[t][r][c][IS_CONNECTED_TO_ZERO], true}, "then ALL", {Var.B[t][r][c+1][IS_CONNECTED_TO_ZERO], true})
  349.         AddIfThenClause("if ALL", {Var.RSC[t][r][c], true, Var.B[t][r][c][IS_CONNECTED_TO_ZERO], false}, "then ALL", {Var.B[t][r][c+1][IS_CONNECTED_TO_ZERO], false})
  350.     end end end
  351.     for t = 1, MaximumTurns + 1 do for r = 1, ROWS - 1 do for c = 1, COLUMNS do
  352.         AddIfThenClause("if ALL", {Var.DSC[t][r][c], true, Var.B[t][r][c][IS_BLOCKED], true}, "then ALL", {Var.B[t][r+1][c][IS_BLOCKED], true})
  353.         AddIfThenClause("if ALL", {Var.DSC[t][r][c], true, Var.B[t][r][c][IS_BLOCKED], false}, "then ALL", {Var.B[t][r+1][c][IS_BLOCKED], false})
  354.         AddIfThenClause("if ALL", {Var.DSC[t][r][c], true, Var.B[t][r][c][IS_CONNECTED_TO_ZERO], true}, "then ALL", {Var.B[t][r+1][c][IS_CONNECTED_TO_ZERO], true})
  355.         AddIfThenClause("if ALL", {Var.DSC[t][r][c], true, Var.B[t][r][c][IS_CONNECTED_TO_ZERO], false}, "then ALL", {Var.B[t][r+1][c][IS_CONNECTED_TO_ZERO], false})
  356.     end end end
  357.    
  358.     print("check blocked...(3)"..total_number_of_clauses)
  359.     --(3)
  360.     -- many many distinct cases... so evil!
  361.     -- there should be some better way to encode this
  362.    
  363.     -- prevent out-of-bound errors
  364.     --
  365.     -- if we write Var.B[t][r-1][c][number] and r == 1,
  366.     -- we get an "attempt to index field ? (a nil value) error"
  367.     -- even if we check that r > 1 beforehand. This can
  368.     -- be prevented only if it is encapsulated with a function call
  369.     --
  370.     -- try the following minimal example:
  371.    
  372.     --[[
  373. t = {"hi"}
  374.  
  375. -- works!
  376. function h(b,f)
  377.     if b then return f() else return "no!" end
  378. end
  379.  
  380. print(t[1]..","..tostring(t[2])..h(false, function() return t[2][1] end))
  381.  
  382. -- does not work! attempt to index field ? (a nil value)
  383. function h(b,f)
  384.     if b then return f else return "no!" end
  385. end
  386.  
  387. print(t[1]..","..tostring(t[2])..h(false, t[2][1]))
  388.     --]]
  389.    
  390.     function OOB_catcher(b, f)
  391.         if b then return f() else return nil end
  392.     end
  393.    
  394.     -- how beautiful, 7 loops!
  395.     -- there will be some duplicate clauses, it is easier
  396.     -- to let the solver remove them than to handle this here.
  397.     for t = 1, MaximumTurns + 1 do
  398.     for r = 1, ROWS do
  399.     for c = 1, COLUMNS do
  400.    
  401.     for _,b1 in pairs{true,false} do
  402.     for _,b2 in pairs{true,false} do
  403.     for _,b3 in pairs{true,false} do
  404.        
  405.         -- there is one reference tile of each color.
  406.         -- if the puzzle is solved, all tiles are connected to the reference tile
  407.         --
  408.         -- if a tile is connected to the reference tile,
  409.         --      - it is the reference tile itself
  410.         --   OR - it is connected to a tile with a lower connection number.
  411.         -- it would make sense that the reference tile has connection number zero but that isnt enforced.
  412.         for _,b4 in pairs{true,false} do
  413.             local function h(cl, a1, a2)
  414.                 cl[#cl+1] = a1
  415.                 cl[#cl+1] = a2
  416.             end
  417.            
  418.             local cl1 = {Var.B[t][r][c][IS_CONNECTED_TO_ZERO], true}
  419.             if r > 1 then h(cl1, Var.DSC[t][r-1][c], b1) end
  420.             if r < ROWS then h(cl1, Var.DSC[t][r][c], b2) end
  421.             if c > 1 then h(cl1, Var.RSC[t][r][c-1], b3) end
  422.             if c < COLUMNS then h(cl1, Var.RSC[t][r][c], b4) end
  423.            
  424.             local cl2 = {Var.B[t][r][c][IS_ZERO], true}
  425.             --[[up   ]] if r > 1 and b1 then h(cl2, Var.B[t][r-1][c][B_CONNECTION_NUMBER_COMPARE_DOWN_OFFSET + BITS - 1], false) end
  426.             --[[down ]] if r < ROWS and b2 then h(cl2, Var.B[t][r][c][B_CONNECTION_NUMBER_COMPARE_DOWN_OFFSET + BITS - 1], true) end
  427.             --[[left ]] if c > 1 and b3 then h(cl2, Var.B[t][r][c-1][B_CONNECTION_NUMBER_COMPARE_RIGHT_OFFSET + BITS - 1], false) end
  428.             --[[right]] if c < COLUMNS and b4 then h(cl2, Var.B[t][r][c][B_CONNECTION_NUMBER_COMPARE_RIGHT_OFFSET + BITS - 1], true) end
  429.            
  430.             AddIfThenClause("if ALL", cl1, "then ONE", cl2)
  431.         end
  432.         -- if a tile is blocked then:
  433.         --     - the tile to its right is unmovable
  434.         --  OR - its right neighbor is not free and has a lower blockedness number
  435.         --  OR - its left, top, or bottom neighbor has the same color AND a lower blockedness number
  436.         if c < COLUMNS then
  437.             local function h(cl, a1, a2)
  438.                 cl[#cl+1] = a1
  439.                 cl[#cl+1] = a2
  440.             end
  441.            
  442.             for _,b4 in pairs{true,false} do
  443.                 local cl1 = {Var.B[t][r][c][IS_BLOCKED], true}
  444.                 if r > 1 then h(cl1, Var.DSC[t][r-1][c], b1) end
  445.                 if r < ROWS then h(cl1, Var.DSC[t][r][c], b2) end
  446.                 if c > 1 then h(cl1, Var.RSC[t][r][c-1], b3) end
  447.                 h(cl1, Var.B[t][r][c+1][IS_FREE], b4)
  448.                
  449.                 local cl2 = {Var.B[t][r][c+1][IS_UNMOVABLE], true}     
  450.                 if r > 1 and b1    then h(cl2, Var.B[t][r-1][c][B_BLOCK_NUMBER_COMPARE_DOWN_OFFSET + BITS - 1], false) end -- less or equal is enough to prevent loops
  451.                 if r < ROWS and b2 then h(cl2, Var.B[t][r][c][B_BLOCK_NUMBER_COMPARE_DOWN_OFFSET + BITS - 1], true) end
  452.                 if c > 1 and b3    then h(cl2, Var.B[t][r][c-1][B_BLOCK_NUMBER_COMPARE_RIGHT_OFFSET + BITS - 1], false) end
  453.                 if not b4          then h(cl2, Var.B[t][r][c][B_BLOCK_NUMBER_COMPARE_RIGHT_OFFSET + BITS - 1], true) end
  454.                
  455.                 AddIfThenClause("if ALL", cl1, "then ONE", cl2)
  456.             end
  457.         end
  458.        
  459.     end end end end end end
  460.    
  461.     print("move!..."..total_number_of_clauses)
  462.     -- now make the move!
  463.     for t = 1, MaximumTurns do
  464.     for r = 1, ROWS do
  465.     for entry = 1, #Var.A[1][1][1] do
  466.     for _,b in pairs{true, false} do
  467.        
  468.         for c = 1, COLUMNS do
  469.             -- a blocked tile or an unmovable tile stays in place
  470.             for _,e1 in pairs{IS_BLOCKED, IS_UNMOVABLE} do
  471.                 AddIfThenClause("if ALL", {Var.B[t][r][c][e1], true, Var.B[t][r][c][entry], b},
  472.                     "then ALL", {Var.A[t+1][r][c][entry], b})
  473.             end
  474.            
  475.             -- otherwise:
  476.                 -- if the tile to the left is neither blocked nor unmovable, move!
  477.            
  478.             if c > 1 then
  479.                 AddIfThenClause(
  480.                     "if ALL", {
  481.                     Var.B[t][r][c][IS_UNMOVABLE], false,
  482.                     Var.B[t][r][c][IS_BLOCKED], false,
  483.                     Var.B[t][r][c-1][IS_UNMOVABLE], false,
  484.                     Var.B[t][r][c-1][IS_BLOCKED], false,
  485.                     Var.B[t][r][c-1][entry], b},
  486.                     "then ALL", {
  487.                     Var.A[t+1][r][c][entry], b}
  488.                 )
  489.                
  490.                 -- if the tile to the left is blocked or unmovable, this tile becomes free!
  491.                 if b then
  492.                     AddIfThenClause(
  493.                         "if ALL", {
  494.                         Var.B[t][r][c][IS_UNMOVABLE], false,
  495.                         Var.B[t][r][c][IS_BLOCKED], false,
  496.                         Var.B[t][r][c-1][IS_UNMOVABLE], true},
  497.                         "then ALL", {
  498.                         Var.A[t+1][r][c][entry], entry == IS_FREE}
  499.                     )
  500.                     AddIfThenClause(
  501.                         "if ALL", {
  502.                         Var.B[t][r][c][IS_UNMOVABLE], false,
  503.                         Var.B[t][r][c][IS_BLOCKED], false,
  504.                         Var.B[t][r][c-1][IS_BLOCKED], true},
  505.                         "then ALL", {
  506.                         Var.A[t+1][r][c][entry], entry == IS_FREE}
  507.                     )
  508.                 end
  509.             else
  510.                 -- if there is no tile to the left, there is new free space!
  511.                 if b then
  512.                     AddIfThenClause(
  513.                         "if ALL", {
  514.                         Var.B[t][r][c][IS_UNMOVABLE], false,
  515.                         Var.B[t][r][c][IS_BLOCKED], false},
  516.                         "then ALL", {
  517.                         Var.A[t+1][r][c][entry], entry == IS_FREE}
  518.                     )
  519.                 end
  520.             end
  521.         end
  522.        
  523.     end end end end
  524.    
  525.     print("winning condition check!.."..total_number_of_clauses)
  526.     -- finally, check the winning condition. so easy now!
  527.     local V = Var.B[MaximumTurns+1]
  528.     for r = 1, ROWS do for c = 1, COLUMNS do
  529.         local cl = {V[r][c][IS_FREE], true, V[r][c][IS_UNMOVABLE], true, V[r][c][IS_CONNECTED_TO_ZERO], true}
  530.         for col = #ColorsToConnect + 1, TotalColors do
  531.             cl[#cl+1] = V[r][c][col]
  532.             cl[#cl+1] = true
  533.         end
  534.         AddSimpleClause(cl)
  535.     end end
  536.     print("done!.."..total_number_of_clauses)
  537. end
  538.  
  539. function MovementPattern()
  540.     local num = {
  541.         [false] = {[false] = 0, [true]  = 1},
  542.         [true] = {[false] = 2, [true] = 3 }}
  543.     local name = {[0] = "right", "up", "left", "down"}
  544.    
  545.     --[[
  546.     -- this is how R was used
  547.     for r = 1, ROWS do for c = 1, COLUMNS do
  548.         -- rotate 0 degrees
  549.         h(false, false, r, c, r, c)
  550.         -- 90 degrees right
  551.         h(false, true, r, c, c, ROWS + 1 - r)
  552.         -- 180 degrees right
  553.         h(true, false, r, c, ROWS + 1 - r, COLUMNS + 1 - c)
  554.         -- 270 degrees right
  555.         h(true, true,  r, c, COLUMNS + 1 - c, r)
  556.     end end --]]
  557.    
  558.     now = 0
  559.     ret = {}
  560.     for t = 1, #Sol.R do
  561.         now = (now + num[Sol.R[t][1]][Sol.R[t][2]]) % 4
  562.         ret[#ret+1] = name[now]
  563.     end
  564.     return ret
  565. end
  566.  
  567. CreateCNF()
  568. WriteSATfile()
  569. if USE_PICOSAT then
  570.     os.execute("picosat satfile.cnf >solutionfile")
  571. elseif USE_MINISAT then
  572.     os.execute("minisat satfile.cnf solutionfile")
  573. end
  574. ParseSolution()
  575. for i,m in ipairs(MovementPattern()) do
  576.     for r = 1, ROWS do
  577.         local s = ""
  578.         for c = 1, COLUMNS do for entry = 1, #Sol.A[1][1][1] do if Sol.A[i][r][c][entry] then s = s .. entry else s = s .. " " end end
  579.             s = s.."|"
  580.         end
  581.         print(s)
  582.     end
  583.     print (i..": "..m)
  584.    
  585.     print()
  586. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement