This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Neraphi's profile picture

Simplifying a code

Started by Neraphi, 04 January 2013 - 06:30 PM
Neraphi #1
Posted 04 January 2013 - 07:30 PM
Hello! I'm not sure whether this is the right forum, but it seemed the most appropiate.
I've been playing with computercraft for about a week now and I'm new to this coding thing. I've managed to write a script for an elevator running on redpower frames. It's painstaikingly slow, but it seemed like a good project to get into computercraft. I love the fact that it works, but it's only 3 floors and for every floor I need a seperate function which could be quite lengthy if there's 20 floors or more. Is there a way to be rid of that?

The code has two computers communicating over rednet, one inside the elevator and one by the framemotors.

The elevator code:

http://pastebin.com/LdWuyPt3

The menu table thing I got from an lp on youtube called "Computerizing Minecraft"

The framemotor code:

http://pastebin.com/wS4WgZVX


On another note, if anyone could direct me to a tutorial on any menu I'd be grateful. Still haven't figured out how to add a border to this one.

Thanks in advance ^^

edit: I figure I can make it work if I could send 2 variables over rednet, I have no idea how to do that though.

Nera
remiX #2
Posted 04 January 2013 - 08:56 PM
Only way I can think of how to simplify the elevator code is by removing the handler functions and put the functions within the table, but simplifed.
You only need to open the mode once, and close it once - at the beginning and end of the code, or atleast that's what I do/prefer.

The table can be changed to this:
floorMenu = {
[1] = { text = "1st Floor", handler = function cFloor = 1 end },
[2] = { text = "2nd Floor", handler = function cFloor = 2 end },
[3] = { text = "3rd Floor", handler = function cFloor = 3 end }
}
and then the onITem() function:
function onItem( menu ) -- starts the menu function(s1, s2 and s3 dependent on which was selected)
    menu[sItem].handler()
    rednet.send(2, tostring(cFloor), true)
end

Other than this, you can't really shorten the code much :P/>

As for the the framemotor code, you can see that you repeat the loops in the if statement so there has to be a way of simplifying that.
This can be achieved by a simple (cFloor<sFloor and colours.red or colours.white) within the rs.setBunbledOutput()

This should work, but I haven't tried it, so give it a try :)/>

-- Local Variables
local cFloor = 1
-- Rednet Info
rednet.open("top")
repeat
    local event,p1,p2, = os.pullEvent()
    if event == "rednet_message" and p1 == 1 then
        sFloor = tonumber(p2) -- Converts the rednet message into a number
        mElev = sFloor - cFloor -- Finds how many floors the elevator needs to move
        for i=1,mElev do
            for i=1,4 do -- The elevator needs 4 redstone pulses to move 1 floor
                rs.setBundledOutput("back", (cFloor<sFloor and colours.red or colours.white)) -- here
                sleep(0.4)
                rs.setBundledOutput("back", 0)
                sleep(0.4)
            end
        end
        cFloor = sFloor -- Rewrites the current floor variable for later use
    end
until event == "key" and p1 == keys.enter -- Exits the loop effectively ending the program

As for the border around around the menu, what kind of border? Colour? Text?
Neraphi #3
Posted 04 January 2013 - 11:26 PM
First a huge thank you, both of those changes help out a lot.
I had no idea you could contain (if that's the right word) an "if" statement like that. The table did need "()" after the function and I changed the variable, but now regardless of how many floors I add I'd only need to edit the table.

As for the menu, for starters anything to be honest. I've been trying to make something simple like this:
Spoiler***************
* text : var1 *
* text2 :var2 *
***************

I got it to print the asterisks on the top, bottom and left side. but the right side disappeared and printed 1's instead and I'm still confused as to why.
So anything simple, with controlable menu and any type of border around it. I've been trying to find something on the site, but the search returns mostly player made os systems.

Again, thank you, it helped a lot!

- Nera
remiX #4
Posted 05 January 2013 - 12:10 AM
First a huge thank you, both of those changes help out a lot.
I had no idea you could contain (if that's the right word) an "if" statement like that. The table did need "()" after the function and I changed the variable, but now regardless of how many floors I add I'd only need to edit the table.
Yeah, it's quite an awesome feature to use within printing/writing too.
Oh woops, forgot the () haha :P/>

As for the menu, for starters anything to be honest. I've been trying to make something simple like this:
Spoiler***************
* text : var1 *
* text2 :var2 *
***************

I got it to print the asterisks on the top, bottom and left side. but the right side disappeared and printed 1's instead and I'm still confused as to why.
So anything simple, with controlable menu and any type of border around it. I've been trying to find something on the site, but the search returns mostly player made os systems.

Again, thank you, it helped a lot!

- Nera

Mm, do you still have the code of when you tried it? I'll go through it and see what's wrong
Neraphi #5
Posted 05 January 2013 - 12:46 AM
Unfortunately, no. But I used same menu type as above, just modified the table and printMenu() function.

something like:

mainMenu = {
[1] = { text = "***********************" },
[2] = { text = "*" "Statement 1", p1, text2 = "*"}
}
(and so on)

And printing code:


function printMenu( menu )
[indent=1]for i=1,#menu do[/indent]
[indent=2]print(menu[i].text..p1..text2)[/indent]
[indent=1]end[/indent]
end		

Or something along these silly lines.
I'd define the p1 variable as either "on" or "off". I don't know whether this is the one that returned the 1's though since I kept changing it.
remiX #6
Posted 05 January 2013 - 01:51 AM
If you're only have < 10 floors then this should be fine, replace it with your printMenu function


function printMenu( menu ) -- Displays the menu with >> << markers to select floors with.
    text = "*******************"
    term.setCursorPos(math.ceil((w-#text)/2)+1, h/2-2)
    write(text)
    text = "*				 *" -- 17 spaces between the asterixes (fix this because posting it here on forums screws it up
    term.setCursorPos(math.ceil((w-#text)/2)+1, h/2-1)
    write(text)
    for i=1,#menu do
        -- Left asterix
        term.setCursorPos(math.ceil((w-#text)/2)+1, h/2-1+i)
        write("*")
        -- Right asterix
        term.setCursorPos(math.ceil((w+#text)/2), h/2-1+i)
        write("*")
        term.setCursorPos(w/2-#menu[i].text/2-2, h/2-1+i) -- centers the menu
        if i == sItem then
            write(">> "..menu[i].text.." <<") -- Displays markers around the selected floor
        else
            write("   "..menu[i].text) -- Displays the other floors
        end
    end
    text = "*				 *" -- 17 spaces between the asterixes (fix this because posting it here on forums screws it up
    term.setCursorPos(math.ceil((w-#text)/2)+1, h/2 + #menu)
    write(text)
    text = "*******************"
    term.setCursorPos(math.ceil((w-#text)/2)+1, h/2 + #menu+1)
    write(text)
end


KaoS #7
Posted 05 January 2013 - 01:58 AM
bleeergh… why the over complication? allow me to show you my elevator code. it works just like yours except the terminal in the elevator uses a touchscreen interface

FRAME MOTOR COMPUTER

rednet.open('bottom')
local maxfloors=4
local oFile=io.open('floor','r')
local floor=tonumber(oFile:read())
oFile:close()
while true do
  local id,msg=rednet.receive()
  if id==1 and msg=='up' then
   print('up')
   for i=1,(floor==2 and 8 or 4) do
	rs.setOutput('back',true)
	sleep(0.4)
	rs.setOutput('back',false)
	sleep(0.4)
   end
   floor=floor-1
  elseif id==1 and msg=='down' and floor<maxfloors then
   print('down')
   for i=1,(floor==1 and 8 or 4) do
	rs.setOutput('top',true)
	sleep(0.4)
	rs.setOutput('top',false)
	sleep(0.4)
   end
   floor=floor+1
  end
  sleep(0.1)
  local oFile=io.open('floor','w')
  oFile:write(floor)
  oFile:close()
  rednet.send(1,tostring(floor))
end

INTERFACE COMPUTER

local oFile=io.open('floor','r')
local floor=tonumber(oFile:read())
oFile:close()
local mon=peripheral.wrap('back')
local size={mon.getSize()}
rednet.open('bottom')
local function disp()
  mon.clear()
  mon.setCursorPos(math.ceil(size[1]/2),1)
  mon.write('+')
  mon.setCursorPos(math.ceil(size[1]/2),math.ceil(size[2]/2))
  mon.write(string.sub(tostring(floor),1,1))
  mon.setCursorPos(math.ceil(size[1]/2),size[2])
  mon.write('-')
end
while true do
  disp()
  local evt={os.pullEvent()}
  if evt[1]=='monitor_touch' then
   if tonumber(evt[4])==1 then
	rednet.send(3,'up')
	print('up')
   elseif tonumber(evt[4])==size[2] then
	rednet.send(3,'down')
	print('down')
   end
  elseif evt[1]=='rednet_message' and evt[2]==3 then
   floor=tonumber(evt[3])
   local oFile=io.open('floor','w')
   oFile:write(floor)
   oFile:close()
  end
end

the touchscreen over complicated it a little but you really don't need to send anything but 'up' or 'down', if you really have to then use a serialized table. in case you were wondering it goes down 8 blocks the first time to avoid making a room where all of my thermopiles are

also it would be a good idea to store the current floor on a file so you can close minecraft at a lower floor and it will still know where it is. I do so in the above code
Neraphi #8
Posted 05 January 2013 - 12:25 PM
remiX:

Thank you again! That really helped out, I believe I'll be able to do some neat menus thanks to that =D
And I can't believe I didn't use the math options before, will definitely use it more from now on.

KaoS:

I was actually searching in the wiki for how to save info to a file, so that really helps out ^^
And I had no idea that the monitors had a touchscreen function… so that's bloody awesome! I believe I understood how your code works correctly, so I'll definitely play around with it, but I do want a terminal since I plan to add private floors that'd require a password.
Right now doing both seems actually somewhat feasible for my limited knowledge of the code so I'll try some different ideas I have ^^
(Don't give me the answer though ^^ I really want to try and learn on my own when possible rather than copying someone's code, even if I understand how it works =)

Again, thank you both! You've been very helpful.

- Nera
KaoS #9
Posted 05 January 2013 - 11:51 PM
Sounds like you're making a pretty cool system, good luck. don't forget you need advanced monitors for the touchscreen functionality