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

Help me please with my Programm

Started by PrinzJuliano, 30 March 2015 - 09:15 AM
PrinzJuliano #1
Posted 30 March 2015 - 11:15 AM
I wrote a program (Text content is in german but thats not important for now) and it should do the following:
-Print out a text
-Wait for key input/handle keyinput
-Redstone flickering

I want to use coroutines !!!!

This is my solution but it kinda doesn't work:

Spoiler

update = false
shouldRender = true
running = true
function clear()
  term.clear()
  term.setCursorPos(1,1)
end
function render()
  while running do
	if shouldRender then
	  clear()
	  print("+------------------+")
	  print("| PJOG Section Lua |")
	  print("| Redstone Furnace |")
	  print("+------------------+--------+")
	  print("| Druecke <g> um zu starten |")
	  print("| Druecke <s> um zu stoppen |")
	  print("+---------------+-----------+")
	  print("| Im Moment <"..(update and "R" or "S").."> |")
	  print("+---------------+")
	  shouldRender = false
	end
  end
end
function tick()
  while running do
  if update then
	rs.setOutput("bottom", true)
	sleep(1)
	rs.setOutput("bottom", false)
  end
  sleep(0)
  end
end
function waitFor()
  while running do
	e = {os.pullEvent()} --coroutine.yield
	if e[1] == "char" then
	  if e[2] == "g" then
		update = true
		shouldRender = true
	  elseif e[2] == "s" then
		update = false
		shouldRender = true
	  elseif e[2] == "q" then
		running = false
	  end
	end
  end
end
function time()
  while running do
  str = os.day.." "..textutils.formatTime(os.time(), true)
  w,h = term.getSize()
  term.setCursorPos(w-str:len(),h-1)
  term.write(str)
  end
end
local renderThread = coroutine.create(render)
local updateThread = coroutine.create(waitFor)
local actionThread = coroutine.create(tick)
local timer = coroutine.create(time)
function main()
  while running do
	e = {os.pullEvent()}
	resume = coroutine.resume(updateThread, unpack(e))
	coroutine.resume(renderThread)
	coroutine.resume(actionThread)
	coroutine.resume(timer)
  end
end
main()
Lupus590 #2
Posted 30 March 2015 - 01:28 PM
the parallel API is what you want
Edited on 30 March 2015 - 11:33 AM
Bomb Bloke #3
Posted 30 March 2015 - 01:44 PM
You kinda forgot to explain the details of your problem. I'm assuming it has something to do with you only providing event data to "updateThread", however - your other coroutines need it too!

But yeah, you could replace this whole block:

local renderThread = coroutine.create(render)
local updateThread = coroutine.create(waitFor)
local actionThread = coroutine.create(tick)
local timer = coroutine.create(time)
function main()
  while running do
        e = {os.pullEvent()}
        resume = coroutine.resume(updateThread, unpack(e))
        coroutine.resume(renderThread)
        coroutine.resume(actionThread)
        coroutine.resume(timer)
  end
end
main()

… with just:

parallel.waitForAll(render, waitFor, tick, time)
PrinzJuliano #4
Posted 30 March 2015 - 07:03 PM
Well I tried to apply it but for some reason the program freezes and makes the computer not reply to any commands (including ctrl+S/R)
So my problem is that the program freezes all the time after one round of rendering
KingofGamesYami #5
Posted 30 March 2015 - 07:21 PM
It should be impossible to freeze the computer to the pint of control+r not working. Are you using an emulator?
PrinzJuliano #6
Posted 30 March 2015 - 09:10 PM
I am using just minecraft and CC
MKlegoman357 #7
Posted 30 March 2015 - 10:33 PM
You never yield in your 'render' function, so when it starts running, it doesn't stop.
Bomb Bloke #8
Posted 30 March 2015 - 10:34 PM
It should be impossible to freeze the computer to the pint of control+r not working.

Rather, that's a symptom of the computer already having turned off, due to yield protection.

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, neither your render() nor time() functions yield. Try getting them to call sleep(1) or somesuch.
PrinzJuliano #9
Posted 31 March 2015 - 04:40 PM
Thanks for telling me the issue about yielding in a program.
It worked that i added a sleep(1) to the functions