Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- random_fly_20.lua (OC Robot + hover)
- -- Стартуй на зарядке: это (0,0,0) и "база". Смотрим на север.
- -- Летает случайно в кубе 20x20x20 по +X/+Y/+Z, пикает, при <30% энергии возвращается на базу и ждёт до 95%.
- local robot = require("robot")
- local computer = require("computer")
- local os = require("os")
- ----------------------------------------------------------------
- -- Настройки
- ----------------------------------------------------------------
- local BOUNDS = {x=20,y=20,z=20}
- local ENERGY_LOW = 0.30
- local ENERGY_FULL = 0.95
- local STEP_DELAY = 0.05
- local BEEP_EVERY = 25 -- шагов
- -- Направления (старт см. на Север). Север=-Z, Восток=+X, Юг=+Z, Запад=-X
- local DIRS = {N=0,E=1,S=2,W=3}
- local dir = DIRS.N
- -- Координаты (от базы)
- local pos = {x=0,y=0,z=0}
- local base = {x=0,y=0,z=0}
- ----------------------------------------------------------------
- -- Безопасные бипы (не падают на старых версиях OC)
- ----------------------------------------------------------------
- local function safeBeep(a,b)
- if type(a)=="table" then
- for i=1,#a do
- local n=a[i]; local f=tonumber(n[1]) or 0; local d=tonumber(n[2]) or 0.1
- pcall(computer.beep,f,d); os.sleep(d+0.01)
- end
- else
- pcall(computer.beep, tonumber(a) or 0, tonumber(b) or 0.1)
- end
- end
- local function beep_tick() safeBeep(1200,0.03) end
- local function beep_warn() safeBeep({{659,0.12},{0,0.05},{659,0.12}}) end
- local function beep_ok() safeBeep({{1046,0.06},{1318,0.08}}) end
- local function beep_start() safeBeep({{880,0.08},{988,0.08},{1046,0.12}}) end
- local function beep_home() safeBeep({{784,0.08},{659,0.08},{523,0.12}}) end
- local function beep_err() safeBeep({{220,0.20},{196,0.20}}) end
- ----------------------------------------------------------------
- -- Энергия
- ----------------------------------------------------------------
- local function energy()
- local m = computer.maxEnergy() or 1
- local e = computer.energy() or 0
- if m<=0 then return 1 end
- return e/m
- end
- ----------------------------------------------------------------
- -- Повороты/шаги (минимум вложенности)
- ----------------------------------------------------------------
- local function turnLeft() local ok=robot.turnLeft(); if ok then dir=(dir+3)%4 end; return ok end
- local function turnRight() local ok=robot.turnRight(); if ok then dir=(dir+1)%4 end; return ok end
- local function face(t)
- t = t % 4
- local n=0
- while dir ~= t and n < 4 do
- turnRight(); n = n + 1
- end
- end
- local function stepForward()
- if robot.forward() then
- if dir==DIRS.N then pos.z=pos.z-1
- elseif dir==DIRS.S then pos.z=pos.z+1
- elseif dir==DIRS.E then pos.x=pos.x+1
- else pos.x=pos.x-1
- end
- return true
- end
- return false
- end
- local function stepBack()
- if robot.back() then
- if dir==DIRS.N then pos.z=pos.z+1
- elseif dir==DIRS.S then pos.z=pos.z-1
- elseif dir==DIRS.E then pos.x=pos.x-1
- else pos.x=pos.x+1
- end
- return true
- end
- return false
- end
- local function stepUp() if robot.up() then pos.y=pos.y+1 return true end return false end
- local function stepDown() if robot.down() then pos.y=pos.y-1 return true end return false end
- ----------------------------------------------------------------
- -- Навигация
- ----------------------------------------------------------------
- local function clamp(p)
- if p.x<0 then p.x=0 elseif p.x>=BOUNDS.x then p.x=BOUNDS.x-1 end
- if p.y<0 then p.y=0 elseif p.y>=BOUNDS.y then p.y=BOUNDS.y-1 end
- if p.z<0 then p.z=0 elseif p.z>=BOUNDS.z then p.z=BOUNDS.z-1 end
- end
- local function moveTo(t)
- clamp(t)
- -- Y
- while pos.y < t.y do
- if energy()<ENERGY_LOW then return false,"low_energy" end
- if not stepUp() then return false,"blocked_y_up" end
- os.sleep(STEP_DELAY)
- end
- while pos.y > t.y do
- if energy()<ENERGY_LOW then return false,"low_energy" end
- if not stepDown() then return false,"blocked_y_down" end
- os.sleep(STEP_DELAY)
- end
- -- X
- while pos.x < t.x do
- if energy()<ENERGY_LOW then return false,"low_energy" end
- face(DIRS.E); if not stepForward() then return false,"blocked_x_pos" end
- os.sleep(STEP_DELAY)
- end
- while pos.x > t.x do
- if energy()<ENERGY_LOW then return false,"low_energy" end
- face(DIRS.W); if not stepForward() then return false,"blocked_x_neg" end
- os.sleep(STEP_DELAY)
- end
- -- Z
- while pos.z < t.z do
- if energy()<ENERGY_LOW then return false,"low_energy" end
- face(DIRS.S); if not stepForward() then return false,"blocked_z_pos" end
- os.sleep(STEP_DELAY)
- end
- while pos.z > t.z do
- if energy()<ENERGY_LOW then return false,"low_energy" end
- face(DIRS.N); if not stepForward() then return false,"blocked_z_neg" end
- os.sleep(STEP_DELAY)
- end
- return true
- end
- local function goHome()
- io.write(string.format("[HOME] -> (%d,%d,%d)\n", base.x,base.y,base.z))
- local ok,why = moveTo(base)
- if not ok then io.write("[HOME] fail: "..tostring(why).."\n"); beep_err(); return false end
- beep_home(); io.write("[HOME] charging...\n")
- while energy() < ENERGY_FULL do os.sleep(0.5) end
- io.write("[HOME] charged\n"); beep_ok(); return true
- end
- ----------------------------------------------------------------
- -- Цель и основной цикл
- ----------------------------------------------------------------
- local function randomTarget()
- return {x=math.random(0,BOUNDS.x-1), y=math.random(0,BOUNDS.y-1), z=math.random(0,BOUNDS.z-1)}
- end
- math.randomseed(os.time())
- beep_start()
- io.write("[INIT] Куб 20x20x20 от базы по +X/+Y/+Z. Старт на зарядке, смотрим на Север.\n")
- local steps=0
- while true do
- if energy() < ENERGY_LOW then beep_warn(); goHome() end
- local t = randomTarget()
- io.write(string.format("[MOVE] -> (%d,%d,%d)\n", t.x,t.y,t.z))
- local ok,why = moveTo(t)
- if ok then
- io.write(string.format("[MOVE] at (%d,%d,%d)\n", pos.x,pos.y,pos.z))
- else
- io.write("[WARN] move fail: "..tostring(why).."\n")
- end
- steps=steps+1
- if steps % BEEP_EVERY == 0 then beep_tick() end
- os.sleep(0.05)
- end
Advertisement
Add Comment
Please, Sign In to add comment