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