-- Editor for Sliding Block Puzzles -- File started 13/10/2k7 by Jean Manuel Morales -- 14/10/2k7 : lot more work -- 01/12/2k7 : more work (up to 26 colours) -- 02/12/2k7 : last PASS ends the game -- 09/12/2k7 : completed (version 1...) dofile("utility_square.lua"); init = function () players = {"Designer"}; square_grid(14); 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", "cross", "soil", "r_arrow", "l_arrow", "mark", "wall"}; cells[14*14+ 1] = "p1_well"; cells[14*14+ 2] = "p2_well"; cells[14*14+ 3] = "p3_well"; cells[14*14+ 4] = "p4_well"; cells[14*14+ 5] = "p5_well"; cells[14*14+ 6] = "p6_well"; cells[14*14+ 7] = "p7_well"; cells[14*14+ 8] = "p8_well"; cells[14*14+ 9] = "p9_well"; cells[14*14+10] = "p10_well"; cells[14*14+11] = "p11_well"; cells[14*14+12] = "p12_well"; cells[14*14+13] = "p13_well"; cells[14*14+14] = "p14_well"; cells[14*14+15] = "p15_well"; cells[14*14+16] = "p16_well"; cells[14*14+17] = "p17_well"; cells[14*14+18] = "p18_well"; cells[14*14+19] = "p19_well"; cells[14*14+20] = "p20_well"; cells[14*14+21] = "p21_well"; cells[14*14+22] = "p22_well"; cells[14*14+23] = "p23_well"; cells[14*14+24] = "p24_well"; cells[14*14+25] = "p25_well"; cells[14*14+26] = "p26_well"; cells[14*14+27] = "soil_well"; cells[14*14+28] = "mark_well"; cells[14*14+29] = "wall_well"; p1 = {}; p2 = {}; p3 = {}; p4 = {}; p5 = {}; p6 = {}; p7 = {}; p8 = {}; 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 = {}; cross = {}; soil = {}; mark = {}; r_arrow = {}; l_arrow = {}; wall = {}; for i = 1,145 do p1[i] = "p1_well"; p2[i] = "p2_well"; p3[i] = "p3_well"; p4[i] = "p4_well"; p5[i] = "p5_well"; p6[i] = "p6_well"; p7[i] = "p7_well"; p8[i] = "p8_well"; p9[i] = "p9_well"; p10[i] = "p10_well"; p11[i] = "p11_well"; p12[i] = "p12_well"; p13[i] = "p13_well"; p14[i] = "p14_well"; p15[i] = "p15_well"; p16[i] = "p16_well"; p17[i] = "p17_well"; p18[i] = "p18_well"; p19[i] = "p19_well"; p20[i] = "p20_well"; p21[i] = "p21_well"; p22[i] = "p22_well"; p23[i] = "p23_well"; p24[i] = "p24_well"; p25[i] = "p25_well"; p26[i] = "p26_well"; soil[i] = "soil_well"; mark[i] = "mark_well"; wall[i] = "wall_well"; end p1[145] = cells[14*13+1]; p2[145] = cells[14*12+1]; p3[145] = cells[14*11+1]; p4[145] = cells[14*10+1]; p5[145] = cells[14*9 +1]; p6[145] = cells[14*8 +1]; p7[145] = cells[14*7 +1]; p8[145] = cells[14*6 +1]; cross[1] = cells[14*3 +1]; soil[145] = cells[14*2+1]; r_arrow[1] = cells[14*1+1]; l_arrow[1] = cells[14*0+1]; wall[145] = cells[14*4+1]; --[[ STATES: 100 - piece not selected (drawing initial position) 200 - piece not selected (drawing final position) 1xx - selected pxx 197 - wall 198 - soil 199 - cross 2xx - selected pxx 299 - cross 0 - design completed --]] return 1; end victory = function () local flag = get_flag(); if (flag > 0) then return 0; else return 1; end end -- return 1 if initial phase is ok: -- - there are at least one piece in the board initial_phase_ok = function () local res = 0; for i = 1,196 do if (math.mod(i, 14) ~= 1) then if (id_get_pieces(i) ~= -1) then res = 1; break; end end end return res; end -- return 1 if initial phase is ok: -- - the final pieces are the same of the initial ones final_phase_ok = function () local res = 0; res = 1; return res; end list_moves = function () local move = ""; local n_moves = 0; moves = {}; local state = get_flag(); if (state > 0) then -- should select something n_moves = n_moves + 1; moves[n_moves] = cells[14*13+1]; -- menu 1 n_moves = n_moves + 1; moves[n_moves] = cells[14*12+1]; n_moves = n_moves + 1; moves[n_moves] = cells[14*11+1]; n_moves = n_moves + 1; moves[n_moves] = cells[14*10+1]; n_moves = n_moves + 1; moves[n_moves] = cells[14* 9+1]; n_moves = n_moves + 1; moves[n_moves] = cells[14* 8+1]; n_moves = n_moves + 1; moves[n_moves] = cells[14* 7+1]; n_moves = n_moves + 1; moves[n_moves] = cells[14* 6+1]; -- menu 8 n_moves = n_moves + 1; moves[n_moves] = cells[14* 4+1]; -- wall n_moves = n_moves + 1; moves[n_moves] = cells[14* 3+1]; -- cross n_moves = n_moves + 1; moves[n_moves] = cells[14* 2+1]; -- soil n_moves = n_moves + 1; moves[n_moves] = cells[14* 1+1]; -- right n_moves = n_moves + 1; moves[n_moves] = cells[14* 0+1]; -- left -- pass only if possible: check via a dedicated routine -- n_moves = n_moves + 1; moves[n_moves] = "PASS"; -- change state end if ((state > 0) and (state < 200)) then -- can draw soils n_moves = n_moves + 1; moves[n_moves] = cells[14* 2+1]; -- soil end if ((state >= 101) and (state <= 198)) then -- can move in every cell (not in the left col) for i = 1,196 do if (math.mod(i, 14) ~= 1) then -- and (id_get_pieces(i) == -1)) then move = cells[i]; n_moves = n_moves + 1; moves[n_moves] = move; end end end if (((state >= 201) and (state <= 299)) or (state == 199)) then -- can move only where there was something at initial phase for i = 1,196 do if ((math.mod(i, 14) ~= 1) and (id_get_n_pieces(i) ~= -1)) then move = cells[i]; n_moves = n_moves + 1; moves[n_moves] = move; end end end if ((state == 199) or (state == 299)) then -- can move in every occupied cell (not in the left col) for i = 1,196 do if ((math.mod(i, 14) ~= 1) and (id_get_pieces(i) ~= -1)) then move = cells[i]; n_moves = n_moves + 1; moves[n_moves] = move; end end end if (state < 200) then if (initial_phase_ok() == 1) then move = "PASS"; n_moves = n_moves + 1; moves[n_moves] = move; end end if (state >= 200) then if (final_phase_ok() == 1) then move = "PASS"; n_moves = n_moves + 1; moves[n_moves] = move; end end return n_moves; end save_the_puzzle = function () local file_name = ""; local msg local file; local first_x = 14; local last_x = 0; local first_y = 14; local last_y = 0; local x1 = 0; local x2 = 0; local x3 = 0; local last_pos = {}; local init_pos = {}; 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 not file then io.close(); file, msg = io.open(file_name, "w"); local line = ""; local ch = ""; local pp; local np; -- output initial position for i = 1,14 do -- check lines for j = 2,14 do -- check rows pp = {id_get_pieces(j + (14+1-i-1)*14)}; ch = pp[1]; if (ch == -1) then line = line .. "#"; else if (ch == 28) then line = line .. "."; else if (ch == 32) then line = line .. "#"; else line = line .. string.char(string.byte("a") - 1 + ch); end end end end init_pos[i] = line; line = ""; end -- file:write("\n"); -- output final position for i = 1,14 do -- check lines for j = 2,14 do -- check rows pp = {id_get_pieces(j + (14+1-i-1)*14)}; np = id_get_n_pieces(j + (14+1-i-1)*14); if (pp[1] == -1) then ch = -1; end if (np == 1) then ch = pp[1]; end if (np == 3) then ch = pp[3]; end if (np == 2) then ch = pp[2]; if (ch == 31) then ch = 28; end end if (ch == -1) then line = line .. "#"; else if (ch == 28) then line = line .. "."; else if (ch == 32) then line = line .. "#"; else line = line .. string.char(string.byte("a") - 1 + ch); end end end end -- if (line ~= "") then last_pos[i] = line; -- file:write(line); -- file:write("\n"); -- end line = ""; end x1 = 9; x2 = 9; x3 = 9; local id1; local id2; for i = 1,14 do id1 = string.find(init_pos[i], "[%.%a]", 1); id2 = string.find(last_pos[i], "[%.%a]", 1); if ((id1 ~= nil) and (id2 ~= nil)) then first_x = math.min(first_x, math.min(id1, id2)); end id1 = string.find(init_pos[i], "[%.%a]", 1); -- reverse find if (id1 ~= nil) then local tmp = id1; while (tmp ~= nil) do tmp = string.find(init_pos[i], "[%.%a]", tmp+1); if (tmp ~= nil) then id1 = tmp end; end end id2 = string.find(last_pos[i], "[%.%a]", 1); -- reverse find if (id2 ~= nil) then local tmp = id2; while (tmp ~= nil) do tmp = string.find(last_pos[i], "[%.%a]", tmp+1); if (tmp ~= nil) then id2 = tmp end; end end if ((id1 ~= nil) and (id2 ~= nil)) then last_x = math.max(last_x, math.max(id1, id2)); end end first_y = 14; last_y = 0; local entered = 0; for i = 1,14 do if ((init_pos[i] == "#############") and (last_pos[i] == "#############")) then if (entered == 0) then first_y = i+1; else last_y = i-1; break; end else entered = 1; end end for i = first_y,last_y do file:write(string.sub(init_pos[i], first_x, last_x)); file:write("\n"); end file:write("\n"); for i = first_y,last_y do file:write(string.sub(last_pos[i], first_x, last_x)); file:write("\n"); end end io.close(); end end end -- get name of output file end make_move = function (move) local state = get_flag(); local id_cell = name_to_id(move); local n_pieces = 0; if (math.mod(id_cell, 14) == 1) then if (state >= 200) then state = 200; else state = 100; end end if (move == "PASS") then if (state < 200) then -- initial phase finished: -- put a mark over existing pieces -- not used colors are no longer available state = 200; for i = 1,196 do if ((math.mod(i, 14) ~= 1) and (id_get_pieces(i) ~= -1) and (id_get_pieces(i) <= 26)) then move_piece("mark_well", 1, cells[i], 2); end end else -- final phase finished -- save the puzzle! save_the_puzzle(); state = 0; end set_flag(state); else if ((state > 100) and (state <= 198)) then id_type = id_get_pieces(id_cell); if (id_type ~= -1) then if ((id_type >= 1) and (id_type <= 12)) then move_piece(move, "p" .. id_type .. "_well"); end if (id_type == 28) then move_piece(move, "soil_well"); end end if ((state >= 101) and (state <= 126)) then move_piece("p" .. state - 100 .. "_well", move); end if (state == 198) then move_piece("soil_well", move); end if (state == 197) then move_piece("wall_well", move); end end if ((state >= 201) and (state <= 226)) then n_pieces = id_get_n_pieces(id_cell); local pos = 1; pos = pos + n_pieces; if (pos == 4) then -- take away previous color local pp = {id_get_pieces(id_cell)}; id_type = pp[pos-1]; if ((id_type >= 1) and (id_type <= 26)) then move_piece(move, pos-1, "p" .. id_type .. "_well", 1); end if (id_type == 28) then move_piece(move, pos-1, "soil_well", 1); end pos = 3; end if ((pos == 2) or (pos == 3)) then move_piece("p" .. state - 200 .. "_well", 1, move, pos); -- if (state == 21) then move_piece("soil_well", 1, move, pos); end end end if (state == 199) then id_type = id_get_pieces(id_cell); if (id_type ~= -1) then if ((id_type >= 1) and (id_type <= 26)) then move_piece(move, "p" .. id_type .. "_well"); end if (id_type == 28) then move_piece(move, "soil_well"); end if (id_type == 32) then move_piece(move, "wall_well"); end end end if (state == 299) then local pp = {id_get_pieces(id_cell)}; n_pieces = id_get_n_pieces(id_cell); if (n_pieces == 3) then move_piece(move, 3, "p" .. pp[n_pieces] .. "_well", get_n_pieces("p" .. pp[n_pieces] .. "_well") + 1); end if ((n_pieces == 2) and (pp[n_pieces] ~= 31)) then move_piece(move, 2, "p" .. pp[n_pieces] .. "_well", get_n_pieces("p" .. pp[n_pieces] .. "_well") + 1); end end if ((state == 100) or (state == 200)) then id_type = id_get_pieces(id_cell); if (id_type ~= -1) then if ((id_type >= 1) and (id_type <= 26)) then state = state + id_type; end if ((id_type == 28) and (state == 100)) then state = 198; end if ((id_type == 32) and (state == 100)) then state = 197; end if (id_type == 27) then state = state + 99; end if (id_type == 29) then -- right arrow local flag_once = 0; if ((flag_once == 0) and (id_get_pieces(14*13+1) == 25)) then flag_once = 1; move_piece("a" .. 14, 1, "p" .. 25 .. "_well", get_n_pieces("p" .. 25 .. "_well")+1); move_piece("a" .. 13, 1, "p" .. 26 .. "_well", get_n_pieces("p" .. 26 .. "_well")+1); for i = 1,8 do move_piece("p" .. i .. "_well", get_n_pieces("p" .. i .. "_well"), "a" .. 14-i+1, 1); end end if ((flag_once == 0) and (id_get_pieces(14*13+1) == 17)) then flag_once = 1; for i = 1,8 do move_piece("a" .. 14-i+1, 1, "p" .. 16+i .. "_well", get_n_pieces("p" .. 16+i .. "_well")+1); end move_piece("p" .. 25 .. "_well", get_n_pieces("p" .. 25 .. "_well"), "a" .. 14, 1); move_piece("p" .. 26 .. "_well", get_n_pieces("p" .. 26 .. "_well"), "a" .. 13, 1); end if ((flag_once == 0) and (id_get_pieces(14*13+1) == 9)) then flag_once = 1; for i = 1,8 do move_piece("a" .. 14-i+1, 1, "p" .. 8+i .. "_well", get_n_pieces("p" .. 8+i .. "_well")+1); move_piece("p" .. 16+i .. "_well", get_n_pieces("p" .. 16+i .. "_well"), "a" .. 14-i+1, 1); end end if ((flag_once == 0) and (id_get_pieces(14*13+1) == 1)) then flag_once = 1; for i = 1,8 do move_piece("a" .. 14-i+1, 1, "p" .. i .. "_well", get_n_pieces("p" .. i .. "_well")+1); move_piece("p" .. 8+i .. "_well", get_n_pieces("p" .. 8+i .. "_well"), "a" .. 14-i+1, 1); end end end if (id_type == 30) then -- left arrow local flag_once = 0; if ((flag_once == 0) and (id_get_pieces(14*13+1) == 9)) then flag_once = 1; for i = 1,8 do move_piece("a" .. 14-i+1, 1, "p" .. 8+i .. "_well", get_n_pieces("p" .. 8+i .. "_well")+1); move_piece("p" .. i .. "_well", get_n_pieces("p" .. i .. "_well"), "a" .. 14-i+1, 1); end end if ((flag_once == 0) and (id_get_pieces(14*13+1) == 17)) then flag_once = 1; for i = 1,8 do move_piece("a" .. 14-i+1, 1, "p" .. 16+i .. "_well", get_n_pieces("p" .. 16+i .. "_well")+1); move_piece("p" .. 8+i .. "_well", get_n_pieces("p" .. 8+i .. "_well"), "a" .. 14-i+1, 1); end end if ((flag_once == 0) and (id_get_pieces(14*13+1) == 25)) then flag_once = 1; move_piece("a" .. 14, 1, "p" .. 25 .. "_well", get_n_pieces("p" .. 25 .. "_well")+1); move_piece("a" .. 13, 1, "p" .. 26 .. "_well", get_n_pieces("p" .. 26 .. "_well")+1); for i = 1,8 do move_piece("p" .. 16+i .. "_well", get_n_pieces("p" .. 16+i .. "_well"), "a" .. 14-i+1, 1); end end if ((flag_once == 0) and (id_get_pieces(14*13+1) == 1)) then flag_once = 1; for i = 1,8 do move_piece("a" .. 14-i+1, 1, "p" .. i .. "_well", get_n_pieces("p" .. i .. "_well")+1); end move_piece("p" .. 25 .. "_well", get_n_pieces("p" .. 25 .. "_well"), "a" .. 14, 1); move_piece("p" .. 26 .. "_well", get_n_pieces("p" .. 26 .. "_well"), "a" .. 13, 1); end end set_flag(state); end end end end valuation = function () val = {}; val[1] = 5000; return 1; end game_info = function () game_name = "SBP editor"; game_help = {}; game_help[ 1] = "Editor for Sliding Block Puzzles."; game_help[ 2] = "The editing take place in 2 phases:"; game_help[ 3] = "- draw the initial position;"; game_help[ 4] = "- draw the final position."; game_help[ 5] = "The edited puzzle will be saved as"; game_help[ 6] = "SBP_xxx.txt"; game_author = "JMM"; game_date = "Oct-Dec 2007"; game_movements = {}; game_movements[ 1] = "The first column is the menu."; game_movements[ 2] = "Click on a piece and where you want"; game_movements[ 3] = "to place it. The cross is the delete"; game_movements[ 4] = "tool. The circle is a wall. The arrows"; game_movements[ 5] = "show you different colours. The square"; game_movements[ 6] = "is the soil."; game_movements[ 7] = ""; game_movements[ 8] = "You can end the initial or the final"; game_movements[ 9] = "phase by clicking the PASS button."; game_movements[10] = ""; game_movements[11] = "When the initial phase is finished, a"; game_movements[12] = "red mark will cover placed pieces."; game_strategy = {}; game_strategy[ 1] = "Be creative!"; return 1; end init_graphics = function () board = "dot_square.bmp"; boardw = 1; boardh = 1; square_xy_grid(); for i = 1,29 do cellsx[14*14+i] = -1; cellsy[14*14+i] = -1; end 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"; -- recycling p9_bmp = "p_violet.bmp"; p10_bmp = "p_yellow.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_light_blue.bmp"; p19_bmp = "p_red.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_yellow.bmp"; cross_bmp = "cross.bmp"; soil_bmp = "square.bmp"; mark_bmp = "mark.bmp"; wall_bmp = "circle.bmp"; r_arrow_bmp = "p_light_blue_r_arrow.bmp"; l_arrow_bmp = "p_light_blue_l_arrow.bmp"; -- menu frame add_line(1.5, 0.5, 1.5, 14.5, 0, 0, 0); add_line(0.5, 0.5, 0.5, 14.5, 0, 0, 0); add_line(0.5, 0.5, 1.5, 0.5, 0, 0, 0); add_line(0.5, 14.5, 1.5, 14.5, 0, 0, 0); set_flag(100); -- first phase: draw initial position return 1; end control_mouse = function (x, y, historical) local res = 0; local state = get_flag(); if ((state == 100) or (state == 200)) then return click_piece(x, y, historical); else return click_cell(x, y, historical); end end