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