-- Sliding Blocks Puzzles -- File started 25/11/2k7 by Jean Manuel Morales -- 25/11/2k7 : init -- 08/12/2k7 : val function --[[ TODO: - valuation - Have 26 colors! --]] dofile("utility_square.lua"); -- The 'variants' vector could be filled by -- reading how many SBPxxx.txt files there are variants = {}; do local file_name = ""; local msg; local n_found = 0; for x1 = 0,9 do for x2 = 0,9 do for x3 = 0,9 do if (x1 + x2 + x3 == 0) then x3 = 1; end file_name = "SBP_" .. x1 .. x2 .. x3 .. ".txt"; file, msg = io.open(file_name, "r"); if file then io.close(); n_found = n_found + 1; variants[n_found] = file_name; end end end end end --[[ variants = {"SBP_001.txt", "SBP_010.txt", "SBP_002.txt", "SBP_003.txt", "SBP_004.txt", "SBP_005.txt", "SBP_008.txt", "SBP_009.txt", "SBP_007.txt", "SBP_006.txt"}; --]] init = function () players = {"Thinker"}; -- Read the initial end the last position form file -- according to variant number last_pos = {}; -- global init_pos = {}; local max_p = 26; -- max pieces local width = 0; local height = 0; local init_end = 0; local file; local msg; local file_name; local line = ""; local len_l = 0; file_name = variants[get_variant()+1]; file, msg = io.open(file_name, "r"); if not file then -- TODO: manage errors print("uh-oh!"); else for line in io.lines(file_name) do width = string.len(line); if (width == 0) then init_end = 1; height = 0; else height = height + 1; if (init_end == 0) then init_pos[height] = line; else last_pos[height] = line; end end end end io.close(); rect_grid(height, width); pieces = {"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", "p16", "p17", "p18", "p19", "p20", "p21", "p22", "p23", "p24", "p25", "p26", "wall"}; p1 = {}; p2 = {}; p3 = {}; p4 = {}; p5 = {}; p6 = {}; p7 = {}; p8 = {}; p9 = {}; p10 = {}; p11 = {}; p12 = {}; p13 = {}; p14 = {}; p15 = {}; p16 = {}; p17 = {}; p18 = {}; p19 = {}; p20 = {}; p21 = {}; p22 = {}; p23 = {}; p24 = {}; p25 = {}; p26 = {}; wall = {}; np = {}; -- number of pieces found in initial position for i = 1,(max_p+1) do np[i] = 0; end local ch = ""; local cell_name = ""; for i = 1,height do for j = 1,width do ch = string.sub(init_pos[i], j, j); cell_name = string.char(string.byte("a") - 1 + j) .. (height + 1 - i); if (ch == "#") then -- a wall np[max_p+1] = np[max_p+1] + 1; wall[np[max_p+1]] = cell_name; else if (ch ~= ".") then -- a piece if (ch == "a") then np[1]=np[1]+1; p1[np[1]]=cell_name; end if (ch == "b") then np[2]=np[2]+1; p2[np[2]]=cell_name; end if (ch == "c") then np[3]=np[3]+1; p3[np[3]]=cell_name; end if (ch == "d") then np[4]=np[4]+1; p4[np[4]]=cell_name; end if (ch == "e") then np[5]=np[5]+1; p5[np[5]]=cell_name; end if (ch == "f") then np[6]=np[6]+1; p6[np[6]]=cell_name; end if (ch == "g") then np[7]=np[7]+1; p7[np[7]]=cell_name; end if (ch == "h") then np[8]=np[8]+1; p8[np[8]]=cell_name; end if (ch == "i") then np[9]=np[9]+1; p9[np[9]]=cell_name; end if (ch == "j") then np[10]=np[10]+1; p10[np[10]]=cell_name; end if (ch == "k") then np[11]=np[11]+1; p11[np[11]]=cell_name; end if (ch == "l") then np[12]=np[12]+1; p12[np[12]]=cell_name; end if (ch == "m") then np[13]=np[13]+1; p13[np[13]]=cell_name; end if (ch == "n") then np[14]=np[14]+1; p14[np[14]]=cell_name; end if (ch == "o") then np[15]=np[15]+1; p15[np[15]]=cell_name; end if (ch == "p") then np[16]=np[16]+1; p16[np[16]]=cell_name; end if (ch == "q") then np[17]=np[17]+1; p17[np[17]]=cell_name; end if (ch == "r") then np[18]=np[18]+1; p18[np[18]]=cell_name; end if (ch == "s") then np[19]=np[19]+1; p19[np[19]]=cell_name; end if (ch == "t") then np[20]=np[20]+1; p20[np[20]]=cell_name; end if (ch == "u") then np[21]=np[21]+1; p21[np[21]]=cell_name; end if (ch == "v") then np[22]=np[22]+1; p22[np[22]]=cell_name; end if (ch == "w") then np[23]=np[23]+1; p23[np[23]]=cell_name; end if (ch == "x") then np[24]=np[24]+1; p24[np[24]]=cell_name; end if (ch == "y") then np[25]=np[25]+1; p25[np[25]]=cell_name; end if (ch == "z") then np[26]=np[26]+1; p26[np[26]]=cell_name; end end end end end cells[width*height+1] = "well"; return 1; end victory = function () local res = 1; local id_cell = 0; local p_id = 0; for i = 1,n_rows do for j = 1,n_cols do if ((string.sub(last_pos[i], j, j) ~= ".") and (string.sub(last_pos[i], j, j) ~= "#")) then ch = string.byte(string.sub(last_pos[i], j, j)) - string.byte("a") + 1; -- whished piece id_cell = j + (n_rows+1-i - 1)*n_cols; if (ch ~= id_get_pieces(id_cell)) then -- cell in id_cell res = 0; break; end end end end return res; end list_moves = function () -- move is "pd" where "p" = 1, ..., 26 is the piece to be moved -- and "d" = "n", "s", "e", "w" is the direction local move = ""; local n_moves = 0; moves = {}; local dir = {"n", "s", "e", "w"}; local p = 0; local no_p; local last_move = past_move(1); local backup_move = ""; if (last_move ~= nil) then local dlm = string.sub(last_move, -1); local plm = string.sub(last_move, 1, string.len(last_move)-1); last_move = plm; if (dlm == "n") then last_move = last_move .. "s"; end if (dlm == "s") then last_move = last_move .. "n"; end if (dlm == "e") then last_move = last_move .. "w"; end if (dlm == "w") then last_move = last_move .. "e"; end end -- for each macro-piece: -- for each piece: -- check if "d" is in board and empty or with another piece local jmp = -1; for i = 1,26 do no_p = 0; local can_d = {1, 1, 1, 1}; -- for k = 1,4 do can_d[k] = 1; end for j = 1,(n_cols*n_rows) do p = id_get_pieces(j); if (p == i) then no_p = 1; for k = 1,4 do jmp = jump(j, dir[k], 1); if ((jmp == -1) or ((id_get_pieces(jmp) ~= p) and (id_get_pieces(jmp) ~= -1))) then can_d[k] = 0; end end end end if (no_p == 1) then for k = 1,4 do if (can_d[k] == 1) then move = i .. dir[k]; if (move == last_move) then backup_move = move; else n_moves = n_moves + 1; moves[n_moves] = move; end end end end end if (n_moves == 0) then n_moves = 1; moves[n_moves] = backup_move; end return n_moves; end make_move = function (move) local d = string.sub(move, -1); local p = string.sub(move, 1, string.len(move) - 1) + 0; local dest = {}; local n = 0; -- move all pieces in the well for j = 1,(n_cols*n_rows) do if (id_get_pieces(j) == p) then n = n + 1; dest[n] = jump(j, d, 1); move_piece(cells[j], 1, "well", n); end end -- move all pieces to their new position for j = 1,n do move_piece("well", n, cells[dest[j]], 1); n = n - 1; end end valuation = function () val = {}; local res = 5000; local cpx = {}; local cpy = {}; -- current pieces' x,y local ipx = {}; local ipy = {}; -- init pieces' x,y local lpx = {}; local lpy = {}; -- last pieces' x,y local ncp = 0; local nip = 0; local nlp = 0; for i = 1,26 do cpx = {}; cpy = {}; ipx = {}; ipy = {}; lpx = {}; lpy = {}; ncp = 0; nip = 0; nlp = 0; for x = 1,n_cols do for y = 1,n_rows do if (i == id_get_pieces(x + (n_rows - y)*n_cols)) then ncp = ncp + 1; cpx[ncp] = x; cpy[ncp] = y; end if (string.char(string.byte("a") - 1 + i) == string.sub(last_pos[y], x, x)) then nlp = nlp + 1; lpx[nlp] = x; lpy[nlp] = y; end if (string.char(string.byte("a") - 1 + i) == string.sub(init_pos[y], x, x)) then nip = nip + 1; ipx[nip] = x; ipy[nip] = y; end end end if (nlp > 0) then local cumdist = 0; for j = 1,nlp do cumdist = cumdist + distance(lpx[j] + (lpy[j]-1)*n_cols, cpx[j] + (cpy[j]-1)*n_cols); cumdist = cumdist - distance(cpx[j] + (cpy[j]-1)*n_cols, ipx[j] + (ipy[j]-1)*n_cols)*50; end res = res - cumdist; end end val[1] = res; if (val[1] < 10000) then val[1] = val[1] - math.random(5) end; return 1; end game_info = function () game_name = "Sliding Block Puzzle"; game_help = {}; game_help[ 1] = "You win by sliding the blocks"; game_help[ 2] = "in the right place. Destinations"; game_help[ 3] = "of the blocks are marked by bold"; game_help[ 4] = "line."; game_author = "???"; game_date = "Dec 2007"; game_movements = {}; game_movements[ 1] = "Click in a piece of the block you"; game_movements[ 2] = "you want to move and then on the cell"; game_movements[ 3] = "that piece should go. The destination"; game_movements[ 4] = "cell should be empty."; game_strategy = {}; game_strategy[ 1] = "-"; return 1; end init_graphics = function () board = "square.bmp"; boardw = 1; boardh = 1; rect_xy_grid(); cellsx[n_rows*n_cols+1] = -1; cellsy[n_rows*n_cols+1] = -1; p1_bmp = "p_aquamarine.bmp"; p2_bmp = "p_blue.bmp"; p3_bmp = "p_green.bmp"; p4_bmp = "p_light_blue.bmp"; p5_bmp = "p_orange.bmp"; p6_bmp = "p_red.bmp"; p7_bmp = "p_violet.bmp"; p8_bmp = "p_yellow.bmp"; -- TODO... -- cycling... p9_bmp = "p_aquamarine.bmp"; p10_bmp = "p_blue.bmp"; p11_bmp = "p_green.bmp"; p12_bmp = "p_light_blue.bmp"; p13_bmp = "p_orange.bmp"; p14_bmp = "p_red.bmp"; p15_bmp = "p_violet.bmp"; p16_bmp = "p_yellow.bmp"; p17_bmp = "p_aquamarine.bmp"; p18_bmp = "p_blue.bmp"; p19_bmp = "p_green.bmp"; p20_bmp = "p_light_blue.bmp"; p21_bmp = "p_orange.bmp"; p22_bmp = "p_red.bmp"; p23_bmp = "p_violet.bmp"; p24_bmp = "p_yellow.bmp"; p25_bmp = "p_aquamarine.bmp"; p26_bmp = "p_blue.bmp"; wall_bmp = "cross.bmp"; -- Draw lines local ch = ""; local x1 = 0; local x2 = 0; local y1 = 0; local y2 = 0; for i = 1,n_rows do for j = 1,n_cols do ch = string.sub(last_pos[i], j, j); if ((ch ~= ".") and (ch ~= "#")) then -- a piece if (ch == "a") then r = 255*(1/26); g = 0; b = 255*(26/26); end if (ch == "b") then r = 255*(7/26); g = 0; b = 255*(25/26); end if (ch == "c") then r = 255*(13/26); g = 0; b = 255*(24/26); end if (ch == "d") then r = 255*(20/26); g = 0; b = 255*(23/26); end if (ch == "e") then r = 255*(26/26); g = 0; b = 255*(22/26); end if (ch == "f") then r = 255*(1/26); g = 0; b = 255*(21/26); end if (ch == "g") then r = 255*(7/26); g = 0; b = 255*(20/26); end if (ch == "h") then r = 255*(13/26); g = 0; b = 255*(19/26); end if (ch == "i") then r = 255*(20/26); g = 0; b = 255*(18/26); end if (ch == "j") then r = 255*(26/26); g = 0; b = 255*(17/26); end if (ch == "k") then r = 255*(1/26); g = 0; b = 255*(16/26); end if (ch == "l") then r = 255*(7/26); g = 0; b = 255*(15/26); end if (ch == "m") then r = 255*(13/26); g = 0; b = 255*(14/26); end if (ch == "n") then r = 255*(20/26); g = 0; b = 255*(13/26); end if (ch == "o") then r = 255*(26/26); g = 0; b = 255*(12/26); end if (ch == "p") then r = 255*(1/26); g = 0; b = 255*(11/26); end if (ch == "q") then r = 255*(7/26); g = 0; b = 255*(10/26); end if (ch == "r") then r = 255*(13/26); g = 0; b = 255*(9/26); end if (ch == "s") then r = 255*(20/26); g = 0; b = 255*(8/26); end if (ch == "t") then r = 255*(26/26); g = 0; b = 255*(7/26); end if (ch == "u") then r = 255*(1/26); g = 0; b = 255*(6/26); end if (ch == "v") then r = 255*(7/26); g = 0; b = 255*(5/26); end if (ch == "w") then r = 255*(13/26); g = 0; b = 255*(4/26); end if (ch == "x") then r = 255*(20/26); g = 0; b = 255*(3/26); end if (ch == "y") then r = 255*(26/26); g = 0; b = 255*(2/26); end if (ch == "z") then r = 255*(1/26); g = 0; b = 255*(1/26); end -- Draw left line x1 = j - 0.5; x2 = j - 0.5; y1 = i - 0.5; y2 = i + 0.5; add_line(x1, y1, x2, y2, r, g, b); -- Draw top line x1 = j - 0.5; x2 = j + 0.5; y1 = i - 0.5; y2 = i - 0.5; add_line(x1, y1, x2, y2, r, g, b); -- Draw right line x1 = j + 0.5; x2 = j + 0.5; y1 = i - 0.5; y2 = i + 0.5; add_line(x1, y1, x2, y2, r, g, b); -- Draw bottom line x1 = j - 0.5; x2 = j + 0.5; y1 = i + 0.5; y2 = i + 0.5; add_line(x1, y1, x2, y2, r, g, b); end end end return 1; end control_mouse = function (x, y, historical) local res = 0; local ic = click(x, y); local id_piece = 0; local id_jump = 0; local dir = {"n", "s", "e", "w"}; if (ic == -1) then historical = ""; else id_piece = id_get_pieces(ic); if (id_piece == -1) then -- clicked an empty cell if (historical ~= "") then for k = 1,4 do id_jump = jump(name_to_id(historical), dir[k], 1); if (id_jump == ic) then historical = id_get_pieces(name_to_id(historical)) .. dir[k]; res = 1; -- OK break; end end else historical = ""; end else -- clicked a piece historical = cells[ic]; end end return historical, res; end