· 6 years ago · Mar 06, 2019, 10:14 PM
1
2term.clear()
3--Variables
4local bck = paintutils.loadImage("bckgrnd.nfp")
5local but = paintutils.loadImage("clcbox.nfp")
6
7--
8--Functions
9function Paintclick()
10term.clear()
11print("What name")
12print("To Exit type")
13print("exit")
14text1 = read()
15if text1 == "" then
16print("Invalid name!")
17sleep(1)
18Paintclick()
19elseif text1 == "exit" or text1 == "Exit" then
20os.run({}, "home.lua")
21else
22shell.run("paint", read())
23end
24end
25
26function security()
27term.clear()
28print("Password required!")
29password1 = read()
30if password1 == "2056" then
31print("Access Granted")
32term.clear()
33print("Sec options")
34print("1 to deploy sentries")
35print("2 to deploy traps")
36print("3 to deploy all")
37print("4 to retract sentries")
38print("5 to retract traps")
39print("6 to retract all")
40print("To exit type exit")
41text2 = read()
42if text2 == "1" then
43print("deploying sentries")
44rednet.broadcast("sent_act")
45sleep(1)
46security()
47elseif text2 == "2" then
48print("deploying traps")
49rednet.broadcast("trap_act")
50sleep(1)
51security()
52elseif text2 == "3" then
53print("deploying all")
54rednet.broadcast("sent_act")
55rednet.broadcast("trap_act")
56sleep(1)
57security()
58elseif text2 == "4" then
59print("retracting sentries")
60rednet.broadcast("sent_dea")
61sleep(1)
62security()
63elseif text2 == "5" then
64print("retracting traps")
65rednet.broadcast("trap_dea")
66sleep(1)
67security()
68elseif text2 == "6" then
69print("retracting all")
70rednet.broadcast("sent_dea")
71rednet.broadcast("trap_dea")
72sleep(1)
73security()
74elseif text2 == "exit" or text2 == "Exit" then
75shell.run("home.lua")
76else
77print("Invalid Command!")
78print("Re-Verifing Identity!")
79sleep(2)
80security()
81end
82else
83print("Access Denied!")
84sleep(1)
85print("Hint: Portal stories: mel")
86sleep(1)
87security()
88end
89end
90function background()
91
92local tabid = multishell.launch({}, "paint bckgrnd")
93
94multishell.setTitle(tabid, "Worm")
95end
96--
97
98function loadSHIT()
99--descriptions
100term.setBackgroundColor(colors.lightBlue)
101term.setTextColor(colors.black)
102term.setCursorPos(1,4)
103term.write("Pnt")
104term.setCursorPos(5,4)
105term.write("Clc")
106term.setCursorPos(9,4)
107term.write("Adv")
108term.setCursorPos(9,3)
109term.setTextColor(colors.white)
110term.write("/-\\")
111term.setCursorPos(9,2)
112term.write("|-|")
113term.setCursorPos(9,1)
114term.write("| |")
115term.setTextColor(colors.black)
116term.setCursorPos(13,4)
117term.write("Sec")
118term.setCursorPos(14,2)
119term.write("!")
120term.setCursorPos(17,4)
121term.write("Rbt")
122term.setCursorPos(18,2)
123term.setTextColor(colors.white)
124term.write("L")
125term.setTextColor(colors.black)
126term.setCursorPos(21,4)
127term.write("Snk")
128term.setCursorPos(22,1)
129term.setTextColor(colors.white)
130term.write(":")
131term.setTextColor(colors.black)
132term.setCursorPos(1,8)
133term.write("Bck")
134term.setCursorPos(5,8)
135term.write("Cht")
136term.setCursorPos(9,8)
137term.write("248")
138term.setCursorPos(9,7)
139term.setTextColor(colors.white)
140term.write("LLL")
141term.setCursorPos(9,7)
142term.write("LLL")
143term.setCursorPos(9,7)
144term.write("LLL")
145term.setTextColor(colors.black)
146term.setCursorPos(13,8)
147term.write("Lua")
148term.setCursorPos(13,5)
149term.write("IDE")
150term.setCursorPos(13,6)
151term.write("1")
152term.setCursorPos(13,7)
153term.write("2")
154term.setCursorPos(17,8)
155term.write("M2D")
156term.setCursorPos(21,8)
157term.write("M3D")
158term.setTextColor(colors.white)
159term.setBackgroundColor(colors.black)
160paintutils.drawImage(bck, 1, 1)
161end
162function game()
163-- 2048
164-- Clone by Richard (Rich73)
165-- Hacked together 10/04/2014
166
167g = { }
168tiles = { }
169tiles[1] = {" ", 1}
170tiles[2] = {" 2 ", 2}
171tiles[3] = {" 4 ", 4}
172tiles[4] = {" 8 ", 8}
173tiles[5] = {" 16 ", 16}
174tiles[6] = {" 32 ", 32}
175tiles[7] = {" 64 ", 64}
176tiles[8] = {"128 ", 128}
177tiles[9] = {"256 ", 256}
178tiles[10] = {"512 ", 512}
179tiles[11] = {"1024", 1024}
180tiles[12] = {"2048", 2048}
181tiles[13] = {"4096", 4092}
182tiles[14] = {"8192", 8192}
183bg = "icon"
184size = 4
185score = 0
186hiscore = 0
187
188function createBoard()
189 for i=1, size do
190 g[i] = { }
191 for j=1, size do
192 g[i][j] = 0
193 end
194 end
195 for j=1, 2 do
196 local x, y = findEmptyPos()
197 g[y][x] = 1
198 end
199end
200
201function getRandomPos()
202 return math.random(size), math.random(size)
203end
204
205function findEmptyPos()
206 while true do
207 x, y = getRandomPos()
208 if g[y][x] == 0 then return x, y end
209 end
210end
211
212function isFull()
213 local full = true
214 for i=1, size do
215 for j=1, size do
216 if g[i][j] == 0 then full = false end
217 end
218 end
219 return full
220end
221
222function canMove()
223 if not isFull() then return true end
224 local pr = nil
225 for i=1, size do
226 local k = 1
227 while k <= size do
228 if k~=size and g[i][k] == g[i][k+1] or false then break end
229 if pr and g[i][k] == pr[k] or false then break end
230 k = k + 1
231 end
232 if k ~= size+1 then return true end
233 pr = g[i]
234 end
235 return false
236end
237
238function moveLeft()
239 for i=1, size do
240 for j=2, size do
241 local k = j
242 while k > 1 do
243 if g[i][k] == 0 then break
244 elseif g[i][k] == g[i][k-1] then
245 g[i][k-1] = g[i][k] + 1
246 g[i][k] = 0
247 score = score + math.pow(2,g[i][k-1])
248 k = k-1
249 elseif g[i][k-1] == 0 then
250 g[i][k-1] = g[i][k]
251 g[i][k] = 0
252 else break end
253 k = k-1
254 end
255 end
256 end
257end
258
259function moveUp()
260 for j=1, size do
261 for i=2, size do
262 local k = i
263 while k > 1 do
264 if g[k][j] == 0 then break
265 elseif g[k][j] == g[k-1][j] then
266 g[k-1][j] = g[k][j] + 1
267 g[k][j] = 0
268 score = score + math.pow(2,g[k-1][j])
269 k = k-1
270 elseif g[k-1][j] == 0 then
271 g[k-1][j] = g[k][j]
272 g[k][j] = 0
273 else break end
274 k = k-1
275 end
276 end
277 end
278end
279
280function moveRight()
281 flipX()
282 moveLeft()
283 flipX()
284end
285
286function moveDown()
287 flipY()
288 moveUp()
289 flipY()
290end
291
292function drawBoard()
293 term.setBackgroundColor(colors.black)
294 term.clear()
295 term.setTextColor(colors.white)
296 for x=1, size do
297 for y=1, size do
298 term.setCursorPos(x*5-1,y*4-2)
299 term.setBackgroundColor(tiles[g[y][x]+1][2])
300 term.write("/---\\")
301 term.setCursorPos(x*5-1,y*4-1)
302 term.write("| |")
303 term.setCursorPos(x*5-1,y*4-1)
304 term.write(tiles[g[y][x]+2][1])
305 term.setCursorPos(x*5-1,y*4+1)
306 term.write("\\___/")
307 term.setCursorPos(x*5-1,y*4)
308 term.write("| |")
309 end
310 end
311 term.setCursorPos(4,18)
312 term.setBackgroundColor(colors.black)
313 term.write("Score: "..score)
314 drawScores()
315end
316
317function drawScores()
318 term.setCursorPos(4,18)
319 term.setBackgroundColor(colors.black)
320 term.write(" Score: "..score)
321 term.setCursorPos(4,19)
322 term.write("HiScore: "..hiscore)
323end
324
325function drawHome()
326 term.clear()
327 im = paintutils.loadImage("bg.nfp")
328 paintutils.drawImage(im,2,2)
329end
330
331function table.reverse(tab)
332 local newtab = { }
333 for i=1, #tab do
334 newtab[#tab+1-i] = tab[i]
335 end
336 return newtab
337end
338
339function flipX()
340 for i=1, size do
341 g[i] = table.reverse(g[i])
342 end
343end
344
345function flipY()
346 g = table.reverse(g)
347end
348
349function update()
350 drawBoard()
351 if not isFull() then
352 local x, y = findEmptyPos()
353 g[y][x] = 1
354 end
355 os.sleep(0.075)
356end
357
358function newGame()
359 if score > hiscore then
360 hiscore = score
361 end
362 score = 0
363 term.setCursorPos(9,18)
364 term.setBackgroundColor(colors.white)
365 term.setTextColor(colors.black)
366 term.clearLine()
367 term.write("GAME OVER!")
368 term.setCursorPos(8,19)
369 term.clearLine()
370 term.write("New game? y/n")
371 while true do
372 local event, key = os.pullEvent("key")
373 if event=="key" then
374 if key==keys.y then return true end
375 if key==keys.n then return false end
376 end
377 end
378end
379
380drawHome()
381
382os.sleep(2)
383while true do
384 createBoard()
385 while canMove() do
386 drawBoard()
387 event, key = os.pullEvent("key")
388 if event == "key" then
389 if key == keys.left then moveLeft()
390 elseif key == keys.right then
391 moveRight()
392 update()
393 elseif key == keys.up then
394 moveUp()
395 update()
396 elseif key == keys.down then
397 moveDown()
398 update()
399 elseif key == keys.q then
400 break
401 elseif key == keys.backspace then
402 shell.run("home")
403 end
404 end
405 end
406 drawBoard()
407 if not newGame() then
408 term.setBackgroundColor(colors.black)
409 term.setTextColor(colors.white)
410 term.clear()
411 term.setCursorPos(1,1)
412 break
413 end
414end
415end
416function luaide()
417
418--
419-- Lua IDE
420-- Made by GravityScore
421--
422
423
424-- -------- Variables
425
426-- Version
427local version = "1.0"
428local args = {}
429
430-- Editing
431local w, h = term.getSize()
432local tabWidth = 2
433
434local autosaveInterval = 20
435local allowEditorEvent = true
436local keyboardShortcutTimeout = 0.4
437
438-- Clipboard
439local clipboard = nil
440
441-- Theme
442local theme = {}
443
444-- Language
445local languages = {}
446local curLanguage = {}
447
448-- Events
449local event_distract = "luaide_distractionEvent"
450
451-- Locations
452--local updateURL = "https://raw.github.com/GravityScore/LuaIDE/master/luaide.lua"
453local ideLocation = "/" .. shell.getRunningProgram()
454local themeLocation = "/.LuaIDE-Theme"
455
456local function isAdvanced() return term.isColor and term.isColor() end
457
458
459-- -------- Utilities
460
461local function modRead(properties)
462 local w, h = term.getSize()
463 local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil,
464 liveUpdates = nil, exitOnKey = nil}
465 if not properties then properties = {} end
466 for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end
467 if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end
468 if not properties.visibleLength then properties.visibleLength = w end
469
470 local sx, sy = term.getCursorPos()
471 local line = ""
472 local pos = 0
473 local historyPos = nil
474
475 local function redraw(repl)
476 local scroll = 0
477 if properties.visibleLength and sx + pos > properties.visibleLength + 1 then
478 scroll = (sx + pos) - (properties.visibleLength + 1)
479 end
480
481 term.setCursorPos(sx, sy)
482 local a = repl or properties.replaceChar
483 if a then term.write(string.rep(a, line:len() - scroll))
484 else term.write(line:sub(scroll + 1, -1)) end
485 term.setCursorPos(sx + pos - scroll, sy)
486 end
487
488 local function sendLiveUpdates(event, ...)
489 if type(properties.liveUpdates) == "function" then
490 local ox, oy = term.getCursorPos()
491 local a, data = properties.liveUpdates(line, event, ...)
492 if a == true and data == nil then
493 term.setCursorBlink(false)
494 return line
495 elseif a == true and data ~= nil then
496 term.setCursorBlink(false)
497 return data
498 end
499 term.setCursorPos(ox, oy)
500 end
501 end
502
503 term.setCursorBlink(true)
504 while true do
505 local e, but, x, y, p4, p5 = os.pullEvent()
506
507 if e == "char" then
508 local s = false
509 if properties.textLength and line:len() < properties.textLength then s = true
510 elseif not properties.textLength then s = true end
511
512 local canType = true
513 if not properties.grantPrint and properties.refusePrint then
514 local canTypeKeys = {}
515 if type(properties.refusePrint) == "table" then
516 for _, v in pairs(properties.refusePrint) do
517 table.insert(canTypeKeys, tostring(v):sub(1, 1))
518 end
519 elseif type(properties.refusePrint) == "string" then
520 for char in properties.refusePrint:gmatch(".") do
521 table.insert(canTypeKeys, char)
522 end
523 end
524 for _, v in pairs(canTypeKeys) do if but == v then canType = false end end
525 elseif properties.grantPrint then
526 canType = false
527 local canTypeKeys = {}
528 if type(properties.grantPrint) == "table" then
529 for _, v in pairs(properties.grantPrint) do
530 table.insert(canTypeKeys, tostring(v):sub(1, 1))
531 end
532 elseif type(properties.grantPrint) == "string" then
533 for char in properties.grantPrint:gmatch(".") do
534 table.insert(canTypeKeys, char)
535 end
536 end
537 for _, v in pairs(canTypeKeys) do if but == v then canType = true end end
538 end
539
540 if s and canType then
541 line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)
542 pos = pos + 1
543 redraw()
544 end
545 elseif e == "key" then
546 if but == keys.enter then break
547 elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end
548 elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end
549 elseif (but == keys.up or but == keys.down) and properties.history then
550 redraw(" ")
551 if but == keys.up then
552 if historyPos == nil and #properties.history > 0 then
553 historyPos = #properties.history
554 elseif historyPos > 1 then
555 historyPos = historyPos - 1
556 end
557 elseif but == keys.down then
558 if historyPos == #properties.history then historyPos = nil
559 elseif historyPos ~= nil then historyPos = historyPos + 1 end
560 end
561
562 if properties.history and historyPos then
563 line = properties.history[historyPos]
564 pos = line:len()
565 else
566 line = ""
567 pos = 0
568 end
569
570 redraw()
571 local a = sendLiveUpdates("history")
572 if a then return a end
573 elseif but == keys.backspace and pos > 0 then
574 redraw(" ")
575 line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)
576 pos = pos - 1
577 redraw()
578 local a = sendLiveUpdates("delete")
579 if a then return a end
580 elseif but == keys.home then
581 pos = 0
582 redraw()
583 elseif but == keys.delete and pos < line:len() then
584 redraw(" ")
585 line = line:sub(1, pos) .. line:sub(pos + 2, -1)
586 redraw()
587 local a = sendLiveUpdates("delete")
588 if a then return a end
589 elseif but == keys["end"] then
590 pos = line:len()
591 redraw()
592 elseif properties.exitOnKey then
593 if but == properties.exitOnKey or (properties.exitOnKey == "control" and
594 (but == 29 or but == 157)) then
595 term.setCursorBlink(false)
596 return nil
597 end
598 end
599 end
600 local a = sendLiveUpdates(e, but, x, y, p4, p5)
601 if a then return a end
602 end
603
604 term.setCursorBlink(false)
605 if line ~= nil then line = line:gsub("^%s*(.-)%s*$", "%1") end
606 return line
607end
608
609
610-- -------- Themes
611
612local defaultTheme = {
613 background = "gray",
614 backgroundHighlight = "lightGray",
615 prompt = "cyan",
616 promptHighlight = "lightBlue",
617 err = "red",
618 errHighlight = "pink",
619
620 editorBackground = "gray",
621 editorLineHightlight = "lightBlue",
622 editorLineNumbers = "gray",
623 editorLineNumbersHighlight = "lightGray",
624 editorError = "pink",
625 editorErrorHighlight = "red",
626
627 textColor = "white",
628 conditional = "yellow",
629 constant = "orange",
630 ["function"] = "magenta",
631 string = "red",
632 comment = "lime"
633}
634
635local normalTheme = {
636 background = "black",
637 backgroundHighlight = "black",
638 prompt = "black",
639 promptHighlight = "black",
640 err = "black",
641 errHighlight = "black",
642
643 editorBackground = "black",
644 editorLineHightlight = "black",
645 editorLineNumbers = "black",
646 editorLineNumbersHighlight = "white",
647 editorError = "black",
648 editorErrorHighlight = "black",
649
650 textColor = "white",
651 conditional = "white",
652 constant = "white",
653 ["function"] = "white",
654 string = "white",
655 comment = "white"
656}
657
658--[[
659local availableThemes = {
660 {"Water (Default)", "https://raw.github.com/GravityScore/LuaIDE/master/themes/default.txt"},
661 {"Fire", "https://raw.github.com/GravityScore/LuaIDE/master/themes/fire.txt"},
662 {"Sublime Text 2", "https://raw.github.com/GravityScore/LuaIDE/master/themes/st2.txt"},
663 {"Midnight", "https://raw.github.com/GravityScore/LuaIDE/master/themes/midnight.txt"},
664 {"TheOriginalBIT", "https://raw.github.com/GravityScore/LuaIDE/master/themes/bit.txt"},
665 {"Superaxander", "https://raw.github.com/GravityScore/LuaIDE/master/themes/superaxander.txt"},
666 {"Forest", "https://raw.github.com/GravityScore/LuaIDE/master/themes/forest.txt"},
667 {"Night", "https://raw.github.com/GravityScore/LuaIDE/master/themes/night.txt"},
668 {"Original", "https://raw.github.com/GravityScore/LuaIDE/master/themes/original.txt"},
669}
670]]--
671
672local function loadTheme(path)
673 local f = io.open(path)
674 local l = f:read("*l")
675 local config = {}
676 while l ~= nil do
677 local k, v = string.match(l, "^(%a+)=(%a+)")
678 if k and v then config[k] = v end
679 l = f:read("*l")
680 end
681 f:close()
682 return config
683end
684
685-- Load Theme
686if isAdvanced() then theme = defaultTheme
687else theme = normalTheme end
688
689
690-- -------- Drawing
691
692local function centerPrint(text, ny)
693 if type(text) == "table" then for _, v in pairs(text) do centerPrint(v) end
694 else
695 local x, y = term.getCursorPos()
696 local w, h = term.getSize()
697 term.setCursorPos(w/2 - text:len()/2 + (#text % 2 == 0 and 1 or 0), ny or y)
698 print(text)
699 end
700end
701
702local function title(t)
703 term.setTextColor(colors[theme.textColor])
704 term.setBackgroundColor(colors[theme.background])
705 term.clear()
706
707 term.setBackgroundColor(colors[theme.backgroundHighlight])
708 for i = 2, 4 do term.setCursorPos(1, i) term.clearLine() end
709 term.setCursorPos(3, 3)
710 term.write(t)
711end
712
713local function centerRead(wid, begt)
714 local function liveUpdate(line, e, but, x, y, p4, p5)
715 if isAdvanced() and e == "mouse_click" and x >= w/2 - wid/2 and x <= w/2 - wid/2 + 10
716 and y >= 13 and y <= 15 then
717 return true, ""
718 end
719 end
720
721 if not begt then begt = "" end
722 term.setTextColor(colors[theme.textColor])
723 term.setBackgroundColor(colors[theme.promptHighlight])
724 for i = 8, 10 do
725 term.setCursorPos(w/2 - wid/2, i)
726 term.write(string.rep(" ", wid))
727 end
728
729 if isAdvanced() then
730 term.setBackgroundColor(colors[theme.errHighlight])
731 for i = 13, 15 do
732 term.setCursorPos(w/2 - wid/2 + 1, i)
733 term.write(string.rep(" ", 10))
734 end
735 term.setCursorPos(w/2 - wid/2 + 2, 14)
736 term.write("> Cancel")
737 end
738
739 term.setBackgroundColor(colors[theme.promptHighlight])
740 term.setCursorPos(w/2 - wid/2 + 1, 9)
741 term.write("> " .. begt)
742 return modRead({visibleLength = w/2 + wid/2, liveUpdates = liveUpdate})
743end
744
745
746-- -------- Prompt
747
748local function prompt(list, dir, isGrid)
749 local function draw(sel)
750 for i, v in ipairs(list) do
751 if i == sel then term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])
752 else term.setBackgroundColor(v.bg or colors[theme.prompt]) end
753 term.setTextColor(v.tc or colors[theme.textColor])
754 for i = -1, 1 do
755 term.setCursorPos(v[2], v[3] + i)
756 term.write(string.rep(" ", v[1]:len() + 4))
757 end
758
759 term.setCursorPos(v[2], v[3])
760 if i == sel then
761 term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])
762 term.write(" > ")
763 else term.write(" - ") end
764 term.write(v[1] .. " ")
765 end
766 end
767
768 local key1 = dir == "horizontal" and 203 or 200
769 local key2 = dir == "horizontal" and 205 or 208
770 local sel = 1
771 draw(sel)
772
773 while true do
774 local e, but, x, y = os.pullEvent()
775 if e == "key" and but == 28 then
776 return list[sel][1]
777 elseif e == "key" and but == key1 and sel > 1 then
778 sel = sel - 1
779 draw(sel)
780 elseif e == "key" and but == key2 and ((err == true and sel < #list - 1) or (sel < #list)) then
781 sel = sel + 1
782 draw(sel)
783 elseif isGrid and e == "key" and but == 203 and sel > 2 and #list == 4 then
784 sel = sel - 2
785 draw(sel)
786 elseif isGrid and e == "key" and but == 205 and sel < 3 and #list == 4 then
787 sel = sel + 2
788 draw(sel)
789 elseif e == "mouse_click" then
790 for i, v in ipairs(list) do
791 if x >= v[2] - 1 and x <= v[2] + v[1]:len() + 3 and y >= v[3] - 1 and y <= v[3] + 1 then
792 return list[i][1]
793 end
794 end
795 end
796 end
797end
798
799local function scrollingPrompt(list)
800 local function draw(items, sel, loc)
801 for i, v in ipairs(items) do
802 local bg = colors[theme.prompt]
803 local bghigh = colors[theme.promptHighlight]
804 if v:find("Back") or v:find("Return") then
805 bg = colors[theme.err]
806 bghigh = colors[theme.errHighlight]
807 end
808
809 if i == sel then term.setBackgroundColor(bghigh)
810 else term.setBackgroundColor(bg) end
811 term.setTextColor(colors[theme.textColor])
812 for x = -1, 1 do
813 term.setCursorPos(3, (i * 4) + x + 4)
814 term.write(string.rep(" ", w - 13))
815 end
816
817 term.setCursorPos(3, i * 4 + 4)
818 if i == sel then
819 term.setBackgroundColor(bghigh)
820 term.write(" > ")
821 else term.write(" - ") end
822 term.write(v .. " ")
823 end
824 end
825
826 local function updateDisplayList(items, loc, len)
827 local ret = {}
828 for i = 1, len do
829 local item = items[i + loc - 1]
830 if item then table.insert(ret, item) end
831 end
832 return ret
833 end
834
835 -- Variables
836 local sel = 1
837 local loc = 1
838 local len = 3
839 local disList = updateDisplayList(list, loc, len)
840 draw(disList, sel, loc)
841
842 -- Loop
843 while true do
844 local e, key, x, y = os.pullEvent()
845
846 if e == "mouse_click" then
847 for i, v in ipairs(disList) do
848 if x >= 3 and x <= w - 11 and y >= i * 4 + 3 and y <= i * 4 + 5 then return v end
849 end
850 elseif e == "key" and key == 200 then
851 if sel > 1 then
852 sel = sel - 1
853 draw(disList, sel, loc)
854 elseif loc > 1 then
855 loc = loc - 1
856 disList = updateDisplayList(list, loc, len)
857 draw(disList, sel, loc)
858 end
859 elseif e == "key" and key == 208 then
860 if sel < len then
861 sel = sel + 1
862 draw(disList, sel, loc)
863 elseif loc + len - 1 < #list then
864 loc = loc + 1
865 disList = updateDisplayList(list, loc, len)
866 draw(disList, sel, loc)
867 end
868 elseif e == "mouse_scroll" then
869 os.queueEvent("key", key == -1 and 200 or 208)
870 elseif e == "key" and key == 28 then
871 return disList[sel]
872 end
873 end
874end
875
876function monitorKeyboardShortcuts()
877 local ta, tb = nil, nil
878 local allowChar = false
879 local shiftPressed = false
880 while true do
881 local event, char = os.pullEvent()
882 if event == "key" and (char == 42 or char == 52) then
883 shiftPressed = true
884 tb = os.startTimer(keyboardShortcutTimeout)
885 elseif event == "key" and (char == 29 or char == 157 or char == 219 or char == 220) then
886 allowEditorEvent = false
887 allowChar = true
888 ta = os.startTimer(keyboardShortcutTimeout)
889 elseif event == "key" and allowChar then
890 local name = nil
891 for k, v in pairs(keys) do
892 if v == char then
893 if shiftPressed then os.queueEvent("shortcut", "ctrl shift", k:lower())
894 else os.queueEvent("shortcut", "ctrl", k:lower()) end
895 sleep(0.005)
896 allowEditorEvent = true
897 end
898 end
899 if shiftPressed then os.queueEvent("shortcut", "ctrl shift", char)
900 else os.queueEvent("shortcut", "ctrl", char) end
901 elseif event == "timer" and char == ta then
902 allowEditorEvent = true
903 allowChar = false
904 elseif event == "timer" and char == tb then
905 shiftPressed = false
906 end
907 end
908end
909
910
911-- -------- Saving and Loading
912
913--[[local function download(url, path)
914 for i = 1, 3 do
915 local response = http.get(url)
916 if response then
917 local data = response.readAll()
918 response.close()
919 if path then
920 local f = io.open(path, "w")
921 f:write(data)
922 f:close()
923 end
924 return true
925 end
926 end
927
928 return false
929end]]
930
931local function saveFile(path, lines)
932 local dir = path:sub(1, path:len() - fs.getName(path):len())
933 if not fs.exists(dir) then fs.makeDir(dir) end
934 if not fs.isDir(path) and not fs.isReadOnly(path) then
935 local a = ""
936 for _, v in pairs(lines) do a = a .. v .. "\n" end
937
938 local f = io.open(path, "w")
939 f:write(a)
940 f:close()
941 return true
942 else return false end
943end
944
945local function loadFile(path)
946 if not fs.exists(path) then
947 local dir = path:sub(1, path:len() - fs.getName(path):len())
948 if not fs.exists(dir) then fs.makeDir(dir) end
949 local f = io.open(path, "w")
950 f:write("")
951 f:close()
952 end
953
954 local l = {}
955 if fs.exists(path) and not fs.isDir(path) then
956 local f = io.open(path, "r")
957 if f then
958 local a = f:read("*l")
959 while a do
960 table.insert(l, a)
961 a = f:read("*l")
962 end
963 f:close()
964 end
965 else return nil end
966
967 if #l < 1 then table.insert(l, "") end
968 return l
969end
970
971
972-- -------- Languages
973
974languages.lua = {}
975languages.brainfuck = {}
976languages.none = {}
977
978-- Lua
979
980languages.lua.helpTips = {
981 "A function you tried to call doesn't exist.",
982 "You made a typo.",
983 "The index of an array is nil.",
984 "The wrong variable type was passed.",
985 "A function/variable doesn't exist.",
986 "You missed an 'end'.",
987 "You missed a 'then'.",
988 "You declared a variable incorrectly.",
989 "One of your variables is mysteriously nil."
990}
991
992languages.lua.defaultHelpTips = {
993 2, 5
994}
995
996languages.lua.errors = {
997 ["Attempt to call nil."] = {1, 2},
998 ["Attempt to index nil."] = {3, 2},
999 [".+ expected, got .+"] = {4, 2, 9},
1000 ["'end' expected"] = {6, 2},
1001 ["'then' expected"] = {7, 2},
1002 ["'=' expected"] = {8, 2}
1003}
1004
1005languages.lua.keywords = {
1006 ["and"] = "conditional",
1007 ["break"] = "conditional",
1008 ["do"] = "conditional",
1009 ["else"] = "conditional",
1010 ["elseif"] = "conditional",
1011 ["end"] = "conditional",
1012 ["for"] = "conditional",
1013 ["function"] = "conditional",
1014 ["if"] = "conditional",
1015 ["in"] = "conditional",
1016 ["local"] = "conditional",
1017 ["not"] = "conditional",
1018 ["or"] = "conditional",
1019 ["repeat"] = "conditional",
1020 ["return"] = "conditional",
1021 ["then"] = "conditional",
1022 ["until"] = "conditional",
1023 ["while"] = "conditional",
1024
1025 ["true"] = "constant",
1026 ["false"] = "constant",
1027 ["nil"] = "constant",
1028
1029 ["print"] = "function",
1030 ["write"] = "function",
1031 ["sleep"] = "function",
1032 ["pairs"] = "function",
1033 ["ipairs"] = "function",
1034 ["load"] = "function",
1035 ["loadfile"] = "function",
1036 ["rawset"] = "function",
1037 ["rawget"] = "function",
1038}
1039
1040languages.lua.parseError = function(e)
1041 local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""}
1042 if e and e ~= "" then
1043 ret.err = e
1044 if e:find(":") then
1045 ret.filename = e:sub(1, e:find(":") - 1):gsub("^%s*(.-)%s*$", "%1")
1046 -- The "" is needed to circumvent a CC bug
1047 e = (e:sub(e:find(":") + 1) .. ""):gsub("^%s*(.-)%s*$", "%1")
1048 if e:find(":") then
1049 ret.line = e:sub(1, e:find(":") - 1)
1050 e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. ""
1051 end
1052 end
1053 ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "."
1054 end
1055
1056 return ret
1057end
1058
1059languages.lua.getCompilerErrors = function(code)
1060 code = "local function ee65da6af1cb6f63fee9a081246f2fd92b36ef2(...)\n\n" .. code .. "\n\nend"
1061 local fn, err = load(code)
1062 if not err then
1063 local _, e = pcall(fn)
1064 if e then err = e end
1065 end
1066
1067 if err then
1068 local a = err:find("]", 1, true)
1069 if a then err = "string" .. err:sub(a + 1, -1) end
1070 local ret = languages.lua.parseError(err)
1071 if tonumber(ret.line) then ret.line = tonumber(ret.line) end
1072 return ret
1073 else return languages.lua.parseError(nil) end
1074end
1075
1076languages.lua.run = function(path, ar)
1077 local fn, err = loadfile(path, _ENV)
1078 if not err then
1079 _, err = pcall(function() fn(table.unpack(ar)) end)
1080 end
1081 return err
1082end
1083
1084
1085-- Brainfuck
1086
1087languages.brainfuck.helpTips = {
1088 "Well idk...",
1089 "Isn't this the whole point of the language?",
1090 "Ya know... Not being able to debug it?",
1091 "You made a typo."
1092}
1093
1094languages.brainfuck.defaultHelpTips = {
1095 1, 2, 3
1096}
1097
1098languages.brainfuck.errors = {
1099 ["No matching '['"] = {1, 2, 3, 4}
1100}
1101
1102languages.brainfuck.keywords = {}
1103
1104languages.brainfuck.parseError = function(e)
1105 local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""}
1106 if e and e ~= "" then
1107 ret.err = e
1108 ret.line = e:sub(1, e:find(":") - 1)
1109 e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. ""
1110 ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "."
1111 end
1112
1113 return ret
1114end
1115
1116languages.brainfuck.mapLoops = function(code)
1117 -- Map loops
1118 local loopLocations = {}
1119 local loc = 1
1120 local line = 1
1121 for let in string.gmatch(code, ".") do
1122 if let == "[" then
1123 loopLocations[loc] = true
1124 elseif let == "]" then
1125 local found = false
1126 for i = loc, 1, -1 do
1127 if loopLocations[i] == true then
1128 loopLocations[i] = loc
1129 found = true
1130 end
1131 end
1132
1133 if not found then
1134 return line .. ": No matching '['"
1135 end
1136 end
1137
1138 if let == "\n" then line = line + 1 end
1139 loc = loc + 1
1140 end
1141 return loopLocations
1142end
1143
1144languages.brainfuck.getCompilerErrors = function(code)
1145 local a = languages.brainfuck.mapLoops(code)
1146 if type(a) == "string" then return languages.brainfuck.parseError(a)
1147 else return languages.brainfuck.parseError(nil) end
1148end
1149
1150languages.brainfuck.run = function(path)
1151 -- Read from file
1152 local f = io.open(path, "r")
1153 local content = f:read("*a")
1154 f:close()
1155
1156 -- Define environment
1157 local dataCells = {}
1158 local dataPointer = 1
1159 local instructionPointer = 1
1160
1161 -- Map loops
1162 local loopLocations = languages.brainfuck.mapLoops(content)
1163 if type(loopLocations) == "string" then return loopLocations end
1164
1165 -- Execute code
1166 while true do
1167 local let = content:sub(instructionPointer, instructionPointer)
1168
1169 if let == ">" then
1170 dataPointer = dataPointer + 1
1171 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1172 elseif let == "<" then
1173 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1174 dataPointer = dataPointer - 1
1175 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1176 elseif let == "+" then
1177 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1178 dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] + 1
1179 elseif let == "-" then
1180 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1181 dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] - 1
1182 elseif let == "." then
1183 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1184 if term.getCursorPos() >= w then print("") end
1185 write(string.char(math.max(1, dataCells[tostring(dataPointer)])))
1186 elseif let == "," then
1187 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1188 term.setCursorBlink(true)
1189 local e, but = os.pullEvent("char")
1190 term.setCursorBlink(false)
1191 dataCells[tostring(dataPointer)] = string.byte(but)
1192 if term.getCursorPos() >= w then print("") end
1193 write(but)
1194 elseif let == "/" then
1195 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
1196 if term.getCursorPos() >= w then print("") end
1197 write(dataCells[tostring(dataPointer)])
1198 elseif let == "[" then
1199 if dataCells[tostring(dataPointer)] == 0 then
1200 for k, v in pairs(loopLocations) do
1201 if k == instructionPointer then instructionPointer = v end
1202 end
1203 end
1204 elseif let == "]" then
1205 for k, v in pairs(loopLocations) do
1206 if v == instructionPointer then instructionPointer = k - 1 end
1207 end
1208 end
1209
1210 instructionPointer = instructionPointer + 1
1211 if instructionPointer > content:len() then print("") break end
1212 end
1213end
1214
1215-- None
1216
1217languages.none.helpTips = {}
1218languages.none.defaultHelpTips = {}
1219languages.none.errors = {}
1220languages.none.keywords = {}
1221
1222languages.none.parseError = function(err)
1223 return {filename = "", line = -1, display = "", err = ""}
1224end
1225
1226languages.none.getCompilerErrors = function(code)
1227 return languages.none.parseError(nil)
1228end
1229
1230languages.none.run = function(path) end
1231
1232
1233-- Load language
1234curLanguage = languages.lua
1235
1236
1237-- -------- Run GUI
1238
1239local function viewErrorHelp(e)
1240 title("LuaIDE - Error Help")
1241
1242 local tips = nil
1243 for k, v in pairs(curLanguage.errors) do
1244 if e.display:find(k) then tips = v break end
1245 end
1246
1247 term.setBackgroundColor(colors[theme.err])
1248 for i = 6, 8 do
1249 term.setCursorPos(5, i)
1250 term.write(string.rep(" ", 35))
1251 end
1252
1253 term.setBackgroundColor(colors[theme.prompt])
1254 for i = 10, 18 do
1255 term.setCursorPos(5, i)
1256 term.write(string.rep(" ", 46))
1257 end
1258
1259 if tips then
1260 term.setBackgroundColor(colors[theme.err])
1261 term.setCursorPos(6, 7)
1262 term.write("Error Help")
1263
1264 term.setBackgroundColor(colors[theme.prompt])
1265 for i, v in ipairs(tips) do
1266 term.setCursorPos(7, i + 10)
1267 term.write("- " .. curLanguage.helpTips[v])
1268 end
1269 else
1270 term.setBackgroundColor(colors[theme.err])
1271 term.setCursorPos(6, 7)
1272 term.write("No Error Tips Available!")
1273
1274 term.setBackgroundColor(colors[theme.prompt])
1275 term.setCursorPos(6, 11)
1276 term.write("There are no error tips available, but")
1277 term.setCursorPos(6, 12)
1278 term.write("you could see if it was any of these:")
1279
1280 for i, v in ipairs(curLanguage.defaultHelpTips) do
1281 term.setCursorPos(7, i + 12)
1282 term.write("- " .. curLanguage.helpTips[v])
1283 end
1284 end
1285
1286 prompt({{"Back", w - 8, 7}}, "horizontal")
1287end
1288
1289local function run(path, lines, useArgs)
1290 local ar = {}
1291 if useArgs then
1292 title("LuaIDE - Run " .. fs.getName(path))
1293 local s = centerRead(w - 13, fs.getName(path) .. " ")
1294 for m in string.gmatch(s, "[^ \t]+") do ar[#ar + 1] = m:gsub("^%s*(.-)%s*$", "%1") end
1295 end
1296
1297 saveFile(path, lines)
1298 term.setCursorBlink(false)
1299 term.setBackgroundColor(colors.black)
1300 term.setTextColor(colors.white)
1301 term.clear()
1302 term.setCursorPos(1, 1)
1303 local err = curLanguage.run(path, ar)
1304
1305 term.setBackgroundColor(colors.black)
1306 print("\n")
1307 if err then
1308 if isAdvanced() then term.setTextColor(colors.red) end
1309 centerPrint("The program has crashed!")
1310 end
1311 term.setTextColor(colors.white)
1312 centerPrint("Press any key to return to LuaIDE...")
1313 while true do
1314 local e = os.pullEvent()
1315 if e == "key" then break end
1316 end
1317
1318 -- To prevent key from showing up in editor
1319 os.queueEvent(event_distract)
1320 os.pullEvent()
1321
1322 if err then
1323 if curLanguage == languages.lua and err:find("]") then
1324 err = fs.getName(path) .. err:sub(err:find("]", 1, true) + 1, -1)
1325 end
1326
1327 while true do
1328 title("LuaIDE - Error!")
1329
1330 term.setBackgroundColor(colors[theme.err])
1331 for i = 6, 8 do
1332 term.setCursorPos(3, i)
1333 term.write(string.rep(" ", w - 5))
1334 end
1335 term.setCursorPos(4, 7)
1336 term.write("The program has crashed!")
1337
1338 term.setBackgroundColor(colors[theme.prompt])
1339 for i = 10, 14 do
1340 term.setCursorPos(3, i)
1341 term.write(string.rep(" ", w - 5))
1342 end
1343
1344 local formattedErr = curLanguage.parseError(err)
1345 term.setCursorPos(4, 11)
1346 term.write("Line: " .. formattedErr.line)
1347 term.setCursorPos(4, 12)
1348 term.write("Error:")
1349 term.setCursorPos(5, 13)
1350
1351 local a = formattedErr.display
1352 local b = nil
1353 if a:len() > w - 8 then
1354 for i = a:len(), 1, -1 do
1355 if a:sub(i, i) == " " then
1356 b = a:sub(i + 1, -1)
1357 a = a:sub(1, i)
1358 break
1359 end
1360 end
1361 end
1362
1363 term.write(a)
1364 if b then
1365 term.setCursorPos(5, 14)
1366 term.write(b)
1367 end
1368
1369 local opt = prompt({{"Error Help", w/2 - 15, 17}, {"Go To Line", w/2 + 2, 17}},
1370 "horizontal")
1371 if opt == "Error Help" then
1372 viewErrorHelp(formattedErr)
1373 elseif opt == "Go To Line" then
1374 -- To prevent key from showing up in editor
1375 os.queueEvent(event_distract)
1376 os.pullEvent()
1377
1378 return "go to", tonumber(formattedErr.line)
1379 end
1380 end
1381 end
1382end
1383
1384
1385-- -------- Functions
1386
1387local function goto()
1388 term.setBackgroundColor(colors[theme.backgroundHighlight])
1389 term.setCursorPos(2, 1)
1390 term.clearLine()
1391 term.write("Line: ")
1392 local line = modRead({visibleLength = w - 2})
1393
1394 local num = tonumber(line)
1395 if num and num > 0 then return num
1396 else
1397 term.setCursorPos(2, 1)
1398 term.clearLine()
1399 term.write("Not a line number!")
1400 sleep(1.6)
1401 return nil
1402 end
1403end
1404
1405local function setsyntax()
1406 local opts = {
1407 "[Lua] Brainfuck None ",
1408 " Lua [Brainfuck] None ",
1409 " Lua Brainfuck [None]"
1410 }
1411 local sel = 1
1412
1413 term.setCursorBlink(false)
1414 term.setBackgroundColor(colors[theme.backgroundHighlight])
1415 term.setCursorPos(2, 1)
1416 term.clearLine()
1417 term.write(opts[sel])
1418 while true do
1419 local e, but, x, y = os.pullEvent("key")
1420 if but == 203 then
1421 sel = math.max(1, sel - 1)
1422 term.setCursorPos(2, 1)
1423 term.clearLine()
1424 term.write(opts[sel])
1425 elseif but == 205 then
1426 sel = math.min(#opts, sel + 1)
1427 term.setCursorPos(2, 1)
1428 term.clearLine()
1429 term.write(opts[sel])
1430 elseif but == 28 then
1431 if sel == 1 then curLanguage = languages.lua
1432 elseif sel == 2 then curLanguage = languages.brainfuck
1433 elseif sel == 3 then curLanguage = languages.none end
1434 term.setCursorBlink(true)
1435 return
1436 end
1437 end
1438end
1439
1440
1441-- -------- Re-Indenting
1442
1443local tabWidth = 2
1444
1445local comments = {}
1446local strings = {}
1447
1448local increment = {
1449 "if%s+.+%s+then%s*$",
1450 "for%s+.+%s+do%s*$",
1451 "while%s+.+%s+do%s*$",
1452 "repeat%s*$",
1453 "function%s+[a-zA-Z_0-9]\(.*\)%s*$"
1454}
1455
1456local decrement = {
1457 "end",
1458 "until%s+.+"
1459}
1460
1461local special = {
1462 "else%s*$",
1463 "elseif%s+.+%s+then%s*$"
1464}
1465
1466local function check(func)
1467 for _, v in pairs(func) do
1468 local cLineStart = v["lineStart"]
1469 local cLineEnd = v["lineEnd"]
1470 local cCharStart = v["charStart"]
1471 local cCharEnd = v["charEnd"]
1472
1473 if line >= cLineStart and line <= cLineEnd then
1474 if line == cLineStart then return cCharStart < charNumb
1475 elseif line == cLineEnd then return cCharEnd > charNumb
1476 else return true end
1477 end
1478 end
1479end
1480
1481local function isIn(line, loc)
1482 if check(comments) then return true end
1483 if check(strings) then return true end
1484 return false
1485end
1486
1487local function setComment(ls, le, cs, ce)
1488 comments[#comments + 1] = {}
1489 comments[#comments].lineStart = ls
1490 comments[#comments].lineEnd = le
1491 comments[#comments].charStart = cs
1492 comments[#comments].charEnd = ce
1493end
1494
1495local function setString(ls, le, cs, ce)
1496 strings[#strings + 1] = {}
1497 strings[#strings].lineStart = ls
1498 strings[#strings].lineEnd = le
1499 strings[#strings].charStart = cs
1500 strings[#strings].charEnd = ce
1501end
1502
1503local function map(contents)
1504 local inCom = false
1505 local inStr = false
1506
1507 for i = 1, #contents do
1508 if content[i]:find("%-%-%[%[") and not inStr and not inCom then
1509 local cStart = content[i]:find("%-%-%[%[")
1510 setComment(i, nil, cStart, nil)
1511 inCom = true
1512 elseif content[i]:find("%-%-%[=%[") and not inStr and not inCom then
1513 local cStart = content[i]:find("%-%-%[=%[")
1514 setComment(i, nil, cStart, nil)
1515 inCom = true
1516 elseif content[i]:find("%[%[") and not inStr and not inCom then
1517 local cStart = content[i]:find("%[%[")
1518 setString(i, nil, cStart, nil)
1519 inStr = true
1520 elseif content[i]:find("%[=%[") and not inStr and not inCom then
1521 local cStart = content[i]:find("%[=%[")
1522 setString(i, nil, cStart, nil)
1523 inStr = true
1524 end
1525
1526 if content[i]:find("%]%]") and inStr and not inCom then
1527 local cStart, cEnd = content[i]:find("%]%]")
1528 strings[#strings].lineEnd = i
1529 strings[#strings].charEnd = cEnd
1530 inStr = false
1531 elseif content[i]:find("%]=%]") and inStr and not inCom then
1532 local cStart, cEnd = content[i]:find("%]=%]")
1533 strings[#strings].lineEnd = i
1534 strings[#strings].charEnd = cEnd
1535 inStr = false
1536 end
1537
1538 if content[i]:find("%]%]") and not inStr and inCom then
1539 local cStart, cEnd = content[i]:find("%]%]")
1540 comments[#comments].lineEnd = i
1541 comments[#comments].charEnd = cEnd
1542 inCom = false
1543 elseif content[i]:find("%]=%]") and not inStr and inCom then
1544 local cStart, cEnd = content[i]:find("%]=%]")
1545 comments[#comments].lineEnd = i
1546 comments[#comments].charEnd = cEnd
1547 inCom = false
1548 end
1549
1550 if content[i]:find("%-%-") and not inStr and not inCom then
1551 local cStart = content[i]:find("%-%-")
1552 setComment(i, i, cStart, -1)
1553 elseif content[i]:find("'") and not inStr and not inCom then
1554 local cStart, cEnd = content[i]:find("'")
1555 local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))
1556 local _, cEnd = nextChar:find("'")
1557 setString(i, i, cStart, cEnd)
1558 elseif content[i]:find('"') and not inStr and not inCom then
1559 local cStart, cEnd = content[i]:find('"')
1560 local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))
1561 local _, cEnd = nextChar:find('"')
1562 setString(i, i, cStart, cEnd)
1563 end
1564 end
1565end
1566
1567local function reindent(contents)
1568 local err = nil
1569 if curLanguage ~= languages.lua then
1570 err = "Cannot indent languages other than Lua!"
1571 elseif curLanguage.getCompilerErrors(table.concat(contents, "\n")).line ~= -1 then
1572 err = "Cannot indent a program with errors!"
1573 end
1574
1575 if err then
1576 term.setCursorBlink(false)
1577 term.setCursorPos(2, 1)
1578 term.setBackgroundColor(colors[theme.backgroundHighlight])
1579 term.clearLine()
1580 term.write(err)
1581 sleep(1.6)
1582 return contents
1583 end
1584
1585 local new = {}
1586 local level = 0
1587 for k, v in pairs(contents) do
1588 local incrLevel = false
1589 local foundIncr = false
1590 for _, incr in pairs(increment) do
1591 if v:find(incr) and not isIn(k, v:find(incr)) then
1592 incrLevel = true
1593 end
1594 if v:find(incr:sub(1, -2)) and not isIn(k, v:find(incr)) then
1595 foundIncr = true
1596 end
1597 end
1598
1599 local decrLevel = false
1600 if not incrLevel then
1601 for _, decr in pairs(decrement) do
1602 if v:find(decr) and not isIn(k, v:find(decr)) and not foundIncr then
1603 level = math.max(0, level - 1)
1604 decrLevel = true
1605 end
1606 end
1607 end
1608
1609 if not decrLevel then
1610 for _, sp in pairs(special) do
1611 if v:find(sp) and not isIn(k, v:find(sp)) then
1612 incrLevel = true
1613 level = math.max(0, level - 1)
1614 end
1615 end
1616 end
1617
1618 new[k] = string.rep(" ", level * tabWidth) .. v
1619 if incrLevel then level = level + 1 end
1620 end
1621
1622 return new
1623end
1624
1625
1626-- -------- Menu
1627
1628local menu = {
1629 [1] = {"File",
1630-- "About",
1631-- "Settings",
1632-- "",
1633 "New File ^+N",
1634 "Open File ^+O",
1635 "Save File ^+S",
1636 "Close ^+W",
1637 "Print ^+P",
1638 "Quit ^+Q"
1639 }, [2] = {"Edit",
1640 "Cut Line ^+X",
1641 "Copy Line ^+C",
1642 "Paste Line ^+V",
1643 "Delete Line",
1644 "Clear Line"
1645 }, [3] = {"Functions",
1646 "Go To Line ^+G",
1647 "Re-Indent ^+I",
1648 "Set Syntax ^+E",
1649 "Start of Line ^+<",
1650 "End of Line ^+>"
1651 }, [4] = {"Run",
1652 "Run Program ^+R",
1653 "Run w/ Args ^+Shift+R"
1654 }
1655}
1656
1657local shortcuts = {
1658 -- File
1659 ["ctrl n"] = "New File ^+N",
1660 ["ctrl o"] = "Open File ^+O",
1661 ["ctrl s"] = "Save File ^+S",
1662 ["ctrl w"] = "Close ^+W",
1663 ["ctrl p"] = "Print ^+P",
1664 ["ctrl q"] = "Quit ^+Q",
1665
1666 -- Edit
1667 ["ctrl x"] = "Cut Line ^+X",
1668 ["ctrl c"] = "Copy Line ^+C",
1669 ["ctrl v"] = "Paste Line ^+V",
1670
1671 -- Functions
1672 ["ctrl g"] = "Go To Line ^+G",
1673 ["ctrl i"] = "Re-Indent ^+I",
1674 ["ctrl e"] = "Set Syntax ^+E",
1675 ["ctrl 203"] = "Start of Line ^+<",
1676 ["ctrl 205"] = "End of Line ^+>",
1677
1678 -- Run
1679 ["ctrl r"] = "Run Program ^+R",
1680 ["ctrl shift r"] = "Run w/ Args ^+Shift+R"
1681}
1682
1683local menuFunctions = {
1684 -- File
1685-- ["About"] = function() end,
1686-- ["Settings"] = function() end,
1687 ["New File ^+N"] = function(path, lines) saveFile(path, lines) return "new" end,
1688 ["Open File ^+O"] = function(path, lines) saveFile(path, lines) return "open" end,
1689 ["Save File ^+S"] = function(path, lines) saveFile(path, lines) end,
1690 ["Close ^+W"] = function(path, lines) saveFile(path, lines) return "menu" end,
1691 ["Print ^+P"] = function(path, lines) saveFile(path, lines) return nil end,
1692 ["Quit ^+Q"] = function(path, lines) saveFile(path, lines) return "exit" end,
1693
1694 -- Edit
1695 ["Cut Line ^+X"] = function(path, lines, y)
1696 clipboard = lines[y] table.remove(lines, y) return nil, lines end,
1697 ["Copy Line ^+C"] = function(path, lines, y) clipboard = lines[y] end,
1698 ["Paste Line ^+V"] = function(path, lines, y)
1699 if clipboard then table.insert(lines, y, clipboard) end return nil, lines end,
1700 ["Delete Line"] = function(path, lines, y) table.remove(lines, y) return nil, lines end,
1701 ["Clear Line"] = function(path, lines, y) lines[y] = "" return nil, lines, "cursor" end,
1702
1703 -- Functions
1704 ["Go To Line ^+G"] = function() return nil, "go to", goto() end,
1705 ["Re-Indent ^+I"] = function(path, lines)
1706 local a = reindent(lines) saveFile(path, lines) return nil, a
1707 end,
1708 ["Set Syntax ^+E"] = function(path, lines)
1709 setsyntax()
1710 if curLanguage == languages.brainfuck and lines[1] ~= "-- Syntax: Brainfuck" then
1711 table.insert(lines, 1, "-- Syntax: Brainfuck")
1712 return nil, lines
1713 end
1714 end,
1715 ["Start of Line ^+<"] = function() os.queueEvent("key", 199) end,
1716 ["End of Line ^+>"] = function() os.queueEvent("key", 207) end,
1717
1718 -- Run
1719 ["Run Program ^+R"] = function(path, lines)
1720 saveFile(path, lines)
1721 return nil, run(path, lines, false)
1722 end,
1723 ["Run w/ Args ^+Shift+R"] = function(path, lines)
1724 saveFile(path, lines)
1725 return nil, run(path, lines, true)
1726 end,
1727}
1728
1729local function drawMenu(open)
1730 term.setCursorPos(1, 1)
1731 term.setTextColor(colors[theme.textColor])
1732 term.setBackgroundColor(colors[theme.backgroundHighlight])
1733 term.clearLine()
1734 local curX = 0
1735 for _, v in pairs(menu) do
1736 term.setCursorPos(3 + curX, 1)
1737 term.write(v[1])
1738 curX = curX + v[1]:len() + 3
1739 end
1740
1741 if open then
1742 local it = {}
1743 local x = 1
1744 for _, v in pairs(menu) do
1745 if open == v[1] then
1746 it = v
1747 break
1748 end
1749 x = x + v[1]:len() + 3
1750 end
1751 x = x + 1
1752
1753 local items = {}
1754 for i = 2, #it do
1755 table.insert(items, it[i])
1756 end
1757
1758 local len = 1
1759 for _, v in pairs(items) do if v:len() + 2 > len then len = v:len() + 2 end end
1760
1761 for i, v in ipairs(items) do
1762 term.setCursorPos(x, i + 1)
1763 term.write(string.rep(" ", len))
1764 term.setCursorPos(x + 1, i + 1)
1765 term.write(v)
1766 end
1767 term.setCursorPos(x, #items + 2)
1768 term.write(string.rep(" ", len))
1769 return items, len
1770 end
1771end
1772
1773local function triggerMenu(cx, cy)
1774 -- Determine clicked menu
1775 local curX = 0
1776 local open = nil
1777 for _, v in pairs(menu) do
1778 if cx >= curX + 3 and cx <= curX + v[1]:len() + 2 then
1779 open = v[1]
1780 break
1781 end
1782 curX = curX + v[1]:len() + 3
1783 end
1784 local menux = curX + 2
1785 if not open then return false end
1786
1787 -- Flash menu item
1788 term.setCursorBlink(false)
1789 term.setCursorPos(menux, 1)
1790 term.setBackgroundColor(colors[theme.background])
1791 term.write(string.rep(" ", open:len() + 2))
1792 term.setCursorPos(menux + 1, 1)
1793 term.write(open)
1794 sleep(0.1)
1795 local items, len = drawMenu(open)
1796
1797 local ret = true
1798
1799 -- Pull events on menu
1800 local ox, oy = term.getCursorPos()
1801 while type(ret) ~= "string" do
1802 local e, but, x, y = os.pullEvent()
1803 if e == "mouse_click" then
1804 -- If clicked outside menu
1805 if x < menux - 1 or x > menux + len - 1 then break
1806 elseif y > #items + 2 then break
1807 elseif y == 1 then break end
1808
1809 for i, v in ipairs(items) do
1810 if y == i + 1 and x >= menux and x <= menux + len - 2 then
1811 -- Flash when clicked
1812 term.setCursorPos(menux, y)
1813 term.setBackgroundColor(colors[theme.background])
1814 term.write(string.rep(" ", len))
1815 term.setCursorPos(menux + 1, y)
1816 term.write(v)
1817 sleep(0.1)
1818 drawMenu(open)
1819
1820 -- Return item
1821 ret = v
1822 break
1823 end
1824 end
1825 end
1826 end
1827
1828 term.setCursorPos(ox, oy)
1829 term.setCursorBlink(true)
1830 return ret
1831end
1832
1833
1834-- -------- Editing
1835
1836local standardsCompletions = {
1837 "if%s+.+%s+then%s*$",
1838 "for%s+.+%s+do%s*$",
1839 "while%s+.+%s+do%s*$",
1840 "repeat%s*$",
1841 "function%s+[a-zA-Z_0-9]?\(.*\)%s*$",
1842 "=%s*function%s*\(.*\)%s*$",
1843 "else%s*$",
1844 "elseif%s+.+%s+then%s*$"
1845}
1846
1847local liveCompletions = {
1848 ["("] = ")",
1849 ["{"] = "}",
1850 ["["] = "]",
1851 ["\""] = "\"",
1852 ["'"] = "'",
1853}
1854
1855local x, y = 0, 0
1856local edw, edh = 0, h - 1
1857local offx, offy = 0, 1
1858local scrollx, scrolly = 0, 0
1859local lines = {}
1860local liveErr = curLanguage.parseError(nil)
1861local displayCode = true
1862local lastEventClock = os.clock()
1863
1864local function attemptToHighlight(line, regex, col)
1865 local match = string.match(line, regex)
1866 if match then
1867 if type(col) == "number" then term.setTextColor(col)
1868 elseif type(col) == "function" then term.setTextColor(col(match)) end
1869 term.write(match)
1870 term.setTextColor(colors[theme.textColor])
1871 return line:sub(match:len() + 1, -1)
1872 end
1873 return nil
1874end
1875
1876local function writeHighlighted(line)
1877 if curLanguage == languages.lua then
1878 while line:len() > 0 do
1879 line = attemptToHighlight(line, "^%-%-%[%[.-%]%]", colors[theme.comment]) or
1880 attemptToHighlight(line, "^%-%-.*", colors[theme.comment]) or
1881 attemptToHighlight(line, "^\".*[^\\]\"", colors[theme.string]) or
1882 attemptToHighlight(line, "^\'.*[^\\]\'", colors[theme.string]) or
1883 attemptToHighlight(line, "^%[%[.-%]%]", colors[theme.string]) or
1884 attemptToHighlight(line, "^[%w_]+", function(match)
1885 if curLanguage.keywords[match] then
1886 return colors[theme[curLanguage.keywords[match]]]
1887 end
1888 return colors[theme.textColor]
1889 end) or
1890 attemptToHighlight(line, "^[^%w_]", colors[theme.textColor])
1891 end
1892 else term.write(line) end
1893end
1894
1895local function draw()
1896 -- Menu
1897 term.setTextColor(colors[theme.textColor])
1898 term.setBackgroundColor(colors[theme.editorBackground])
1899 term.clear()
1900 drawMenu()
1901
1902 -- Line numbers
1903 offx, offy = tostring(#lines):len() + 1, 1
1904 edw, edh = w - offx, h - 1
1905
1906 -- Draw text
1907 for i = 1, edh do
1908 local a = lines[scrolly + i]
1909 if a then
1910 local ln = string.rep(" ", offx - 1 - tostring(scrolly + i):len()) .. tostring(scrolly + i)
1911 local l = a:sub(scrollx + 1, edw + scrollx + 1)
1912 ln = ln .. ":"
1913
1914 if liveErr.line == scrolly + i then ln = string.rep(" ", offx - 2) .. "!:" end
1915
1916 term.setCursorPos(1, i + offy)
1917 term.setBackgroundColor(colors[theme.editorBackground])
1918 if scrolly + i == y then
1919 if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
1920 term.setBackgroundColor(colors[theme.editorErrorHighlight])
1921 else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
1922 term.clearLine()
1923 elseif scrolly + i == liveErr.line then
1924 term.setBackgroundColor(colors[theme.editorError])
1925 term.clearLine()
1926 end
1927
1928 term.setCursorPos(1 - scrollx + offx, i + offy)
1929 if scrolly + i == y then
1930 if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
1931 term.setBackgroundColor(colors[theme.editorErrorHighlight])
1932 else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
1933 elseif scrolly + i == liveErr.line then term.setBackgroundColor(colors[theme.editorError])
1934 else term.setBackgroundColor(colors[theme.editorBackground]) end
1935 if scrolly + i == liveErr.line then
1936 if displayCode then term.write(a)
1937 else term.write(liveErr.display) end
1938 else writeHighlighted(a) end
1939
1940 term.setCursorPos(1, i + offy)
1941 if scrolly + i == y then
1942 if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
1943 term.setBackgroundColor(colors[theme.editorError])
1944 else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end
1945 elseif scrolly + i == liveErr.line then
1946 term.setBackgroundColor(colors[theme.editorErrorHighlight])
1947 else term.setBackgroundColor(colors[theme.editorLineNumbers]) end
1948 term.write(ln)
1949 end
1950 end
1951 term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
1952end
1953
1954local function drawLine(...)
1955 local ls = {...}
1956 offx = tostring(#lines):len() + 1
1957 for _, ly in pairs(ls) do
1958 local a = lines[ly]
1959 if a then
1960 local ln = string.rep(" ", offx - 1 - tostring(ly):len()) .. tostring(ly)
1961 local l = a:sub(scrollx + 1, edw + scrollx + 1)
1962 ln = ln .. ":"
1963
1964 if liveErr.line == ly then ln = string.rep(" ", offx - 2) .. "!:" end
1965
1966 term.setCursorPos(1, (ly - scrolly) + offy)
1967 term.setBackgroundColor(colors[theme.editorBackground])
1968 if ly == y then
1969 if ly == liveErr.line and os.clock() - lastEventClock > 3 then
1970 term.setBackgroundColor(colors[theme.editorErrorHighlight])
1971 else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
1972 elseif ly == liveErr.line then
1973 term.setBackgroundColor(colors[theme.editorError])
1974 end
1975 term.clearLine()
1976
1977 term.setCursorPos(1 - scrollx + offx, (ly - scrolly) + offy)
1978 if ly == y then
1979 if ly == liveErr.line and os.clock() - lastEventClock > 3 then
1980 term.setBackgroundColor(colors[theme.editorErrorHighlight])
1981 else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
1982 elseif ly == liveErr.line then term.setBackgroundColor(colors[theme.editorError])
1983 else term.setBackgroundColor(colors[theme.editorBackground]) end
1984 if ly == liveErr.line then
1985 if displayCode then term.write(a)
1986 else term.write(liveErr.display) end
1987 else writeHighlighted(a) end
1988
1989 term.setCursorPos(1, (ly - scrolly) + offy)
1990 if ly == y then
1991 if ly == liveErr.line and os.clock() - lastEventClock > 3 then
1992 term.setBackgroundColor(colors[theme.editorError])
1993 else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end
1994 elseif ly == liveErr.line then
1995 term.setBackgroundColor(colors[theme.editorErrorHighlight])
1996 else term.setBackgroundColor(colors[theme.editorLineNumbers]) end
1997 term.write(ln)
1998 end
1999 end
2000 term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
2001end
2002
2003local function cursorLoc(x, y, force)
2004 local sx, sy = x - scrollx, y - scrolly
2005 local redraw = false
2006 if sx < 1 then
2007 scrollx = x - 1
2008 sx = 1
2009 redraw = true
2010 elseif sx > edw then
2011 scrollx = x - edw
2012 sx = edw
2013 redraw = true
2014 end if sy < 1 then
2015 scrolly = y - 1
2016 sy = 1
2017 redraw = true
2018 elseif sy > edh then
2019 scrolly = y - edh
2020 sy = edh
2021 redraw = true
2022 end if redraw or force then draw() end
2023 term.setCursorPos(sx + offx, sy + offy)
2024end
2025
2026local function executeMenuItem(a, path)
2027 if type(a) == "string" and menuFunctions[a] then
2028 local opt, nl, gtln = menuFunctions[a](path, lines, y)
2029 if type(opt) == "string" then term.setCursorBlink(false) return opt end
2030 if type(nl) == "table" then
2031 if #lines < 1 then table.insert(lines, "") end
2032 y = math.min(y, #lines)
2033 x = math.min(x, lines[y]:len() + 1)
2034 lines = nl
2035 elseif type(nl) == "string" then
2036 if nl == "go to" and gtln then
2037 x, y = 1, math.min(#lines, gtln)
2038 cursorLoc(x, y)
2039 end
2040 end
2041 end
2042 term.setCursorBlink(true)
2043 draw()
2044 term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
2045end
2046
2047local function edit(path)
2048 -- Variables
2049 x, y = 1, 1
2050 offx, offy = 0, 1
2051 scrollx, scrolly = 0, 0
2052 lines = loadFile(path)
2053 if not lines then return "menu" end
2054
2055 -- Enable brainfuck
2056 if lines[1] == "-- Syntax: Brainfuck" then
2057 curLanguage = languages.brainfuck
2058 end
2059
2060 -- Clocks
2061 local autosaveClock = os.clock()
2062 local scrollClock = os.clock() -- To prevent redraw flicker
2063 local liveErrorClock = os.clock()
2064 local hasScrolled = false
2065
2066 -- Draw
2067 draw()
2068 term.setCursorPos(x + offx, y + offy)
2069 term.setCursorBlink(true)
2070
2071 -- Main loop
2072 local tid = os.startTimer(3)
2073 while true do
2074 local e, key, cx, cy = os.pullEvent()
2075 if e == "key" and allowEditorEvent then
2076 if key == 200 and y > 1 then
2077 -- Up
2078 x, y = math.min(x, lines[y - 1]:len() + 1), y - 1
2079 drawLine(y, y + 1)
2080 cursorLoc(x, y)
2081 elseif key == 208 and y < #lines then
2082 -- Down
2083 x, y = math.min(x, lines[y + 1]:len() + 1), y + 1
2084 drawLine(y, y - 1)
2085 cursorLoc(x, y)
2086 elseif key == 203 and x > 1 then
2087 -- Left
2088 x = x - 1
2089 local force = false
2090 if y - scrolly + offy < offy + 1 then force = true end
2091 cursorLoc(x, y, force)
2092 elseif key == 205 and x < lines[y]:len() + 1 then
2093 -- Right
2094 x = x + 1
2095 local force = false
2096 if y - scrolly + offy < offy + 1 then force = true end
2097 cursorLoc(x, y, force)
2098 elseif (key == 28 or key == 156) and (displayCode and true or y + scrolly - 1 ==
2099 liveErr.line) then
2100 -- Enter
2101 local f = nil
2102 for _, v in pairs(standardsCompletions) do
2103 if lines[y]:find(v) then f = v end
2104 end
2105
2106 local _, spaces = lines[y]:find("^[ ]+")
2107 if not spaces then spaces = 0 end
2108 if f then
2109 table.insert(lines, y + 1, string.rep(" ", spaces + 2))
2110 if not f:find("else", 1, true) and not f:find("elseif", 1, true) then
2111 table.insert(lines, y + 2, string.rep(" ", spaces) ..
2112 (f:find("repeat", 1, true) and "until " or f:find("{", 1, true) and "}" or
2113 "end"))
2114 end
2115 x, y = spaces + 3, y + 1
2116 cursorLoc(x, y, true)
2117 else
2118 local oldLine = lines[y]
2119
2120 lines[y] = lines[y]:sub(1, x - 1)
2121 table.insert(lines, y + 1, string.rep(" ", spaces) .. oldLine:sub(x, -1))
2122
2123 x, y = spaces + 1, y + 1
2124 cursorLoc(x, y, true)
2125 end
2126 elseif key == 14 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
2127 -- Backspace
2128 if x > 1 then
2129 local f = false
2130 for k, v in pairs(liveCompletions) do
2131 if lines[y]:sub(x - 1, x - 1) == k then f = true end
2132 end
2133
2134 lines[y] = lines[y]:sub(1, x - 2) .. lines[y]:sub(x + (f and 1 or 0), -1)
2135 drawLine(y)
2136 x = x - 1
2137 cursorLoc(x, y)
2138 elseif y > 1 then
2139 local prevLen = lines[y - 1]:len() + 1
2140 lines[y - 1] = lines[y - 1] .. lines[y]
2141 table.remove(lines, y)
2142 x, y = prevLen, y - 1
2143 cursorLoc(x, y, true)
2144 end
2145 elseif key == 199 then
2146 -- Home
2147 x = 1
2148 local force = false
2149 if y - scrolly + offy < offy + 1 then force = true end
2150 cursorLoc(x, y, force)
2151 elseif key == 207 then
2152 -- End
2153 x = lines[y]:len() + 1
2154 local force = false
2155 if y - scrolly + offy < offy + 1 then force = true end
2156 cursorLoc(x, y, force)
2157 elseif key == 211 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
2158 -- Forward Delete
2159 if x < lines[y]:len() + 1 then
2160 lines[y] = lines[y]:sub(1, x - 1) .. lines[y]:sub(x + 1)
2161 local force = false
2162 if y - scrolly + offy < offy + 1 then force = true end
2163 drawLine(y)
2164 cursorLoc(x, y, force)
2165 elseif y < #lines then
2166 lines[y] = lines[y] .. lines[y + 1]
2167 table.remove(lines, y + 1)
2168 draw()
2169 cursorLoc(x, y)
2170 end
2171 elseif key == 15 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
2172 -- Tab
2173 lines[y] = string.rep(" ", tabWidth) .. lines[y]
2174 x = x + 2
2175 local force = false
2176 if y - scrolly + offy < offy + 1 then force = true end
2177 drawLine(y)
2178 cursorLoc(x, y, force)
2179 elseif key == 201 then
2180 -- Page up
2181 y = math.min(math.max(y - edh, 1), #lines)
2182 x = math.min(lines[y]:len() + 1, x)
2183 cursorLoc(x, y, true)
2184 elseif key == 209 then
2185 -- Page down
2186 y = math.min(math.max(y + edh, 1), #lines)
2187 x = math.min(lines[y]:len() + 1, x)
2188 cursorLoc(x, y, true)
2189 end
2190 elseif e == "char" and allowEditorEvent and (displayCode and true or
2191 y + scrolly - 1 == liveErr.line) then
2192 local shouldIgnore = false
2193 for k, v in pairs(liveCompletions) do
2194 if key == v and lines[y]:find(k, 1, true) and lines[y]:sub(x, x) == v then
2195 shouldIgnore = true
2196 end
2197 end
2198
2199 local addOne = false
2200 if not shouldIgnore then
2201 for k, v in pairs(liveCompletions) do
2202 if key == k and lines[y]:sub(x, x) ~= k then key = key .. v addOne = true end
2203 end
2204 lines[y] = lines[y]:sub(1, x - 1) .. key .. lines[y]:sub(x, -1)
2205 end
2206
2207 x = x + (addOne and 1 or key:len())
2208 local force = false
2209 if y - scrolly + offy < offy + 1 then force = true end
2210 drawLine(y)
2211 cursorLoc(x, y, force)
2212 elseif e == "mouse_click" and key == 1 then
2213 if cy > 1 then
2214 if cx <= offx and cy - offy == liveErr.line - scrolly then
2215 displayCode = not displayCode
2216 drawLine(liveErr.line)
2217 else
2218 local oldy = y
2219 y = math.min(math.max(scrolly + cy - offy, 1), #lines)
2220 x = math.min(math.max(scrollx + cx - offx, 1), lines[y]:len() + 1)
2221 if oldy ~= y then drawLine(oldy, y) end
2222 cursorLoc(x, y)
2223 end
2224 else
2225 local a = triggerMenu(cx, cy)
2226 if a then
2227 local opt = executeMenuItem(a, path)
2228 if opt then return opt end
2229 end
2230 end
2231 elseif e == "shortcut" then
2232 local a = shortcuts[key .. " " .. cx]
2233 if a then
2234 local parent = nil
2235 local curx = 0
2236 for i, mv in ipairs(menu) do
2237 for _, iv in pairs(mv) do
2238 if iv == a then
2239 parent = menu[i][1]
2240 break
2241 end
2242 end
2243 if parent then break end
2244 curx = curx + mv[1]:len() + 3
2245 end
2246 local menux = curx + 2
2247
2248 -- Flash menu item
2249 term.setCursorBlink(false)
2250 term.setCursorPos(menux, 1)
2251 term.setBackgroundColor(colors[theme.background])
2252 term.write(string.rep(" ", parent:len() + 2))
2253 term.setCursorPos(menux + 1, 1)
2254 term.write(parent)
2255 sleep(0.1)
2256 drawMenu()
2257
2258 -- Execute item
2259 local opt = executeMenuItem(a, path)
2260 if opt then return opt end
2261 end
2262 elseif e == "mouse_scroll" then
2263 if key == -1 and scrolly > 0 then
2264 scrolly = scrolly - 1
2265 if os.clock() - scrollClock > 0.0005 then
2266 draw()
2267 term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
2268 end
2269 scrollClock = os.clock()
2270 hasScrolled = true
2271 elseif key == 1 and scrolly < #lines - edh then
2272 scrolly = scrolly + 1
2273 if os.clock() - scrollClock > 0.0005 then
2274 draw()
2275 term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
2276 end
2277 scrollClock = os.clock()
2278 hasScrolled = true
2279 end
2280 elseif e == "timer" and key == tid then
2281 drawLine(y)
2282 tid = os.startTimer(3)
2283 end
2284
2285 -- Draw
2286 if hasScrolled and os.clock() - scrollClock > 0.1 then
2287 draw()
2288 term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
2289 hasScrolled = false
2290 end
2291
2292 -- Autosave
2293 if os.clock() - autosaveClock > autosaveInterval then
2294 saveFile(path, lines)
2295 autosaveClock = os.clock()
2296 end
2297
2298 -- Errors
2299 if os.clock() - liveErrorClock > 1 then
2300 local prevLiveErr = liveErr
2301 liveErr = curLanguage.parseError(nil)
2302 local code = ""
2303 for _, v in pairs(lines) do code = code .. v .. "\n" end
2304
2305 liveErr = curLanguage.getCompilerErrors(code)
2306 liveErr.line = math.min(liveErr.line - 2, #lines)
2307 if liveErr ~= prevLiveErr then draw() end
2308 liveErrorClock = os.clock()
2309 end
2310 end
2311
2312 return "menu"
2313end
2314
2315
2316-- -------- Open File
2317
2318local function newFile()
2319 local wid = w - 13
2320
2321 -- Get name
2322 title("Lua IDE - New File")
2323 local name = centerRead(wid, "/")
2324 if not name or name == "" then return "menu" end
2325 name = "/" .. name
2326
2327 -- Clear
2328 title("Lua IDE - New File")
2329 term.setTextColor(colors[theme.textColor])
2330 term.setBackgroundColor(colors[theme.promptHighlight])
2331 for i = 8, 10 do
2332 term.setCursorPos(w/2 - wid/2, i)
2333 term.write(string.rep(" ", wid))
2334 end
2335 term.setCursorPos(1, 9)
2336 if fs.isDir(name) then
2337 centerPrint("Cannot Edit a Directory!")
2338 sleep(1.6)
2339 return "menu"
2340 elseif fs.exists(name) then
2341 centerPrint("File Already Exists!")
2342 local opt = prompt({{"Open", w/2 - 9, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal")
2343 if opt == "Open" then return "edit", name
2344 elseif opt == "Cancel" then return "menu" end
2345 else return "edit", name end
2346end
2347
2348local function openFile()
2349 local wid = w - 13
2350
2351 -- Get name
2352 title("Lua IDE - Open File")
2353 local name = centerRead(wid, "/")
2354 if not name or name == "" then return "menu" end
2355 name = "/" .. name
2356
2357 -- Clear
2358 title("Lua IDE - New File")
2359 term.setTextColor(colors[theme.textColor])
2360 term.setBackgroundColor(colors[theme.promptHighlight])
2361 for i = 8, 10 do
2362 term.setCursorPos(w/2 - wid/2, i)
2363 term.write(string.rep(" ", wid))
2364 end
2365 term.setCursorPos(1, 9)
2366 if fs.isDir(name) then
2367 centerPrint("Cannot Open a Directory!")
2368 sleep(1.6)
2369 return "menu"
2370 elseif not fs.exists(name) then
2371 centerPrint("File Doesn't Exist!")
2372 local opt = prompt({{"Create", w/2 - 11, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal")
2373 if opt == "Create" then return "edit", name
2374 elseif opt == "Cancel" then return "menu" end
2375 else return "edit", name end
2376end
2377
2378
2379-- -------- Settings
2380
2381local function update()
2382--[[
2383 local function draw(status)
2384 title("LuaIDE - Update")
2385 term.setBackgroundColor(colors[theme.prompt])
2386 term.setTextColor(colors[theme.textColor])
2387 for i = 8, 10 do
2388 term.setCursorPos(w/2 - (status:len() + 4), i)
2389 write(string.rep(" ", status:len() + 4))
2390 end
2391 term.setCursorPos(w/2 - (status:len() + 4), 9)
2392 term.write(" - " .. status .. " ")
2393
2394 term.setBackgroundColor(colors[theme.errHighlight])
2395 for i = 8, 10 do
2396 term.setCursorPos(w/2 + 2, i)
2397 term.write(string.rep(" ", 10))
2398 end
2399 term.setCursorPos(w/2 + 2, 9)
2400 term.write(" > Cancel ")
2401 end
2402
2403 if not http then
2404 draw("HTTP API Disabled!")
2405 sleep(1.6)
2406 return "settings"
2407 end
2408
2409 draw("Updating...")
2410 local tID = os.startTimer(10)
2411 http.request(updateURL)
2412 while true do
2413 local e, but, x, y = os.pullEvent()
2414 if (e == "key" and but == 28) or
2415 (e == "mouse_click" and x >= w/2 + 2 and x <= w/2 + 12 and y == 9) then
2416 draw("Cancelled")
2417 sleep(1.6)
2418 break
2419 elseif e == "http_success" and but == updateURL then
2420 local new = x.readAll()
2421 local curf = io.open(ideLocation, "r")
2422 local cur = curf:read("*a")
2423 curf:close()
2424
2425 if cur ~= new then
2426 draw("Update Found")
2427 sleep(1.6)
2428 local f = io.open(ideLocation, "w")
2429 f:write(new)
2430 f:close()
2431
2432 draw("Click to Exit")
2433 while true do
2434 local e = os.pullEvent()
2435 if e == "mouse_click" or (not isAdvanced() and e == "key") then break end
2436 end
2437 return "exit"
2438 else
2439 draw("No Updates Found!")
2440 sleep(1.6)
2441 break
2442 end
2443 elseif e == "http_failure" or (e == "timer" and but == tID) then
2444 draw("Update Failed!")
2445 sleep(1.6)
2446 break
2447 end
2448 end
2449]]--
2450
2451 return "settings"
2452end
2453
2454local function changeTheme()
2455 title("LuaIDE - Theme")
2456 term.setCursorPos(1, 7)
2457 centerPrint("Themes are not available on the")
2458 centerPrint("treasure disk version of LuaIDE!")
2459 centerPrint("Download the full program from the")
2460 centerPrint("ComputerCraft Forums!")
2461
2462--[[
2463 if isAdvanced() then
2464 local disThemes = {"Back"}
2465 for _, v in pairs(availableThemes) do table.insert(disThemes, v[1]) end
2466 local t = scrollingPrompt(disThemes)
2467 local url = nil
2468 for _, v in pairs(availableThemes) do if v[1] == t then url = v[2] end end
2469
2470 if not url then return "settings" end
2471 if t == "Dawn (Default)" then
2472 term.setBackgroundColor(colors[theme.backgroundHighlight])
2473 term.setCursorPos(3, 3)
2474 term.clearLine()
2475 term.write("LuaIDE - Loaded Theme!")
2476 sleep(1.6)
2477
2478 fs.delete(themeLocation)
2479 theme = defaultTheme
2480 return "menu"
2481 end
2482
2483 term.setBackgroundColor(colors[theme.backgroundHighlight])
2484 term.setCursorPos(3, 3)
2485 term.clearLine()
2486 term.write("LuaIDE - Downloading...")
2487
2488 fs.delete("/.LuaIDE_temp_theme_file")
2489 download(url, "/.LuaIDE_temp_theme_file")
2490 local a = loadTheme("/.LuaIDE_temp_theme_file")
2491
2492 term.setCursorPos(3, 3)
2493 term.clearLine()
2494 if a then
2495 term.write("LuaIDE - Loaded Theme!")
2496 fs.delete(themeLocation)
2497 fs.move("/.LuaIDE_temp_theme_file", themeLocation)
2498 theme = a
2499 sleep(1.6)
2500 return "menu"
2501 end
2502
2503 term.write("LuaIDE - Could Not Load Theme!")
2504 fs.delete("/.LuaIDE_temp_theme_file")
2505 sleep(1.6)
2506 return "settings"
2507 else
2508 term.setCursorPos(1, 8)
2509 centerPrint("Themes are not available on")
2510 centerPrint("normal computers!")
2511 end
2512]]--
2513end
2514
2515local function settings()
2516 title("LuaIDE - Settings")
2517
2518 local opt = prompt({{"Change Theme", w/2 - 17, 8}, {"Return to Menu", w/2 - 19, 13},
2519 --[[{"Check for Updates", w/2 + 2, 8},]] {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err],
2520 highlight = colors[theme.errHighlight]}}, "vertical", true)
2521 if opt == "Change Theme" then return changeTheme()
2522-- elseif opt == "Check for Updates" then return update()
2523 elseif opt == "Return to Menu" then return "menu"
2524 elseif opt == "Exit IDE" then return "exit" end
2525end
2526
2527
2528-- -------- Menu
2529
2530local function menu()
2531 title("Welcome to LuaIDE " .. version)
2532
2533 local opt = prompt({{"New File", w/2 - 13, 8}, {"Open File", w/2 - 14, 13},
2534 {"Settings", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err],
2535 highlight = colors[theme.errHighlight]}}, "vertical", true)
2536 if opt == "New File" then return "new"
2537 elseif opt == "Open File" then return "open"
2538 elseif opt == "Settings" then return "settings"
2539 elseif opt == "Exit IDE" then return "exit" end
2540end
2541
2542
2543-- -------- Main
2544
2545local function main(arguments)
2546 local opt, data = "menu", nil
2547
2548 -- Check arguments
2549 if type(arguments) == "table" and #arguments > 0 then
2550 local f = "/" .. shell.resolve(arguments[1])
2551 if fs.isDir(f) then print("Cannot edit a directory.") end
2552 opt, data = "edit", f
2553 end
2554
2555 -- Main run loop
2556 while true do
2557 -- Menu
2558 if opt == "menu" then opt = menu() end
2559
2560 -- Other
2561 if opt == "new" then opt, data = newFile()
2562 elseif opt == "open" then opt, data = openFile()
2563 elseif opt == "settings" then opt = settings()
2564 end if opt == "exit" then break end
2565
2566 -- Edit
2567 if opt == "edit" and data then opt = edit(data) end
2568 end
2569end
2570
2571-- Load Theme
2572if fs.exists(themeLocation) then theme = loadTheme(themeLocation) end
2573if not theme and isAdvanced() then theme = defaultTheme
2574elseif not theme then theme = normalTheme end
2575
2576-- Run
2577local _, err = pcall(function()
2578 parallel.waitForAny(function() main(args) end, monitorKeyboardShortcuts)
2579end)
2580
2581-- Catch errors
2582if err and not err:find("Terminated") then
2583 term.setCursorBlink(false)
2584 title("LuaIDE - Crash! D:")
2585
2586 term.setBackgroundColor(colors[theme.err])
2587 for i = 6, 8 do
2588 term.setCursorPos(5, i)
2589 term.write(string.rep(" ", 36))
2590 end
2591 term.setCursorPos(6, 7)
2592 term.write("LuaIDE Has Crashed! D:")
2593
2594 term.setBackgroundColor(colors[theme.background])
2595 term.setCursorPos(2, 10)
2596 print(err)
2597
2598 term.setBackgroundColor(colors[theme.prompt])
2599 local _, cy = term.getCursorPos()
2600 for i = cy + 1, cy + 4 do
2601 term.setCursorPos(5, i)
2602 term.write(string.rep(" ", 36))
2603 end
2604 term.setCursorPos(6, cy + 2)
2605 term.write("Please report this error to")
2606 term.setCursorPos(6, cy + 3)
2607 term.write("GravityScore! ")
2608
2609 term.setBackgroundColor(colors[theme.background])
2610 if isAdvanced() then centerPrint("Click to Exit...", h - 1)
2611 else centerPrint("Press Any Key to Exit...", h - 1) end
2612 while true do
2613 local e = os.pullEvent()
2614 if e == "mouse_click" or (not isAdvanced() and e == "key") then break end
2615 end
2616
2617 -- Prevent key from being shown
2618 os.queueEvent(event_distract)
2619 os.pullEvent()
2620end
2621
2622-- Exit
2623term.setBackgroundColor(colors.black)
2624term.setTextColor(colors.white)
2625term.clear()
2626term.setCursorPos(1, 1)
2627centerPrint("Thank You for Using Lua IDE " .. version)
2628centerPrint("Made by GravityScore")
2629end
2630function maze3d()
2631--[[
2632 Project info:
2633
2634 Name: Maze 3D
2635 Creator: Jesusthekiller
2636 Language: Lua (CC)
2637 Website: None
2638 License: GNU GPL
2639 License file can be fount at www.jesusthekiller.com/license-gpl.html
2640
2641 Version: 2.1
2642]]--
2643
2644--[[
2645 Big thanks to Gopher for 3D engine!
2646 http://www.computercraft.info/forums2/index.php?/topic/10786-wolf3d-style-3d-engine-proof-of-concept/page__hl__wolf3d
2647]]--
2648
2649--[[
2650 Changelog:
2651 1.0:
2652 Initial Release
2653 2.0:
2654 No-HTTP version for Treasure disk
2655 2.1:
2656 No more temp files!
2657]]--
2658
2659--[[
2660 LICENSE:
2661
2662 Maze 3D
2663 Copyright (c) 2013 Jesusthekiller
2664
2665 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
2666
2667 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2668
2669 See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
2670]]--
2671
2672-- The color check
2673if (not term.isColor()) or turtle then
2674 print("This program has to be run on advanced computer.")
2675 error()
2676end
2677
2678-- The cprint
2679local function cwrite(msg)
2680 msg = tostring(msg)
2681 local x, y = term.getCursorPos()
2682 term.setCursorPos((51-#msg)/2, y)
2683 write(msg)
2684end
2685
2686local function cprint(msg)
2687 cwrite(msg.."\n")
2688end
2689
2690-- The splash
2691term.setBackgroundColor(colors.black)
2692term.setTextColor(colors.white)
2693term.clear()
2694
2695paintutils.drawImage({[1]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=0,[8]=1,[9]=1,[10]=0,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[2]={[1]=1,[2]=1,[3]=0,[4]=1,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=0,[14]=0,[15]=0,[16]=1,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[3]={[1]=1,[2]=0,[3]=1,[4]=0,[5]=1,[6]=0,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=0,[13]=0,[14]=1,[15]=1,[16]=0,[17]=0,[18]=1,[19]=1,[20]=1,[21]=0,},[4]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=0,[15]=0,[16]=0,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[5]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[6]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=0,},[7]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=0,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=0,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[8]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=128,[15]=128,[16]=512,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[9]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[10]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[11]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=128,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[12]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=128,[9]=0,[10]=0,[11]=0,[12]=0,[13]=128,[14]=128,[15]=128,[16]=128,},}, 15, 3)
2696
2697parallel.waitForAny(
2698 function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end,
2699 function() term.setBackgroundColor(colors.black); term.setTextColor(colors.white) while true do term.setCursorPos(18, 16); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end
2700)
2701
2702-- The size
2703local size
2704
2705repeat
2706 term.setCursorPos(1, 16)
2707 term.clearLine()
2708
2709 cwrite("Enter maze size (5-99):")
2710 size = read()
2711
2712 size = tonumber(size)
2713 if not size then
2714 size = 0
2715 end
2716until size > 4 and size < 100
2717
2718-- The generate
2719local function mazeGen(mx, my)
2720
2721 --[[
2722 Format:
2723
2724 maze.x.y.(1/2/3/4) = true/false
2725
2726 1 - top
2727 2 - bottom
2728 3 - right
2729 4 - left
2730 ]]--
2731
2732 local maze = {}
2733 for i = 1, mx do
2734 maze[i] = {}
2735 for j = 1, my do
2736 maze[i][j] = {}
2737 for k = 1, 4 do
2738 maze[i][j][k] = true
2739 end
2740 end
2741 end
2742
2743 local vis = 1
2744 local tot = mx * my
2745 local curr = {}
2746 curr.x = math.random(1, mx)
2747 curr.y = math.random(1, my)
2748 local stack = {}
2749
2750 while vis < tot do
2751 local intact = {}
2752 local x = curr.x
2753 local y = curr.y
2754
2755 if x - 1 >= 1 and maze[x-1][y][1] and maze[x-1][y][2] and maze[x-1][y][3] and maze[x-1][y][4] then -- Check for full cells
2756 intact[#intact+1] = {x-1, y, 1}
2757 end
2758
2759 if x + 1 <= mx and maze[x+1][y][1] and maze[x+1][y][2] and maze[x+1][y][3] and maze[x+1][y][4] then
2760 intact[#intact+1] = {x+1, y, 2}
2761 end
2762
2763 if y + 1 <= my and maze[x][y+1][1] and maze[x][y+1][2] and maze[x][y+1][3] and maze[x][y+1][4] then
2764 intact[#intact+1] = {x, y+1, 3}
2765 end
2766
2767 if y - 1 >= 1 and maze[x][y-1][1] and maze[x][y-1][2] and maze[x][y-1][3] and maze[x][y-1][4] then
2768 intact[#intact+1] = {x, y-1, 4}
2769 end
2770
2771 if #intact > 0 then
2772 local i = math.random(1, #intact) -- Choose random
2773
2774 if intact[i][3] == 1 then -- Set intact's attached wall to false
2775 maze[intact[i][1]][intact[i][2]][2] = false
2776 elseif intact[i][3] == 2 then
2777 maze[intact[i][1]][intact[i][2]][1] = false
2778 elseif intact[i][3] == 3 then
2779 maze[intact[i][1]][intact[i][2]][4] = false
2780 elseif intact[i][3] == 4 then
2781 maze[intact[i][1]][intact[i][2]][3] = false
2782 end
2783
2784 maze[x][y][intact[i][3]] = false -- Set attached wall to false
2785
2786 vis = vis + 1 -- Increase vis
2787
2788 stack[#stack+1] = intact[i] -- Add to stack
2789 else
2790 local tmp = table.remove(stack) -- Get last cell
2791 curr.x = tmp[1]
2792 curr.y = tmp[2]
2793 end
2794 end
2795
2796 return maze
2797end
2798
2799local m = mazeGen(size, size)
2800
2801-- The game init
2802local posx = 2
2803local posy = 2
2804
2805local offsetx = 51/2-2
2806local offsety = 19/2-2
2807
2808-- The maze-to-table
2809local tab = {}
2810
2811for x = 1, size * 2 + 1 do
2812 tab[x] = {}
2813
2814 for y = 1, size * 2 + 1 do
2815 if x % 2 == 0 and y % 2 == 0 then -- Fill cells (empty)
2816 tab[x][y] = " "
2817 elseif x % 2 == 1 and y % 2 == 1 then -- Fill corners (full)
2818 tab[x][y] = "1"
2819 end
2820 end
2821end
2822
2823for x, tV in ipairs(m) do
2824 for y, v in ipairs(tV) do
2825 if x == size and y == size then
2826 v[1] = v[1] and "2" or " "
2827 v[2] = v[2] and "2" or " "
2828 v[3] = v[3] and "2" or " "
2829 v[4] = v[4] and "2" or " "
2830 tab[x*2-1][y*2] = v[1] -- Up
2831 tab[x*2+1][y*2] = v[2] -- Down
2832 tab[x*2][y*2+1] = v[3] -- Right
2833 tab[x*2][y*2-1] = v[4] -- Left
2834 else
2835 v[1] = v[1] and "1" or " "
2836 v[2] = v[2] and "1" or " "
2837 v[3] = v[3] and "1" or " "
2838 v[4] = v[4] and "1" or " "
2839 tab[x*2-1][y*2] = v[1] -- Up
2840 tab[x*2+1][y*2] = v[2] -- Down
2841 tab[x*2][y*2+1] = v[3] -- Right
2842 tab[x*2][y*2-1] = v[4] -- Left
2843 end
2844 end
2845end
2846
2847local gtab = {}
2848
2849for k, v in ipairs(tab) do
2850 gtab[#gtab+1] = table.concat(v)
2851end
2852
2853size = size * 2 + 1
2854
2855--[[
2856local template = fs.open("maze3d_template", "r")
2857local game = fs.open("maze3d_game", "w")
2858
2859game.writeLine("local mapH, mapW = "..size..","..size)
2860game.writeLine("local dir = "..(gtab[2]:sub(3,3) == " " and '0' or '88'))
2861game.writeLine("local map = {")
2862
2863for k, v in ipairs(gtab) do
2864 game.writeLine('"'..v..'",')
2865end
2866
2867game.writeLine("}")
2868
2869game.writeLine(template.readAll())
2870game.close()
2871template.close()
2872
2873shell.run("maze3d_game")
2874
2875fs.delete("maze3d_game")
2876fs.delete("maze3d_template")]]
2877
2878local mapH, mapW = size, size
2879local dir = gtab[2]:sub(3,3) == " " and '0' or '88'
2880local map = gtab
2881local startdir = dir
2882
2883------------------------------------------------------------------------------------------------------
2884--GOPHER'S CODE HERE
2885
2886local buffer=term
2887local loadedAPI=false
2888
2889local stime = os.clock()
2890
2891if redirect then
2892 buffer=redirect.createRedirectBuffer()
2893 print("redirect API found, using buffer")
2894else
2895 local pe=printError
2896 rawset(_G,"printError",error)
2897 local ok, err=pcall(os.loadAPI,"redirect")
2898 if not ok then
2899 print("trying "..shell.dir().."/redirect")
2900 ok,err=pcall(os.loadAPI,shell.dir().."/redirect")
2901 end
2902 if ok then
2903 print("Loaded redirect API, using buffer")
2904 buffer=redirect.createRedirectBuffer()
2905 loadedAPI=true
2906 else
2907 print("redirect API not found or could not be loaded, drawing directly; this may cause flickering.")
2908 end
2909 rawset(_G,"printError",pe)
2910end
2911
2912local colorSchemes = {
2913 {0,8}, --white+gray
2914 {3,11}, --blue
2915 {6,14}, --red
2916 {5,13}, --green
2917 {4,1}, --yellow/orange
2918}
2919
2920
2921local function cast(cx,cy,angle)
2922 --direction vector
2923 local vx,vy=math.cos(angle), math.sin(angle)
2924 local slope=vy/vx
2925 --next distance, x and y axis points
2926 local ndx, ndy
2927 --steps, distance and block
2928 local dsx, dsy, bsx, bsy
2929 if vx<0 then
2930 local x=(cx%1)
2931 bsx=-1
2932 ndx=math.sqrt(x*x*(1+slope*slope))
2933 dsx=math.sqrt((1+slope*slope))
2934 else
2935 local x=1-(cx%1)
2936 bsx=1
2937 ndx=math.sqrt(x*x*(1+slope*slope))
2938 dsx=math.sqrt((1+slope*slope))
2939 end
2940
2941 if vy<0 then
2942 local y=(cy%1)
2943 bsy=-1
2944 ndy=math.sqrt(y*y*(1+1/(slope*slope)))
2945 dsy=math.sqrt((1+1/(slope*slope)))
2946 else
2947 local y=1-(cy%1)
2948 bsy=1
2949 ndy=math.sqrt(y*y*(1+1/(slope*slope)))
2950 dsy=math.sqrt((1+1/(slope*slope)))
2951 end
2952
2953 local x,y=math.floor(cx),math.floor(cy)
2954 while x>0 and x<=mapW and y>0 and y<=mapH do
2955 local hitD
2956 local isX
2957 if ndx<ndy then
2958 --x crossing is next
2959 x=x+bsx
2960 isX=true
2961 hitD=ndx
2962 ndx=ndx+dsx
2963 else
2964 y=y+bsy
2965 isX=false
2966 hitD=ndy
2967 ndy=ndy+dsy
2968 end
2969 local wall=map[y]:sub(x,x)
2970 if wall~=" " then
2971
2972 return colorSchemes[tonumber(wall)][isX and 1 or 2], hitD
2973 end
2974 end
2975end
2976
2977local w,h=term.getSize()
2978local centerX, centerY=math.floor((w+1)/2), math.floor((h+1)/2)
2979
2980local px, py=2.5,2.5
2981--local dir=0
2982local fx,fy
2983local speed=.1
2984local turnSpeed=4
2985
2986local function turn(amt)
2987 dir=dir+amt
2988 fx,fy=math.cos(math.rad(dir)), math.sin(math.rad(dir))
2989end
2990
2991turn(0)
2992
2993--build table of angles and base distances per scanline
2994local screenDist=.55*w
2995local scan={}
2996
2997for x=1,w do
2998 local t={}
2999 scan[x]=t
3000 t.angle=math.atan2(x-centerX,screenDist)
3001 t.dist=((x-centerX)^2+screenDist^2)^.5/screenDist
3002end
3003
3004local function redraw()
3005 local oldTerm
3006 if buffer.isBuffer then
3007 oldTerm = term.redirect(buffer)
3008 end
3009 for x=1,w do
3010 local wall,dist=cast(px,py,math.rad(dir)+scan[x].angle)
3011 if wall then
3012 --calc wall height based on distance
3013 local height=scan[x].dist/dist
3014 height=math.floor(math.min(height*centerY,(h+1)/2))
3015 term.setBackgroundColor(colors.gray)
3016 for y=1,(h+1)/2-height-1 do
3017 term.setCursorPos(x,y)
3018 term.write(" ")
3019 end
3020 for y=centerY+height+1,h do
3021 term.setCursorPos(x,y)
3022 term.write(" ")
3023 end
3024 term.setBackgroundColor(2^wall)
3025 for y=centerY-height,centerY+height do
3026 term.setCursorPos(x,y)
3027 term.write(" ")
3028 end
3029 end
3030 end
3031 if buffer.isBuffer then
3032 term.redirect(oldTerm)
3033 buffer.blit()
3034 end
3035end
3036
3037local function clampCollision(x,y,radius)
3038 --am I *in* a block?
3039 local gx,gy=math.floor(x),math.floor(y)
3040 if map[gy]:sub(gx,gx)~=" " then
3041 --I am. Complete fail, do nothing.
3042 return x,y
3043 end
3044
3045 --ok, check the neighbors.
3046 local right=math.floor(x+radius)>gx
3047 local left=math.floor(x-radius)<gx
3048 local front=math.floor(y-radius)<gy
3049 local back=math.floor(y+radius)>gy
3050
3051 local pushed=false
3052
3053 if right and map[gy]:sub(gx+1,gx+1)~=" " then
3054 --push left
3055 pushed=true
3056 x=gx+1-radius
3057 elseif left and map[gy]:sub(gx-1,gx-1)~=" " then
3058 --push right
3059 pushed=true
3060 x=gx+radius
3061 end
3062
3063 if front and map[gy-1]:sub(gx,gx)~=" " then
3064 --push back
3065 pushed=true
3066 y=gy+radius
3067 elseif back and map[gy+1]:sub(gx,gx)~=" " then
3068 --push forward
3069 pushed=true
3070
3071
3072
3073 y=gy+1-radius
3074 end
3075
3076 --if I wasn't pushed out on any side, I might be hitting a corner
3077 if not pushed then
3078 --square rad
3079 local r2=radius^2
3080 local pushx,pushy=0,0
3081 if left then
3082 if front and map[gy-1]:sub(gx-1,gx-1)~=" " then
3083 --check front-left
3084 local dist2=(gx-x)^2+(gy-y)^2
3085 if dist2<r2 then
3086 local pushd=(r2-dist2)/2^.5
3087 pushx,pushy=pushd,pushd
3088 end
3089 elseif back and map[gy+1]:sub(gx-1,gx-1)~=" " then
3090 local dist2=(gx-x)^2+(gy+1-y)^2
3091 if dist2<r2 then
3092 local pushd=(r2-dist2)/2^.5
3093 pushx,pushy=pushd,-pushd
3094 end
3095 end
3096 elseif right then
3097 if front and map[gy-1]:sub(gx+1,gx+1)~=" " then
3098 --check front-left
3099 local dist2=(gx+1-x)^2+(gy-y)^2
3100 if dist2<r2 then
3101 local pushd=(r2-dist2)/2^.5
3102 pushx,pushy=-pushd,pushd
3103 end
3104 elseif back and map[gy+1]:sub(gx+1,gx+1)~=" " then
3105 local dist2=(gx+1-x)^2+(gy+1-y)^2
3106 if dist2<r2 then
3107 local pushd=(r2-dist2)/2^.5
3108 pushx,pushy=-pushd,-pushd
3109 end
3110 end
3111 end
3112 x=x+pushx
3113 y=y+pushy
3114 end
3115
3116 return x,y
3117end
3118
3119term.setBackgroundColor(colors.black)
3120--term.setTextColor(colors.white)
3121term.clear()
3122term.setCursorPos(1, 1)
3123
3124term.setTextColor(colors.yellow)
3125write("Move: ")
3126term.setTextColor(colors.lime)
3127print("WASD")
3128
3129term.setTextColor(colors.yellow)
3130write("Turn: ")
3131term.setTextColor(colors.lime)
3132print("Left/Right arrow")
3133
3134term.setTextColor(colors.yellow)
3135write("Teleport to start: ")
3136term.setTextColor(colors.lime)
3137print("R")
3138
3139term.setTextColor(colors.yellow)
3140write("Quit: ")
3141term.setTextColor(colors.lime)
3142print("Q\n")
3143
3144term.setTextColor(colors.white)
3145write("Goal: go to ")
3146term.setTextColor(colors.lightBlue)
3147write("blue")
3148term.setTextColor(colors.white)
3149print(" spot (opposite corner of the map)\n\n\n\n")
3150
3151term.setTextColor(colors.white)
3152cprint("Press any key to start!")
3153
3154os.pullEvent("key")
3155
3156local frameTimer=os.startTimer(0.5)
3157local prevTick=0
3158local dirty=true
3159local win = false
3160while true do
3161 px,py=clampCollision(px,py,.25)
3162 if dirty then
3163 redraw()
3164 dirty=false
3165 end
3166
3167 local e={os.pullEvent()}
3168 if e[1]=="key" then
3169 if e[2]==keys.left then
3170 turn(-turnSpeed)
3171 dirty=true
3172 elseif e[2]==keys.right then
3173 turn(turnSpeed)
3174 dirty=true
3175 elseif e[2]==keys.up or e[2]==keys.w then
3176 px=px+fx*speed
3177 py=py+fy*speed
3178 dirty=true
3179 elseif e[2]==keys.down or e[2]==keys.s then
3180 px=px-fx*speed
3181 py=py-fy*speed
3182 dirty=true
3183 elseif e[2]==keys.a then
3184 px=px+fy*speed
3185 py=py-fx*speed
3186 dirty=true
3187 elseif e[2]==keys.d then
3188 px=px-fy*speed
3189 py=py+fx*speed
3190 dirty=true
3191 elseif e[2]==keys.q then
3192 break
3193 elseif e[2]==keys.r then
3194 px,py = 2.5,2.5
3195 dir=startdir
3196 dirty=true
3197 end
3198
3199 if px >= mapW-1 and py >= mapH-1 then
3200 win = true
3201 break
3202 end
3203 end
3204end
3205
3206
3207if loadedAPI then
3208 os.unloadAPI("redirect")
3209end
3210
3211-- JESUS PART
3212
3213-- The win/loose message
3214term.setBackgroundColor(colors.white)
3215term.setTextColor(colors.black)
3216term.clear()
3217term.setCursorPos(1, 1)
3218
3219if win then
3220 local ntime = os.clock()
3221 write("\n")
3222 cprint("Congratulations!")
3223 cprint("You made it in")
3224 cprint(tostring(math.floor((ntime-stime)/60)).." minutes and "..tostring(math.ceil((ntime-stime)%60)).." seconds")
3225 cprint("Size of maze: "..(mapW-1)/2)
3226sleep(1)
3227else
3228 write("\n")
3229 cprint("Oh noes D:")
3230end
3231
3232
3233
3234parallel.waitForAny(
3235 function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end,
3236 function() term.setBackgroundColor(colors.white); term.setTextColor(colors.black) while true do term.setCursorPos(18, 14); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end
3237)
3238
3239term.setBackgroundColor(colors.black)
3240term.setTextColor(colors.white)
3241term.clear()
3242term.setCursorPos(1, 1)
3243cprint(" Maze 3D by JTK. Thanks for playing!")
3244cprint("3D engine by Gopher, He is A-W-E-S-O-M-E")
3245end
3246function maze2d()
3247--[[
3248 Project info:
3249
3250 Name: Maze
3251 Creator: Jesusthekiller
3252 Language: Lua (CC)
3253 Website: None
3254 License: GNU GPL
3255 License file can be fount at www.jesusthekiller.com/license-gpl.html
3256
3257 Version: 1.2
3258]]--
3259
3260--[[
3261 Changelog:
3262 1.0:
3263 Initial Release
3264 1.1:
3265 Typos D:
3266 1.2:
3267 New logo
3268 Time fixed
3269]]--
3270
3271--[[
3272 LICENSE:
3273
3274 Maze
3275 Copyright (c) 2013 Jesusthekiller
3276
3277 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
3278
3279 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3280
3281 See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
3282]]--
3283
3284-- The maze
3285
3286-- The cprint
3287local function cwrite(msg)
3288 msg = tostring(msg)
3289 local x, y = term.getCursorPos()
3290 term.setCursorPos((51-#msg)/2, y)
3291 write(msg)
3292end
3293
3294local function cprint(msg)
3295 cwrite(msg.."\n")
3296end
3297
3298-- The splash
3299term.setBackgroundColor(colors.black)
3300term.setTextColor(colors.white)
3301term.clear()
3302
3303term.setCursorPos(27, 8)
3304print("Nano maze!")
3305
3306paintutils.drawImage({[1]={[1]=1,[2]=1,[3]=1,[4]=1,[5]=1,[6]=1,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=1,[13]=0,[14]=0,[15]=1,[16]=0,[17]=0,[18]=1,[19]=0,[20]=0,[21]=1,[22]=0,[23]=0,[24]=1,[25]=0,[26]=0,[27]=1,},[2]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=0,[6]=1,[7]=0,[8]=0,[9]=0,[10]=1,[11]=0,[12]=1,[13]=1,[14]=0,[15]=1,[16]=0,[17]=1,[18]=0,[19]=1,[20]=0,[21]=1,[22]=1,[23]=0,[24]=1,[25]=0,[26]=1,[27]=0,[28]=1,},[3]={[1]=1,[2]=1,[3]=1,[4]=1,[5]=0,[6]=1,[7]=1,[8]=1,[9]=0,[10]=1,[11]=0,[12]=1,[13]=0,[14]=1,[15]=1,[16]=0,[17]=1,[18]=0,[19]=1,[20]=0,[21]=1,[22]=0,[23]=1,[24]=1,[25]=0,[26]=0,[27]=1,},[4]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=1,[9]=0,[10]=1,},[5]={[1]=1,[2]=0,[3]=1,[4]=1,[5]=1,[6]=1,[7]=0,[8]=1,[9]=0,[10]=1,[11]=0,[12]=1,[13]=0,[14]=0,[15]=0,[16]=1,[17]=0,[18]=0,[19]=1,[20]=0,[21]=0,[22]=1,[23]=1,[24]=0,[25]=0,[26]=1,[27]=1,[28]=1,},[6]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=0,[8]=0,[9]=0,[10]=1,[11]=0,[12]=1,[13]=1,[14]=0,[15]=1,[16]=1,[17]=0,[18]=1,[19]=0,[20]=1,[21]=0,[22]=0,[23]=1,[24]=0,[25]=0,[26]=1,[27]=1,},[7]={[1]=1,[2]=1,[3]=1,[4]=1,[5]=1,[6]=1,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=1,[13]=0,[14]=1,[15]=0,[16]=1,[17]=0,[18]=1,[19]=0,[20]=1,[21]=0,[22]=0,[23]=1,[24]=1,[25]=0,[26]=1,[27]=1,[28]=1,},}, 13, 5)
3307
3308parallel.waitForAny(
3309 function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end,
3310 function() term.setBackgroundColor(colors.black); term.setTextColor(colors.white) while true do term.setCursorPos(18, 14); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end
3311)
3312
3313-- The size
3314local size
3315
3316repeat
3317 term.setCursorPos(1, 14)
3318 term.clearLine()
3319
3320 cwrite("Enter maze size (5-99):")
3321 size = read()
3322
3323 size = tonumber(size)
3324 if not size then
3325 size = 0
3326 end
3327until size > 4 and size < 100
3328
3329-- The generate
3330local function mazeGen(mx, my)
3331
3332 --[[
3333 Format:
3334
3335 maze.x.y.(1/2/3/4) = true/false
3336
3337 1 - top
3338 2 - bottom
3339 3 - right
3340 4 - left
3341 ]]--
3342
3343 local maze = {}
3344 for i = 1, mx do
3345 maze[i] = {}
3346 for j = 1, my do
3347 maze[i][j] = {}
3348 for k = 1, 4 do
3349 maze[i][j][k] = true
3350 end
3351 end
3352 end
3353
3354 local vis = 1
3355 local tot = mx * my
3356 local curr = {}
3357 curr.x = math.random(1, mx)
3358 curr.y = math.random(1, my)
3359 local stack = {}
3360
3361 while vis < tot do
3362 local intact = {}
3363 local x = curr.x
3364 local y = curr.y
3365
3366 if x - 1 >= 1 and maze[x-1][y][1] and maze[x-1][y][2] and maze[x-1][y][3] and maze[x-1][y][4] then -- Check for full cells
3367 intact[#intact+1] = {x-1, y, 1}
3368 end
3369
3370 if x + 1 <= mx and maze[x+1][y][1] and maze[x+1][y][2] and maze[x+1][y][3] and maze[x+1][y][4] then
3371 intact[#intact+1] = {x+1, y, 2}
3372 end
3373
3374 if y + 1 <= my and maze[x][y+1][1] and maze[x][y+1][2] and maze[x][y+1][3] and maze[x][y+1][4] then
3375 intact[#intact+1] = {x, y+1, 3}
3376 end
3377
3378 if y - 1 >= 1 and maze[x][y-1][1] and maze[x][y-1][2] and maze[x][y-1][3] and maze[x][y-1][4] then
3379 intact[#intact+1] = {x, y-1, 4}
3380 end
3381
3382 if #intact > 0 then
3383 local i = math.random(1, #intact) -- Choose random
3384
3385 if intact[i][3] == 1 then -- Set intact's attached wall to false
3386 maze[intact[i][1]][intact[i][2]][2] = false
3387 elseif intact[i][3] == 2 then
3388 maze[intact[i][1]][intact[i][2]][1] = false
3389 elseif intact[i][3] == 3 then
3390 maze[intact[i][1]][intact[i][2]][4] = false
3391 elseif intact[i][3] == 4 then
3392 maze[intact[i][1]][intact[i][2]][3] = false
3393 end
3394
3395 maze[x][y][intact[i][3]] = false -- Set attached wall to false
3396
3397 vis = vis + 1 -- Increase vis
3398
3399 stack[#stack+1] = intact[i] -- Add to stack
3400 else
3401 local tmp = table.remove(stack) -- Get last cell
3402 curr.x = tmp[1]
3403 curr.y = tmp[2]
3404 end
3405 end
3406
3407 return maze
3408end
3409
3410local m = mazeGen(size, size)
3411
3412-- The game init
3413local posx = 2
3414local posy = 2
3415
3416local offsetx = 51/2-2
3417local offsety = 19/2-2
3418
3419local stime = os.clock()
3420
3421-- The maze-to-table
3422local tab = {}
3423
3424for x = 1, size * 2 + 1 do
3425 tab[x] = {}
3426
3427 for y = 1, size * 2 + 1 do
3428 if x % 2 == 0 and y % 2 == 0 then -- Fill cells (empty)
3429 tab[x][y] = false
3430 elseif x % 2 == 1 and y % 2 == 1 then -- Fill corners (full)
3431 tab[x][y] = true
3432 end
3433 end
3434end
3435
3436for x, tV in ipairs(m) do
3437 for y, v in ipairs(tV) do
3438 tab[x*2-1][y*2] = v[1] -- Up
3439 tab[x*2+1][y*2] = v[2] -- Down
3440 tab[x*2][y*2+1] = v[3] -- Right
3441 tab[x*2][y*2-1] = v[4] -- Left
3442 end
3443end
3444
3445-- The game itself
3446repeat
3447 -- Print map
3448 term.setBackgroundColor(colors.white)
3449 term.clear()
3450
3451 if posx == 2 and posy == 2 then
3452 term.setCursorPos(1, 1)
3453 term.setTextColor(colors.black)
3454 print("Controls: WASD")
3455 print("Back to start: R")
3456 print("Quit: Q")
3457 print("Goal: Step on # (It's on bottom right corner)")
3458 print("\nGood Luck!")
3459 end
3460
3461 --[[
3462 term.setTextColor(colors.black)
3463 term.setCursorPos(1, 19)
3464 write("X: "..posx.." Y: "..posy)
3465 ]]
3466
3467 for x, tV in ipairs(tab) do -- Print the map
3468 for y, v in ipairs(tV) do
3469 if offsety+y > 20 then
3470 break
3471 end
3472
3473 term.setCursorPos(offsetx+x, offsety+y)
3474
3475 if v then
3476 term.setBackgroundColor(colors.black)
3477 else
3478 term.setBackgroundColor(colors.white)
3479 end
3480
3481 if offsety+y < 20 and offsety+y > 0 and offsetx+x < 52 and offsetx+x > 0 then
3482 if x == size*2 and y == size*2 then
3483 if term.isColor() then
3484 term.setTextColor(colors.cyan)
3485 end
3486 write("#")
3487 else
3488 write(" ")
3489 end
3490 end
3491 end
3492
3493 if offsetx+x > 51 then
3494 break
3495 end
3496 end
3497
3498 term.setCursorPos(51/2, 19/2)
3499 term.setBackgroundColor(colors.white)
3500
3501 if term.isColor() then
3502 term.setTextColor(colors.red)
3503 else
3504 term.setTextColor(colors.black)
3505 end
3506
3507 write("X")
3508
3509 -- Wait for key
3510
3511 local e, k = os.pullEvent("char")
3512
3513 if k == "a" and (not tab[posx-1][posy]) then
3514 posx = posx - 1
3515 offsetx = offsetx + 1
3516 end
3517
3518 if k == "d" and (not tab[posx+1][posy]) then
3519 posx = posx + 1
3520 offsetx = offsetx - 1
3521 end
3522
3523 if k == "w" and (not tab[posx][posy-1]) then
3524 posy = posy - 1
3525 offsety = offsety + 1
3526 end
3527
3528 if k == "s" and (not tab[posx][posy+1]) then
3529 posy = posy + 1
3530 offsety = offsety - 1
3531 end
3532
3533 if k == "q" then
3534 break
3535 end
3536
3537 if k == "r" then
3538 posx = 2
3539 posy = 2
3540
3541 offsetx = 51/2-2
3542 offsety = 19/2-2
3543 end
3544until posx == size*2 and posy == size*2
3545
3546-- The win/loose message
3547term.setBackgroundColor(colors.white)
3548term.setTextColor(colors.black)
3549term.clear()
3550term.setCursorPos(1, 1)
3551
3552if posx == size*2 and posy == size*2 then
3553 local ntime = os.clock()
3554 write("\n")
3555 cprint("Congratulations!")
3556 cprint("You made it in")
3557 cprint(tostring(math.floor((ntime-stime)/60)).." minutes and "..tostring(math.ceil((ntime-stime)%60)).." seconds")
3558 cprint("Size of maze: "..size)
3559else
3560 write("\n")
3561 cprint("Oh noes D:")
3562end
3563
3564parallel.waitForAny(
3565 function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end,
3566 function() term.setBackgroundColor(colors.white); term.setTextColor(colors.black) while true do term.setCursorPos(18, 14); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end
3567)
3568
3569term.setBackgroundColor(colors.black)
3570term.setTextColor(colors.white)
3571term.clear()
3572term.setCursorPos(1, 1)
3573cprint(" Maze by JTK. Thanks for playing!")
3574end
3575
3576
3577
3578--
3579--Buttons
3580loadSHIT()
3581local event, button, x, y = os.pullEvent("mouse_click")
3582if x > 0 and x < 4 and y > 0 and y < 4 then
3583Paintclick()
3584elseif x > 4 and x < 8 and y > 0 and y < 4 then
3585os.run({}, "calc")
3586elseif x > 8 and x < 12 and y > 0 and y < 4 then
3587os.run({}, "rom/programs/fun/adventure.lua")
3588elseif x > 12 and x < 16 and y > 0 and y < 4 then
3589security()
3590elseif x > 16 and x < 20 and y > 0 and y < 4 then
3591term.clear()
3592term.setCursorPos(1,1)
3593os.run({},"rom/programs/shell.lua")
3594elseif x > 20 and x < 24 and y > 0 and y < 4 then
3595term.clear()
3596term.setCursorPos(1,1)
3597shell.run("worm")
3598elseif x > 0 and x < 4 and y > 4 and y < 8 then
3599shell.run("npaintpro bckgrnd")
3600elseif x > 4 and x < 8 and y > 4 and y < 8 then
3601term.clear()
3602term.setCursorPos(1,1)
3603shell.run("skype")
3604elseif x > 8 and x < 12 and y > 4 and y < 8 then
3605game()
3606elseif x > 12 and x < 16 and y > 4 and y < 8 then
3607luaide()
3608elseif x > 16 and x < 20 and y > 4 and y < 8 then
3609maze2d()
3610elseif x > 20 and x < 24 and y > 4 and y < 8 then
3611maze3d()
3612else
3613shell.run("home")
3614end