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

help with a function

Started by kain184, 25 July 2017 - 05:18 AM
kain184 #1
Posted 25 July 2017 - 07:18 AM
hello all i am writing a draconic reactor control program with computercraft and plethora. i am having an issue with one of the functions in my program. after scanning to find at which power output the reactor passes redstone level 8 on the code it blanks out and stops transmiting power. i was wondering if someone can help me rewrite this code and make it better.

function control()
	storagechg.setAnalogOutput(storagechgsde,0)
	
	if disabled["mainctl"] and not t.buttonList["active"]["active"] then
		t:toggleButton("active")
	end
	
	local times = 0
	oldfuel = fuel.getAnalogInput(fuelside)
	powerlevel = 1
	powerchng = true
	
	while true do
		term.clear()
		term.setCursorPos(1,1)

		if fuel.getAnalogInput(fuelside) > 14  then
			shldpwr.setAnalogOutput(shldsde,7)
			storagechg.setAnalogOutput(storagechgsde,15)
			mainpwr.setAnalogOutput(mainpwrsde,0)
			buttont("mainpwr","off")
			
			if times == 1 then
				local input = "reactor fuel low"
				sleep(5)
				http.post("http://server.jesusfreakserver.com/multicraft/mail.php?message="..textutils.urlEncode(input),"a")
				times = 2
			end
		elseif temp.getAnalogInput(tempsd) > 10 or sat.getAnalogInput(satsd) < 3 then
			mainpwr.setAnalogOutput(mainpwrsde,0)
			buttont("mainpwr","off")
		else
			if oldfuel < fuel.getAnalogInput(fuelside) then
				powerchng = true
			end
			
			buttont("mainpwr","on")

			if powerchng == true then
				for i = 1,15 do
					term.setCursorPos(1,1)
					print(i.." test powerlevel")
					
					if temp.getAnalogInput(tempsd) > 8 then
						powerchng = false
						mainpwr.setAnalogOutput(mainpwrsde,i-1)
						term.setCursorPos(1,1)
						print(math.floor(i-1).." final output")
						sleep()
						break
						--# it is right after this break that the program stops functioning i think or around this part. i have all of the program working in parallel with other parts such as a screen with progress bars and dialog buttons.
					else
						term.setCursorPos(1,1)
						mainpwr.setAnalogOutput(mainpwrsde,i)
						
						for i = 3,5 do
							term.setCursorPos(1,i)
							term.clearLine()
						end
						
						term.setCursorPos(1,3)
						local fuelstate = oldfuel < fuel.getAnalogInput(fuelside)
						print("has fuel change been detected" .. tostring(fuelstate) )
						print("temp is " ..temp.getAnalogInput(tempsd) )
						print("saturation is " ..sat.getAnalogInput(satsd) )
					end
					
					sleep(10)
				end
			end
		end
	end
end
Edited on 25 July 2017 - 11:20 PM
The Crazy Phoenix #2
Posted 25 July 2017 - 11:22 AM
The "break" statement ends the for loop. Once the for loop has ended, the program jumps back to the start of the while loop and "mainpwr.setAnalogOutput(mainpwrsde, 0)" runs.
If your intention is to continue the loop, use "continue" (jumps to the next iteration). If you want to do something else after finding the point where >8 then add code after the for loop.
Edited on 25 July 2017 - 05:59 PM
apemanzilla #3
Posted 25 July 2017 - 02:20 PM
The "break" statement ends the for loop. Once the for loop has ended, the program jumps back to the start of the while loop and "mainpwr.setAnalogOutput(mainpwrsde, 0)" runs.
If your intention is to continue the loop, use "continue" (jumps to the next iteration). If you want to do something else after finding the point where >8 then add code after the for loop.

Lua doesn't have continue.
kain184 #4
Posted 25 July 2017 - 05:43 PM
right it should jump back from the for loop to the while loop. the issue i am having is after the jump it just kind of resets. the power output shuts back off instead of staying at the level set with

								    powerchng = false
								    mainpwr.setAnalogOutput(mainpwrsde,i-1)
								    term.setCursorPos(1,1)
								    print(math.floor(i-1).." final output")
								    sleep()

what should happen is it sets the power than waits for a fuel level change with

if oldfuel < fuel.getAnalogInput(fuelside) then
		    powerchng = true
    end

but it does not it just kind of dies
The Crazy Phoenix #5
Posted 25 July 2017 - 08:08 PM
Here's your while body reduced only to conditions and calls that alter the output.


if fuel.getAnalogInput(fuelside) > 14 then
	mainpwr.setAnalogOutput(mainpwrsde, 0)
elseif temp.getAnalogInput(tempsd) > 10 or sat.getAnalogInput(satsd) < 3 then
	mainpwr.setAnalogOutput(mainpwrsde, 0)
elseif oldfuel < fuel.getAnalogInput(fuelside) then
	for i = 1, 15 do
		[...]
	end
end

You should check if the above is written the way you want it to behave.
If the issue still exists, check that the sleep just before the break has the right delay.

I recommend that you fix your indentation to make your code easier to read.
Edited on 25 July 2017 - 06:08 PM
Bomb Bloke #6
Posted 26 July 2017 - 02:02 AM
When a computer/turtle starts running code, ComputerCraft starts a ten second timer. If that code doesn't yield before that timer ends then ComputerCraft will either crash the script or the whole computer (depending on the nature of the functions your script is calling). After each yield, any other systems waiting to run code may do so, then after they've all yielded, processing continues with a new time limit.

The reason why is that running your code chews up valuable server processing power, and so it shouldn't be able to monopolise it. In fact, only ONE CC device can run code at a time: While one is doing something, none of the others can do anything until it yields.

Whether or not it takes more than ten seconds for your code to execute has a little to do with the power of the Minecraft server it's running on, and a lot to do with how often you allow your code to yield. Pulling events (eg getting typed characters or checking timers) triggers a yield, and many commands (eg turtle movements, sleeping, or getting text input from the user) have to pull events to work anyway. Basically, anything that triggers a pause is pulling an event in order to do it, and in order to pull an event the code yields.

In your code, you're running a "while true do" loop which will only sleep if:
  • fuel.getAnalogInput(fuelside) > 14, and times == 1 (though there's nothing here which'll set it to that)
  • not (fuel.getAnalogInput(fuelside) > 14) and not (temp.getAnalogInput(tempsd) > 10 or sat.getAnalogInput(satsd) < 3) and oldfuel < fuel.getAnalogInput(fuelside)
If neither of those condition lists a met, all of your sleep statements are bypassed. Some of your peripheral calls may trigger yields, but likely not all of them (if any) - you'd best ensure your loop sleeps upon every iteration.
Edited on 26 July 2017 - 12:02 AM