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