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

[Lua/Error] - Program crashing - Can't figure out the error.

Started by DrLancer, 18 January 2013 - 10:52 PM
DrLancer #1
Posted 18 January 2013 - 11:52 PM
Hey guys, i'm trying to program a Guess the Number game, with a monitor and 3 redstone inputs.
However I'm running into a problem.
Whenever i start the program, it shows the text which it's supposed to, and then it suddenly crashes, without giving me any errors.
The computer just reboots.


Are there any way of capturing the last action the computer does before shutting down - and perhaps saving that into a file?

If you'd like to help me out, here's my code:
(and sorry if it's a mess, but I'm no pro ;)/>)

Spoiler


-- Placement of monitor.
-- top/bottom/left/right/front/back
local monitorSide = "top"

local rHighS = "left" -- redstone input for Higher guess.
local rLowS = "right" -- redstone input for Lower guess.
local rOKS = "bottom" -- redstone input for OK button.
local maxTries = 100 -- Max Tries 0=infinite.
local difficulty = "easy" -- easy/medium/hard

---------------------------------
-- DO NOT EDIT BELOW THIS LINE --
---------------------------------

-- Initial variables
local mon = peripheral.wrap(monitorSide)
local version = "1.0"
local number = 0
local win = false
local tries = 0
local guess = 1

-- Slowprint for monitor (18 char MAX)
function monitorsp(text,monitor)
  for x = 1, string.len(text) do
    char = string.sub(text,x,x)
    monitor.write(char)
    sleep(0.1)
  end
end

-- Faster to type moncur.
function moncur(x,y)
  mon.setCursorPos(x,y)
end

-- Raise Guess
function raiseG()
  if guess < 101 then
    guess = guess + 1
    moncur(1,7)
    mon.clearLine()
    mon.write("Guess: "..guess)  
  end
end

-- Lower Guess
function lowerG()
  if guess > 0 then
    guess = guess - 1
    moncur(1,7)
    mon.clearLine()
    mon.write("Guess: "..guess)  
  end
end

-- Set difficulty settings
if difficulty == "easy" then
  number = math.random(1,100)
elseif difficulty == "medium" then
  number = math.random(1,250)
elseif difficulty == "hard" then
  number = math.random(1,500)
else
  number = math.random(1,100)
end

-- Display
do
  mon.clear()
  moncur(1,1)
  mon.write("------------------")
  moncur(1,2)
  monitorsp("Welcome to HighLow",mon)
  moncur(1,3)
  mon.write("------------------")
  moncur(1,4)
  mon.write("Difficulty: "..difficulty)
  moncur(1,5)
  mon.write("Max Tries: "..maxTries)
  moncur(1,6)
  mon.write("------------------")
  sleep(3)
  moncur(1,2)
  mon.clearLine()
  moncur(1,2)
  mon.write("Tries: "..tries)
  moncur(1,7)
  mon.write("Guess: "..guess)  
end

-- Start the game
while true do
  if tries > maxTries then
    break
  else
    local event, param1 = os.pullEvent("redstone") -- Make sure the redstone only triggers once
    if event == "redstone" and redstone.getInput(rHighS) == true then
      raiseG()
    elseif event == "redstone" and redstone.getInput(rLowS) == true then
      lowerG()
    elseif event == "redstone" and redstone.getInput(rOKS) == true then
      tries = tries + 1
      moncur(1,2)
      mon.clearLine()
      mon.write("Tries: "..tries)
      if guess == number then
        win = true
        break
      else
        if guess < number then
          moncur(1,8)
          mon.clearLine()
          mon.write("Too Low!")
        else
          moncur(1,8)
          mon.clearLine()
          mon.write("Too High!")
        end        
      end
    end
  end
 sleep(0)
end

-- Outro
do
  mon.clear()
  moncur(1,4)
  mon.write("------------------")
  moncur(1,5)
  mon.write("-                -")
  moncur(1,6)
  mon.write("-    GAME OVER   -")
  moncur(1,7)
  mon.write("-                -")
  moncur(1,8)
  mon.write("------------------")
  moncur(1,6)
  if win == true then
    monitorsp("-    YOU WIN     -",mon)
  else
    monitorsp("-    YOU LOSE   -",mon)
  end
  moncur(1,10)
  monitorsp(("Tries: "..tries),mon)
end

Thanks in advance to anyone trying to help me out..

Edit:
Changed the codeblock to match my current code.
TheOriginalBIT solved my first problem - by adding a sleep(1) my program is now working.

New problem:
with sleep(0), 1 redstone button equals 20 points instead of 1.
with sleep(1), 1 redstone button equals 1 point - but is VERY slow to increment/decrement.
– Using os.pullEvent("redstone") solves this issue.

- Now working on a toggle switch to be able to use a lever for fast increment/decrement.
Edited on 19 January 2013 - 01:57 AM
remiX #2
Posted 19 January 2013 - 12:11 AM
Judt after it selects the difficulty, you have a 'do' which is invallid syntax for lua. What were you trying to do there
DrLancer #3
Posted 19 January 2013 - 12:17 AM
Judt after it selects the difficulty, you have a 'do' which is invallid syntax for lua. What were you trying to do there

It's just for easier reading when using Notepad++ so i can combine the different uhm.. places.
I'll try remove them and see if it works.
theoriginalbit #4
Posted 19 January 2013 - 12:17 AM
Judt after it selects the difficulty, you have a 'do' which is invallid syntax for lua. What were you trying to do there
"do" is actually correct syntax… give me a second to find a link... see under the heading "Local scope" http://lua-users.org...i/ScopeTutorial

I can actually see an unrelated post with your while loop… you will get a failed to yield error in there, you may want to add something like a sleep(0)
Edited on 18 January 2013 - 11:21 PM
DrLancer #5
Posted 19 January 2013 - 12:19 AM
– When i removed the Do and End, i'm able to notice a 2-3 line error message which blinks for a milisecond before shutdown. But i can't time my printscreen to get a good look at it..


Ok, so after adding a Sleep(0), the program doesn't crash anymore, however it's not functional.. At all.

When pressing one of the buttons (rHigh and rLow) nothing happens.
Do i have to use
 if redstone.getInput(rHighS) == true then 
instead of
 if rHigh == true then 
?

Edit:
After changing that code, i can now use the OK button, which will tell me that the guess is too low.
However, I'm unable to change the guess with the plus and minus button.
Okay, so now everything seems to be working - i made a typo in my raise/lower function.

I stumbled upon a new problem tho.
When i press a button, the redstone signal gives me a total of 20 points. instead of simply 1. I suppose its because of the length the redstone signal is active.

I can limit the signal by using sleep(1), if i use sleep(0.5) it gives 2 points each time.
So i tried adding a lever to enable fast increment and decrement of the guess, but that results in a VERY slow incr./decr. (1 per sec.)
Edited on 18 January 2013 - 11:58 PM
theoriginalbit #6
Posted 19 January 2013 - 01:51 AM
yeh the problem is that the pulse is lasting longer than the time it takes to loop. There are 2 plans of attack. you can sleep for the time the redstone pulse is on (sorry cant remember exact value) OR, and probably the best way to do it, is an event pull loop ( see here http://computercraft...ki/Os.pullEvent and here http://computercraft...Redstone_(event) for more details )…

Using your current method it just checks the state every loop, using an event pull loop will only trigger when the state changes. also a pull event loop yields so there is no need for that sleep(0) I suggested before…

Give it your best shot to implement those changes, and if you need any further help, just ask :)/>
Edited on 19 January 2013 - 12:52 AM
remiX #7
Posted 19 January 2013 - 02:01 AM
Judt after it selects the difficulty, you have a 'do' which is invallid syntax for lua. What were you trying to do there
"do" is actually correct syntax… give me a second to find a link... see under the heading "Local scope" http://lua-users.org...i/ScopeTutorial

I can actually see an unrelated post with your while loop… you will get a failed to yield error in there, you may want to add something like a sleep(0)

Oh.. that's interesting, sorry about the wrong info :P/>
theoriginalbit #8
Posted 19 January 2013 - 02:02 AM
Oh.. that's interesting, sorry about the wrong info :P/>
No problems… its a very good way of making sure parts of your program don't know about other parts. but it is kinda pointless for this usage…
DrLancer #9
Posted 19 January 2013 - 02:43 AM
Alright, so that os.pullEvent worked perfectly! Thanks so much!

As always, when something gets fixed, new issues arrive.

I had a lever set up at the same input as my button, to have the number increase/decrease rapidly.
However, using this new code with pullEvent, prevents me from doing so, as it only gets detected once per pulse.

Could you come with a tip on how to improve it so i can have a toggle button for having rapid increase/decrease instead of only once? (The toggle button would be a lever you could switch On/Off)


– Edited my original code from first post.
theoriginalbit #10
Posted 19 January 2013 - 02:51 AM
change it to keys instead :P/>

also whats your code look like now?
Edited on 19 January 2013 - 01:52 AM
DrLancer #11
Posted 19 January 2013 - 02:58 AM
change it to keys instead :P/>

also whats your code look like now?
Change what to keys? :huh:/>

My code is in the first post.
I'm editing my changes and posting it in that post each time :)/>
theoriginalbit #12
Posted 19 January 2013 - 03:04 AM
change it to keys instead :P/>

also whats your code look like now?
Change what to keys? :huh:/>

My code is in the first post.
I'm editing my changes and posting it in that post each time :)/>
the increment and decrement, to key press… :)/>

Ok ill look it over now :)/>

ahh ok sorry didn't realise, most people don't do that… :)/> thanx :)/>

EDIT: Hmmm well I'm not sure, it should work fine for a lever, unless its something I am missing ( which could be likely, its late here )

Maybe try testing it with some key events for say keys.up and keys.down and see if the results are the same, if it is then its most likely some logic somewhere slowing it down…
Edited on 19 January 2013 - 02:19 AM
DrLancer #13
Posted 19 January 2013 - 05:38 AM
change it to keys instead :P/>

also whats your code look like now?
Change what to keys? :huh:/>

My code is in the first post.
I'm editing my changes and posting it in that post each time :)/>
the increment and decrement, to key press… :)/>

Ok ill look it over now :)/>

ahh ok sorry didn't realise, most people don't do that… :)/> thanx :)/>

EDIT: Hmmm well I'm not sure, it should work fine for a lever, unless its something I am missing ( which could be likely, its late here )

Maybe try testing it with some key events for say keys.up and keys.down and see if the results are the same, if it is then its most likely some logic somewhere slowing it down…

Thats alright don't worry :)/>

I'm not sure how i would use key events, as I'm trying to make the computer be inaccessible, and force the user to use the physical buttons, and view what have to be viewed on the monitor.
Im thinking i could have an if statement, checking wether the toggle lever has been pressed, and then use the normal timing method, rather than the pullevent, and when its not toggled, the pullevent would be put to use.
Again, thanks for all the help giving to me in this programming course :)/>
TheOddByte #14
Posted 19 January 2013 - 06:08 AM
If you wonder how you use like key events then here is an example:
Spoiler

function keyEvents()
--NOTE: I used the W,A,S,D controls since those are the most basic in gameplay.
-- 200 = Up, 208 = Down, 28 = Enter

event, p1 = os.pullEvent()
if event == "char" and -- It doesn't need to be "char", It can also Be "key"
p1 == "w" then
--Do Something

elseif p1 == "a" then
--Do Something

elseif p1 == "s" then
--Do Something

elseif p1 == "d" then 
--Do Something
elseif p1 == 28 then -- This Is the Enter Key
--Do Something
             end
               end

Then run it so everytime you press it it does'nt exit:

while true do
keyEvents()
end
DrLancer #15
Posted 19 January 2013 - 06:45 AM
Thank for your sample code.

I've more or less fixed my problems..
There's only ONE problem left.

If the player forgets to DEactivate the toggle switch, when he/she presses the Guess button, the number of tries will be added with an interval of my sleep().
I tried putting the pullevent around and stuff, but that prevents my switch from working.

Heres my current code:


-- Placement of monitor.
-- top/bottom/left/right/front/back
local monitorSide = "top"

local rHighS = "left" -- redstone input for Higher guess.
local rLowS = "right" -- redstone input for Lower guess.
local rOKS = "bottom" -- redstone input for OK button.
local maxTries = 100 -- Max Tries 0=infinite.
local difficulty = "easy" -- easy/medium/hard
local rToggle = "back" -- Toggle switch placement

---------------------------------
-- DO NOT EDIT BELOW THIS LINE --
---------------------------------

-- Initial variables
local mon = peripheral.wrap(monitorSide)
local version = "1.0"
local number = 0
local win = false
local tries = 0
local guess = 1
local rToggleActive = false

-- Slowprint for monitor (18 char MAX)
function monitorsp(text,monitor)
  for x = 1, string.len(text) do
    char = string.sub(text,x,x)
    monitor.write(char)
    sleep(0.1)
  end
end

-- Faster to type moncur.
function moncur(x,y)
  mon.setCursorPos(x,y)
end

-- Raise Guess
function raiseG()
  if guess < 101 then
    guess = guess + 1
    moncur(1,7)
    mon.clearLine()
    mon.write("Guess: "..guess)  
  end
end

-- Lower Guess
function lowerG()
  if guess > 0 then
    guess = guess - 1
    moncur(1,7)
    mon.clearLine()
    mon.write("Guess: "..guess)  
  end
end

-- Set difficulty settings
if difficulty == "easy" then
  number = math.random(1,100)
elseif difficulty == "medium" then
  number = math.random(1,250)
elseif difficulty == "hard" then
  number = math.random(1,500)
else
  number = math.random(1,100)
end

-- Display
do
  mon.clear()
  moncur(1,1)
  mon.write("------------------")
  moncur(1,2)
  monitorsp("Welcome to HighLow",mon)
  moncur(1,3)
  mon.write("------------------")
  moncur(1,4)
  mon.write("Difficulty: "..difficulty)
  moncur(1,5)
  mon.write("Max Tries: "..maxTries)
  moncur(1,6)
  mon.write("------------------")
  sleep(3)
  moncur(1,2)
  mon.clearLine()
  moncur(1,2)
  mon.write("Tries: "..tries)
  moncur(1,7)
  mon.write("Guess: "..guess)  
end

-- Start the game
while true do
  if rToggle ~= nil then -- Able to toggle at all?
    if redstone.getInput(rToggle) == true then -- Is toggleswitch activated?
      rToggleActive = true
    else
      rToggleActive = false
    end
  end

  if tries > maxTries then
    break
  else
    if rToggleActive == true then
      if redstone.getInput(rLowS) == true then
        lowerG()
      elseif redstone.getInput(rHighS) == true then
        raiseG()
      end
    else    
      local event, param1 = os.pullEvent("redstone") -- Make sure the redstone only triggers once
      if event == "redstone" and redstone.getInput(rHighS) == true then
        raiseG()
      elseif event == "redstone" and redstone.getInput(rLowS) == true then
        lowerG()
      elseif event == "redstone" and redstone.getInput(rOKS) == true then
        tries = tries + 1
        moncur(1,2)
        mon.clearLine()
        mon.write("Tries: "..tries)
        if guess == number then
          win = true
          break
        else
          if guess < number then
            moncur(1,8)
            mon.clearLine()
            mon.write("Too Low!")
          else
            moncur(1,8)
            mon.clearLine()
            mon.write("Too High!")
          end
        end        
      end
    end

    if redstone.getInput(rOKS) == true then
      tries = tries + 1
      moncur(1,2)
      mon.clearLine()
      mon.write("Tries: "..tries)
      if guess == number then
        win = true
        break
      else
        if guess < number then
          moncur(1,8)
          mon.clearLine()
          mon.write("Too Low!")
        else
          moncur(1,8)
          mon.clearLine()
          mon.write("Too High!")
        end
      end
    end
  end
 sleep(0.2)
end

-- Outro
do
  mon.clear()
  moncur(1,4)
  mon.write("------------------")
  moncur(1,5)
  mon.write("-                -")
  moncur(1,6)
  mon.write("-    GAME OVER   -")
  moncur(1,7)
  mon.write("-                -")
  moncur(1,8)
  mon.write("------------------")
  moncur(1,6)
  if win == true then
    monitorsp("-    YOU WIN     -",mon)
  else
    monitorsp("-    YOU LOSE   -",mon)
  end
  moncur(1,10)
  monitorsp(("Tries: "..tries),mon)
end