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

Code Causes Computer To Reboot?

Started by t3hcoolness, 15 February 2012 - 05:02 PM
t3hcoolness #1
Posted 15 February 2012 - 06:02 PM
Hey guys, I've been trying to make a program that causes a line of "O"s to bounce across the screen, but all it does is cause the computer to stop working and reboot ._.
Heres the code: http://pastebin.com/n4c9uKDC
What did I do wrong?
Advert #2
Posted 15 February 2012 - 06:29 PM
X and Y are 0, at some point.

Your first repeat loop does not handle this.

Here are some pointers: http://pastebin.com/LbDviNxD

There may still be other issues, though, so reply if you're still having trouble :D/>/>
t3hcoolness #3
Posted 15 February 2012 - 07:27 PM
X and Y are 0, at some point.

Your first repeat loop does not handle this.

Here are some pointers: http://pastebin.com/LbDviNxD

There may still be other issues, though, so reply if you're still having trouble :D/>/>

Not sure if what you added is what I need. X and Y can't be 0 at any point, given that the loops break upon the minimum and maximum being reached.
After setting some "breakpoints", it looks like this: http://pastebin.com/dzJLDgGx
The output I get now is just "2" repeated 1000 times until it reboots.
I'm guessing none of the if statements are being fired?
Espen #4
Posted 15 February 2012 - 08:28 PM
The if-statements are not firing, because x is 0 at that point and hasn't been modified yet.
And because the your first repeat-block only breaks when x == 50, it will repeat forever, since x is always 0.
You have to modify x somewhere, it won't increment automatically, you have to do this yourself with e.g. x = x + 1
CC terminates any program which doesn't yield for 10 seconds, otherwise it wouldn't do anything but loop and loop and loop and loop and loop …
t3hcoolness #5
Posted 15 February 2012 - 08:46 PM
The if-statements are not firing, because x is 0 at that point and hasn't been modified yet.
And because the your first repeat-block only breaks when x == 50, it will repeat forever, since x is always 0.
You have to modify x somewhere, it won't increment automatically, you have to do this yourself with e.g. x = x + 1
CC terminates any program which doesn't yield for 10 seconds, otherwise it wouldn't do anything but loop and loop and loop and loop and loop …
Thanks for the help! Getting further…. http://pastebin.com/fkXC5fc3
Right now, the "O"s go diagonally down to the right, like I wanted, but then it stops and freezes. So close!
Espen #6
Posted 16 February 2012 - 12:45 AM
TL;DR: Control the values of x and y!

You have some semantic errors in your program.
I'll first explain why your program still reaches an infinite loop (and thus gets terminated).

At the beginning x and y are both 1.
When we enter the REPEAT of the first IF-block they will both be incremented repeatedly by the rd() function, until x reaches 50 (you don't need to simultaneously check for y == 1, as that will never happen, because y is incremented again and again, like x. The moment x == 50, y will be 50 as well).
This will get us out of the REPEAT-block and towards the second IF-block.
But because y == 50 at this point (you haven't reset it), it won't trigger the IF-block, since that one expects y == 18.
So we pass over that whole block and reach the end of our first REPEAT-block, where the condition for x == 50 is checked.
Our x is indeed 50, so we will not loop around, but move on to the next REPEAT-block.

Within this block y is checked for either 18 or 1. But since y is still 50, neither of these two IF-blocks will fire.
And because x is also still 50 the REPEAT-block won't stop looping, for it is waiting that x == 1.
But that will never happen and thus it loops infinitely without doing anything, which leads to CC terminating your program after 10 seconds.

So what you have to do is to always remember in what states your two variables x and y will be in at any point in your program.
Don't just assume that they will be reset automatically. You have to make sure they will always be within the values you need them to be at any given point in the program, so that the checks both make sense and can/will be reached.


Alright, now about the other thing:
I'd advise against trying to print to coordinates off the screen. If you overshoot the y-coordinate, then it might print it, but not without a line-break at least and that might mess up your intended print behavior.
Also the screen has indeed a maximum width of 50. But if you attempt to print to the 50th coordinate, then that will produce a line-break and print the character at the beginning of the next line and thus lead to unintended behavior as well.
Therefore: only ever write to the 49th x-coordinate. The y-axis is no problem, you can go the full 18 lines there, without producing a line print. That is, only if you use write(), of course, since print() always produces a line-break.
And creating a line-break on the 18th y-coordinate will scroll your whole screen. :

Ok, I hope everything is understandable.
If you have any further questions, give us a holler. :D/>/>

Cheers!
t3hcoolness #7
Posted 20 February 2012 - 07:23 PM
So close! This is the end result now:


(That last rd in the bottom left happens last)

Here is the new code that accomplished this: http://pastebin.com/dMavvH0N

I can see the finish line!
Espen #8
Posted 20 February 2012 - 09:22 PM
You should replace the repeat-loops where you call the functions with while-loops so that the check for the coordinate-boundaries is done before they're called.
Also with your code there is no way to know what the last function call was. But you need to know that, especially if you want to loop back to the beginning.
I've modified your code a bit to make it do what I think you want to make it do, I hope you don't mind, just trying to help. ;)/>/>
Here you go:

term.clear()
term.setCursorPos(1,1)
local x = 1
local y = 1
function rd()
    term.setCursorPos(x,y)
    x, y = x + 1, y + 1
    write("rd")
    sleep(0.1)
    return "rd"
end
function ru()
    term.setCursorPos(x,y)
    x, y = x + 1, y - 1
    write("ru")
    sleep(0.1)
    return "ru"
end
function ld()
    term.setCursorPos(x,y)
    x, y = x - 1, y + 1
    write("ld")
    sleep(0.1)
    return "ld"
end
function lu()
    term.setCursorPos(x,y)
    x, y = x - 1, y - 1
    write("lu")
    sleep(0.1)
    return "lu"
end

local counter = 0
local last = "ru"   -- Initial state = 'ru' so that the first thing we do is go 'rd'.
while true do
    repeat
        if last == "ru" or last == "ld" then
            while ( y < 18 ) and ( x < 48 ) do  -- See info on coordinate x below.
                    last = rd()
            end
        end
        if last == "rd" or last == "lu" then
            while ( y > 1 ) and ( x < 48 ) do   -- See info on coordinate x below.
                    last = ru()
            end
        end
    until x >= 48   -- Since we are printing 2 characters, we can only print to coordinate 48 (maximum x - number of characters => 50 - 2 = 48)
    repeat
        if last == "lu" or last == "rd" then
            while ( y < 18 ) and ( x > 1 ) do
                    last = ld()
            end
        end
        if last == "ld" or last == "ru" then
            while ( y > 1 ) and ( x > 1 ) do
                    last = lu()
            end
        end
    until x <= 1

    -- Goes around 3 times and then ends.
    counter = counter + 1
    if counter >= 3 then break end
end
Not perfect, but for now it does what (I think) it is supposed to do.
Hope it helps, cheers!
Edited on 20 February 2012 - 08:24 PM
t3hcoolness #9
Posted 22 February 2012 - 03:27 PM
You should replace the repeat-loops where you call the functions with while-loops so that the check for the coordinate-boundaries is done before they're called.
Also with your code there is no way to know what the last function call was. But you need to know that, especially if you want to loop back to the beginning.
I've modified your code a bit to make it do what I think you want to make it do, I hope you don't mind, just trying to help. :)/>/>
Here you go:

((CODE))

Not perfect, but for now it does what (I think) it is supposed to do.
Hope it helps, cheers!

I'm going to try this, but wont "last = rd()" just define the variable rather than call it?
Also, I set the write()s to the name of the function just for debugging purposes <_</>/>
Casper7526 #10
Posted 22 February 2012 - 03:34 PM
Nope when he's doing last = rd() what happens is it calls the RD function and the last variable becomes the return result of the RD function
Espen #11
Posted 22 February 2012 - 06:17 PM
I'm going to try this, but wont "last = rd()" just define the variable rather than call it?
*What Casper said*
Only if you'd write last = rd without the brackets, then you'd be defining last as just another name/reference for the rd() function.

Also, I set the write()s to the name of the function just for debugging purposes :)/>/>
Yeah, I thought as much. And I have to admit that I tested it with only one character and a maximum x of 49 first.
When it was working as intended I changed it back and decreased the maximum allowed x, to make it conform more with your original code. <_</>/>
If you want to make it dynamic, then you could replace the concrete x and y numbers with variables and make the variables depend on the maximum screen size by making use of term.getSize().
But then again I'm not sure what your end goal for it is. At the moment it looks like an old school screen saver. :D/>/>