MineOS/Applications/QuantumCube/QuantumCube.lua
Igor Timofeev cffb11c141 aaaefaef
2016-01-12 20:01:30 +03:00

442 lines
16 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()
-------------------------------------------------------------------------------------