mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-20 19:19:21 +01:00
442 lines
16 KiB
Lua
442 lines
16 KiB
Lua
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()
|
||
------------------------------------------------------------------------------------- |