diff --git a/Applications/QuantumQube/Icon.pic b/Applications/QuantumQube/Icon.pic new file mode 100644 index 00000000..07de54f6 Binary files /dev/null and b/Applications/QuantumQube/Icon.pic differ diff --git a/Applications/QuantumQube/QuantumCube.lua b/Applications/QuantumQube/QuantumCube.lua new file mode 100644 index 00000000..726b160e --- /dev/null +++ b/Applications/QuantumQube/QuantumCube.lua @@ -0,0 +1,442 @@ +local os = require("os") +local term = require("term") +local event = require("event") +local component = require("component") +local gpu = component.gpu +math.randomseed(os.time()) +local version = "Cube v1.0" +local level = {} +local doors = {} +local indicator={} +local nick_player +local markColor = {0xff0000, 0xffff00, 0x00ff00, 0x00ffff, 0x0000ff, 0xff00ff, 0xffffff} +local playerColor = 3 +local sx,sy = gpu.getResolution() +sx, sy = math.modf(sx/4), math.modf(sy/2) -- точка отступа/координата игрока на экране (статичные)/центр событий +local px,py = 3,3 -- относительные координаты игрока в комнате +local min_map, max_map = 1, 1000 -- ограничители номеров комнат, чтобы сильно не запутаться при прохождении +level[1] = {number=1, color = 0xffffff, mark=false} -- цель игры - попасть в эту комнату +------------------------------------------------------------------------------------- +----------------------- Генерация случайных формул для дверей ----------------------- +local rand_1, rand_2 ,rand_3, rand_4 +while true do + rand_1, rand_2 ,rand_3, rand_4 = math.random(1,2), math.random(10,30), math.random(1,2), math.random(10,30) + if rand_1~=rand_3 and rand_2~=rand_4 then break end +end +formula={} +formula[1]=function(n) return n*rand_1 + rand_2 end +formula[2]=function(n) return n*rand_3 + rand_4 end +formula[-1]=function(n) return (n - rand_2)/rand_1 end +formula[-2]=function(n) return (n - rand_4)/rand_3 end +------------------------------------------------------------------------------------- +---------------------- Возвращает или генерирует новую комнату ---------------------- +function gen_level(i) + i = tonumber(i) + if not level[i] then + level[i]={number=i, color = math.random(0x000000, 0xffffff), mark=false} + end + return level[i] +end +------------------------------------------------------------------------------------- +-------------------------- Проверка, существует ли комната -------------------------- +function proverka(x,y) -- где x номер формулы, y номер текущей комнаты + local number = formula[x](y) + return number >= min_map and number <= max_map and number == math.modf(number) +end +------------------------------------------------------------------------------------- +---------------------------- Генерация статистики комнат ---------------------------- +function sorting(sorting_table, not_sorting_table) + local trash_table={} + while true do + if #not_sorting_table==0 then + break + else + local new_level = not_sorting_table[1] + local power = true + for i=1, #sorting_table do + if sorting_table[i][1]== new_level[1] then + power = false + if new_level[2] < sorting_table[i][2] then + sorting_table[i][2]=new_level[2] + if proverka(1,new_level[1]) then + trash_table[#trash_table+1] = {formula[1](new_level[1]), new_level[2]+1} + end + if proverka(2,new_level[1]) then + trash_table[#trash_table+1] = {formula[2](new_level[1]), new_level[2]+1} + end + if proverka(-1,new_level[1]) then + trash_table[#trash_table+1] = {formula[-1](new_level[1]), new_level[2]+1} + end + if proverka(-2,new_level[1]) then + trash_table[#trash_table+1] = {formula[-2](new_level[1]), new_level[2]+1} + end + end + table.remove(not_sorting_table,1) + end + end + if power then + sorting_table[#sorting_table+1] = new_level + table.remove(not_sorting_table,1) + if proverka(1,new_level[1]) then + not_sorting_table[#not_sorting_table+1] = {formula[1](new_level[1]), new_level[2]+1} + end + if proverka(2,new_level[1]) then + not_sorting_table[#not_sorting_table+1] = {formula[2](new_level[1]), new_level[2]+1} + end + if proverka(-1,new_level[1]) then + not_sorting_table[#not_sorting_table+1] = {formula[-1](new_level[1]), new_level[2]+1} + end + if proverka(-2,new_level[1]) then + not_sorting_table[#not_sorting_table+1] = {formula[-2](new_level[1]), new_level[2]+1} + end + end + end + end + return sorting_table, trash_table +end + +-- первая сортировка +local not_sorting_tb, trash_tb={} +not_sorting_tb[1]={1,0} +local sorting_tb, trash_tb = sorting({}, not_sorting_tb) + +-- последующие сортировки +while true do + not_sorting_tb = trash_tb + sorting_tb, trash_tb = sorting(sorting_tb, not_sorting_tb) + if #trash_tb == 0 then break end +end + +-- очищаем память +not_sorting_tb, trash_tb = nil, nil + +-- перестраиваем таблицу +local stat_table={} +for i=1, #sorting_tb do + stat_table[sorting_tb[i][1]]=sorting_tb[i][2] +end +------------------------------------------------------------------------------------- +------------------ Находим номер самой удалённой комнаты от выхода ------------------ +local j=1 +for i=1, #sorting_tb do + if sorting_tb[i][2]>sorting_tb[j][2] then + j=i + end +end +------------------------------------------------------------------------------------- +----------------------- Устанавливаем номер стартовой комнаты ----------------------- +local chamber = gen_level(sorting_tb[j][1]) + +-- запишем количество комнат в игре +local max_table, max_level = #sorting_tb, sorting_tb[j][2] + +-- удалим из памяти ненужную таблицу +sorting_tb = nil +------------------------------------------------------------------------------------- +--------------------------- Переставляет двери в комнате ---------------------------- +function reload_doors() + local rezerv={} + for i=1,4 do -- занесём двери в базу данных, чтобы знать использованные формулы + if doors[i] then + rezerv[#rezerv+1]=doors[i] + end + end + for i=1,4 do -- перебираем все 4 двери + if not doors[i] then + while true do + local rand = math.random(-2,2) + local rezerv_2 = 0 + if rand ~= 0 then + if #rezerv > 0 then -- проверка, есть ли комната с такой же формулой + for j=1, #rezerv do + if rezerv[j] == rand then break else rezerv_2 = rezerv_2 + 1 end + end + end + if rezerv_2 == #rezerv then -- если нет повторяющихся формул, то присваивается данная формула + doors[i] = rand + rezerv[#rezerv+1]=rand + break + end + end + end + end + end +end +-- //данная функция достаточно сложна чтобы запутаться +------------------------------------------------------------------------------------- +---------------------------------- Рисования меток ---------------------------------- +function mark_print(nx, ny, number) + if level[number].mark then + for i=1, #level[number].mark do + gpu.setBackground(level[number].mark[i][3]) + gpu.set((level[number].mark[i][1]+nx)*2, level[number].mark[i][2]+ny, " ") + end + end +end +------------------------------------------------------------------------------------- +------------------------- Рисования комнаты по координатам -------------------------- +function level_print(nx, ny, color, number) + number = tostring(number) + gpu.setBackground(color) + gpu.set(nx*2, ny, " ") + gpu.set((nx+4)*2, ny, " ") + gpu.set(nx*2, ny+6, " ") + gpu.set((nx+4)*2, ny+6, " ") + + gpu.set(nx*2, ny+1, " ") + gpu.set(nx*2, ny+2, " ") + gpu.set(nx*2, ny+4, " ") + gpu.set(nx*2, ny+5, " ") + gpu.set((nx+6)*2, ny+1, " ") + gpu.set((nx+6)*2, ny+2, " ") + gpu.set((nx+6)*2, ny+4, " ") + gpu.set((nx+6)*2, ny+5, " ") + + gpu.setBackground(0x000000) + gpu.set(nx*2+6-math.modf((string.len(number)-1)/2), ny+3, number) +end +------------------------------------------------------------------------------------- +----------------------------- Переходы между комнатами ------------------------------ +pxx, pyy = {}, {} +pxx[-1]=function(nx) + local rezerv_3 = doors[1] + if proverka(rezerv_3, chamber.number) then + doors={} + doors[2] = -rezerv_3 + reload_doors() + chamber = gen_level(formula[rezerv_3](chamber.number)) + ppx = 6 + else + ppx = px + end +end +pxx[7]=function(nx) + local rezerv_3 = doors[2] + if proverka(rezerv_3, chamber.number) then + doors={} + doors[1] = -rezerv_3 + reload_doors() + chamber = gen_level(formula[rezerv_3](chamber.number)) + ppx = 0 + else + ppx = px + end +end +pyy[-1]=function(ny) + local rezerv_3 = doors[3] + if proverka(rezerv_3, chamber.number) then + doors={} + doors[4] = -rezerv_3 + reload_doors() + chamber = gen_level(formula[rezerv_3](chamber.number)) + ppy = 6 + else + ppy = py + end +end +pyy[7]=function(ny) + local rezerv_3 = doors[4] + if proverka(rezerv_3, chamber.number) then + doors={} + doors[3] = -rezerv_3 + reload_doors() + chamber = gen_level(formula[rezerv_3](chamber.number)) + ppy = 0 + else + ppy = py + end +end +-- //работает как надо, но лучше подредактировать +------------------------------------------------------------------------------------- +-------------------------------- Передвижение игрока -------------------------------- +function player_update(nx,ny) + ppx, ppy = px+nx, py+ny + if not ((ppx==0 or ppy==0 or ppx==6 or ppy==6) and ppx~=3 and ppy~=3) then + if pxx[ppx] then pxx[ppx](ppx) + elseif pyy[ppy] then pyy[ppy](ppy) + end + px,py = ppx,ppy + end +end +-- //работает как надо, но лучше подредактировать +------------------------------------------------------------------------------------- +--------------------------------- Блок отображения ---------------------------------- +function update(nick) + nick_player = nick + term.clear() + + -- текущая комната + gen_level(chamber.number) + mark_print(sx-px,sy-py, chamber.number) + level_print(sx-px,sy-py,chamber.color, chamber.number) + + -- комната слева + if proverka(doors[1], chamber.number) and px==0 then + local number = formula[doors[1]](chamber.number) + gen_level(number) + mark_print(sx-7-px,sy-py, number) + level_print(sx-7-px,sy-py,gen_level(formula[doors[1]](chamber.number)).color, gen_level(formula[doors[1]](chamber.number)).number) + end + + -- комната справа + if proverka(doors[2], chamber.number) and px==6 then + local number = formula[doors[2]](chamber.number) + gen_level(number) + mark_print(sx+7-px,sy-py, number) + level_print(sx+7-px,sy-py,gen_level(formula[doors[2]](chamber.number)).color, gen_level(formula[doors[2]](chamber.number)).number) + end + + -- комната сверху + if proverka(doors[3], chamber.number) and py==0 then + local number = formula[doors[3]](chamber.number) + gen_level(number) + mark_print(sx-px,sy-7-py, number) + level_print(sx-px,sy-7-py,gen_level(formula[doors[3]](chamber.number)).color, gen_level(formula[doors[3]](chamber.number)).number) + end + + -- комната снизу + if proverka(doors[4], chamber.number) and py==6 then + local number = formula[doors[4]](chamber.number) + gen_level(number) + mark_print(sx-px,sy+7-py, number) + level_print(sx-px,sy+7-py,gen_level(formula[doors[4]](chamber.number)).color, number) + end + + -- отображение игрока + gpu.setBackground(0xff0000) + gpu.set(sx*2, sy, " ") + + -- текстовые индикаторы + for i=1, #indicator do + indicator[i]() + end + + -- индикатор выбранного цвета + gpu.setBackground(markColor[playerColor]) + gpu.set(2, sy*2, " ") +end +------------------------------------------------------------------------------------- +---------------------------------- Блок управления ---------------------------------- +local command={} +command[200]=function() player_update(0,-1) end -- вверх +command[208]=function() player_update(0,1) end -- вниз +command[203]=function() player_update(-1,0) end -- влево +command[205]=function() player_update(1,0) end -- вправо +command[17]=function() -- ставить метку + if not level[chamber.number].mark then level[chamber.number].mark={} end + level[chamber.number].mark[#level[chamber.number].mark+1]={px,py,markColor[playerColor]} + end +command[30]=function() if playerColor-1<1 then playerColor=#markColor else playerColor=playerColor-1 end end -- цвет слева +command[32]=function() if playerColor+1>#markColor then playerColor=1 else playerColor=playerColor+1 end end -- цвет справа +command[31]=function() -- удалить метку + if level[chamber.number].mark then + for i=#level[chamber.number].mark, 1, -1 do + if px==level[chamber.number].mark[i][1] and py==level[chamber.number].mark[i][2] then + table.remove(level[chamber.number].mark,i) + end + end + end + end +command[23]=function() -- включает режим разработчика + if #indicator==0 then + indicator[1]=function() + gpu.setBackground(0x000000) + gpu.setForeground(0xffff00) + gpu.set(2, 2, "max level: "..max_level) + gpu.set(2, 3, "all levels: "..max_table) + gpu.set(2, 4, "this level: "..stat_table[chamber.number]) + gpu.setForeground(0xff0000) + gpu.set(2, 5, "formula 1: ".."n".."*"..rand_1.." + "..rand_2) + gpu.set(2, 6, "formula 2: ".."n".."*"..rand_3.." + "..rand_4) + gpu.set(2, 7, "formula -1: ".."(n - "..rand_2..")/"..rand_1) + gpu.set(2, 8, "formula -2: ".."(n - "..rand_4..")/"..rand_3) + gpu.setForeground(0xff00ff) + gpu.set(2, 9, "progress: " .. math.modf(100-stat_table[chamber.number]*100/max_level).."%") + gpu.setForeground(0xff00ff) + gpu.set(2, 10, "color: "..playerColor) + gpu.setForeground(0xffffff) + end + else + table.remove(indicator,1) + end +end +command[35]=function() -- отобразить управление + term.clear() + gpu.setForeground(0xff0000) + print(version) + print("") + gpu.setForeground(0x00ff00) + print("Target: searching chamber 1") + print("Game 100% passable") + gpu.setForeground(0xffff00) + print("Control:") + print("Q - exit game") + print("H - help") + print("I - info") + print("W - set mark") + print("S - remove mark") + print("A - back color mark") + print("D - next color mark") + print("") + gpu.setForeground(0xffffff) + print("press enter to continue...") + while true do + _,_,_, key = event.pull("key_down") + if key == 28 then + break + end + end +end +------------------------------------------------------------------------------------- +---------------------- Показываем управление до начала игры ------------------------- +command[35]() +------------------------------------------------------------------------------------- +------------------------- Отображение комнат до начала игры ------------------------- +reload_doors() +update(nick) +gpu.setBackground(0x000000) +------------------------------------------------------------------------------------- +------------------------------------- Тело игры ------------------------------------- +while true do + _,_,_, key, nick = event.pull("key_down") + if key==16 then + term.clear() + gpu.setForeground(0xff0000) + print("Exit to game?") + gpu.setForeground(0xffffff) + print("") + print("y/n") + while true do + _,_,_, key = event.pull("key_down") + if key == 21 then + term.clear() + return + elseif key == 49 then + break + end + end + elseif command[key] then + command[key]() + end + update(nick) + gpu.setBackground(0x000000) + if chamber.number == 1 then break end -- цель игры, комната с этим номером + os.sleep(1/15) -- задержка, для более удобного управления +end +------------------------------------------------------------------------------------- +------------------------------------- Прощание ------------------------------------- +term.clear() +gpu.setForeground(0x00ff00) +print("Congratulations "..nick_player.."!") +print("You win!") +print("") +gpu.setForeground(0xffffff) +print("press enter to exit...") +while true do + _,_,_, key = event.pull("key_down") + if key == 28 then + break + end +end +term.clear() +------------------------------------------------------------------------------------- \ No newline at end of file