I'm very new to Lua, and I'm doing a very simple text based adventure thing, but it wont work. My code is as follows:
while input ~= ("leave cave" or "leave") do
print("What do you want to do?")
input = io.read()
if input == "inspect" then
print("You are in a cave")
elseif input == "leave cave" or "leave" then
print("You leave the cave")
elseif input == "inv" then
for i,v in pairs(inv) do
print(i, v)
end
else
print("You didn't write a valid command...")
end
end
-- leave cave
input = ""
print("What do you want to do?")
input = io.read()
while input ~= "follow path" do
if input == "inspect" then
print("You are at the base of a hill. There is a path.")
elseif input == "follow path" then
print("You follow the path. There is a gate.")
elseif input == "inv" then
for i,v in pairs(inv) do
print(v)
end
else
print("That's not a valid command...")
end
end
What I'm trying to do is have it so whenever the user types leave, or leave cave, it proceeds to the next segment (the path one), however, when I type "leave" and then type "inspect" again it says "I am in a cave" rather than what it should be saying which is saying that you left, and you see a path. And when I type leave cave, and then inspect, it spams "You are at the base of a hill. THERE IS A PATH" over and over, indefinitely.
And when I type "inv" it doesn't print my inventory, and instead prints "You left the cave," but doesn't actually leave.
a or b can't make a value that means "either a or b" -- that would be too complicated.
In fact, if you ask it to choose between two strings, it will just pick the first:
print("leave cave" or "leave") --> leave cave
or is only meant to be used on booleans -- you have to combine it on multiple full conditions:
while (input ~= "leave cave") and (input ~= "leave") do
In this case, a repeat ....... until <condition> loop might serve you better:
repeat
print("What do you want to do?")
input = io.read()
-- <do stuff>
until input == "leave" or input == "leave cave"
While or cannot accomplish such a complex operation, it is possible to recreate the effect yourself with some hacky metatable code.
Please note I do not reccomend using this code in any serious professional or commercial programs, or really at all for that matter, this code is inefficient and unecessary, however it is a fun piece of code to do exactly what you're looking for. It's just a fun way to experiment with the power of Lua.
local iseither
iseither = setmetatable({},{
__sub = function(arg1,arg2)
if arg2 == iseither then
arg2.Value = arg1
return arg2
else
if type(arg2) ~= "table" then
error("Second operator is -iseither- was not a table",2)
else
for i,v in ipairs(arg2) do
if arg1.Value == v then
arg1.Value = nil
return true
end
end
arg1.Value = nil
return false
end
end
end
})
print(1 -iseither- {1,2,3,4,5})
Related
I want the player to be able to choose a character so I print a list of four characters.
print("Choose a character")
print("1. the rocker")
print("2. the vocalist")
print("3. the drummer")
print("4. the bassist")
I then use the io.write function to allow the player to make a choice between characters 1 and 4. I save the choice in the menu_option variable. I know that I would have to add some code for error handling but I am not worried about that at the moment
io.write('Which character do you choose?')
menu_option = io.read()
I now want to create some conditionals to create a variable that will define the title of the character that the player chose.
if menu_option == 1 then
character = ("the rocker")
elseif menu_option == 2 then
character = ("the vocalist")
elseif menu_option == 3 then
character = ("the drummer")
elseif menu_option == 4 then
character = ("the bassist")
end
This is where my code begins to fail. The write function is correctly writing the choice (from 1 to 4) to the menu_option variable but my if statement block is not correctly functioning. The character variable remains nil.
What am I doing wrong? Thanks for any help you all can give me.
The wrong is that io.read() always returning a string.
You expected a number in your if conditions.
Now you have to correct each if like #Egor wrote in the comment or do...
menu_option = tonumber(io.read())
...and let the if' check for numbers
After that you can do in case of NaN (Not a Number) or entering nothing (i.e. hit only RETURN/ENTER)...
io.write('Which character do you choose? ')
local menu_option = tonumber(io.read())
if menu_option == empty then menu_option = math.random(4) end
-- empty == nil but better (human) readable
...for a random selection.
Moreover i suggest using more local variable declarations so it looks like...
-- File: character.lua
local character = ''
print("Choose a character:")
print("[1] the rocker")
print("[2] the vocalist")
print("[3] the drummer")
print("[4] the bassist")
io.write('Which character do you choose? ')
local menu_option = tonumber(io.read())
if menu_option == empty then menu_option = math.random(4) end
if menu_option == 1 then
character = "the rocker"
elseif menu_option == 2 then
character = "the vocalist"
elseif menu_option == 3 then
character = "the drummer"
elseif menu_option == 4 then
character = "the bassist"
end
print('You choosed:',character:upper())
-- Possible return values...
-- return character:upper(), menu_option -- Two values: first=string second=number
-- return os.exit(menu_option) -- Number can examined on bash with ${?}
-- ^-> Example: lua character.lua || printf '%d\n' ${?}
I want to do a program that tells the user if what kind of information is he telling...
that's what I have for now, but as you can see, it is missing the IF function to identify if it is a number, but I don't know how to get a number not using io.read('*number)
a = io.read()
if a == string.lower(a) then
print('It's a lower string')
end
if a == string.upper(a) then
print('It's an upper string')
end
pls help
Keep reading with a = io.read() and try to convert to a number:
a = io.read()
if tonumber(a) then
print("It's a number")
elseif a == string.lower(a) then
print("It's a lowercase string")
elseif a == string.upper(a) then
print("It's an uppercase string")
end
I'm working on a project where I want to update the clock on screen say every 5 seconds unless the user inputs something. This is the code I have so far,
function thread1()
term.clear()
term.setCursorPos(1,1)
write (" SteveCell ")
local time = os.time()
local formatTime = textutils.formatTime(time, false)
write (formatTime)
print ("")
print ("")
for i=1,13 do
write ("-")
end
print("")
print ("1. Clock")
print ("2. Calender")
print ("3. Memo")
print ("4. Shutdown")
for i=1,13 do
write ("-")
end
print ("")
print ("")
write ("Choose an option: ")
local choice = io.read()
local choiceValid = false
if (choice == "1") then
-- do this
elseif (choice == "2") then
-- do that
elseif (choice == "3") then
-- do this
elseif (choice == "4") then
shell.run("shutdown")
else
print ("Choice Invalid")
os.sleep(2)
shell.run("mainMenu")
end
end
function thread2()
localmyTimer = os.startTimer(5)
while true do
local event,timerID = os.pullEvent("timer")
if timerID == myTimer then break end
end
return
end
parallel.waitForAny(thread1, thread2)
shell.run("mainMenu")
Unfortunately it's not working. If someone could help me with this, I would really appreciate it. Thanks :)
You want to do something like this (Im not doing the correct on screen drawing, only the time)
local function thread1_2()
-- both threads in one!
while true do
local ID_MAIN = os.startTimer(5)
local ID = os.startTimer(0.05)
local e = { os.pullEvent() }
if e[1] == "char" then
-- Check all the options with variable e[2] here
print( string.format( "Pressed %s", e[2] ) )
break -- Getting out of the 'thread'
elseif e[1] == "timer" and e[2] == ID then
ID = os.startTimer(0.05) -- shortest interval in cc
redrawTime() -- Redraw and update the time in this function!!!
elseif e[1] == "timer" and e[2] == MAIN_ID then
break
end
end
end
Also, ask this in the proper forum, you have more chance getting an answer there!
Another note, get more into event handling, it really helps.
FYI Lua doesn't have 'multi-threading' as in executing multiple routines simultaneously. What it does have is 'thread parking.' You can switch between routines (yielding) and switch back and it will resume where it left off, but only a single routine will be active at any given time.
This is my go-to Lua reference, which explains in detail:
http://lua-users.org/wiki/CoroutinesTutorial
It is my first lua project and i have a trouble with skipping part of my code. I want the code to stop after part "Cool". So if i write good and it answers cool i want the rest of the code to stop since after that the next question is not relative anymore.
How it works:
Code says: Hello
You say: anything
Code says: How are you?
You say: good
after you say good it will say cool.
If you say anything other than good it will ask "Why?"
e.g. you say: bad
Code says: It will be alright
I want it to stop after "cool" and skip out the further part of the code.
os.execute(" cls ")
print("Hello")
odp = io.read()
if odp == string then
end
tof = true or false
print("How are you?")
odp2 = io.read()
if odp2 == "good" then print("Cool") tof = true
else print("Why?") tof = false
if tof == true then os.execute(" pause ")
end
end
odp3 = io.read()
if odp3 ~= math then print("It will be alright")
print("Okay, I have to go see you.")
end
os.execute(" pause ")
When you compile code, it becomes the body of a function. The prototypical way of exiting a function is with a return statement. A function can have zero or more return statements.
But, since you want to exit the program, you can instead call os.exit().
You've just got to nest your "if" statements differently. All you need to do is put the rest of the code into the "else" part of your "if" statement, like this:
os.execute(" cls ")
print("Hello")
odp = io.read()
if odp == string then
end
tof = true or false
print("How are you?")
odp2 = io.read()
if odp2 == "good" then
print("Cool")
tof = true
else
print("Why?")
tof = false
if tof == true then
os.execute(" pause ")
end
-- You had an "end" here.
odp3 = io.read()
if odp3 ~= math then
print("It will be alright")
print("Okay, I have to go see you.")
end
os.execute(" pause ")
end -- You literally just need to move it here.
That way, it only gets input from the user after it asks for it, and only if the user doesn't answer, "good" to the "How are you?" question.
Note that I re-indented the code, but it's still the same code in the same order. I just made it more standard-looking and easier to visually see the structure of the program.
I'm trying to make a 'simple' Y/N answer choice thing. (That you saw all the time on old programs) But an If Statement I'm using doesn't seem to want to work. I even print out the variable and it is nowhere near what i want to compare yet it still passes it.
--Porgram Functions
function check()
--Local Variables
local num = 0
local loop = true
io.write("Continue? (Y/N):")
--User input
local input = io.read()
while(loop==true) do
if (input=="y" or "Y") then
print("Ok!")
loop = true
num = 1
elseif (input=="n" or "N") then
print("Fine...")
num = 2
else
print("Invalid Answser!")
loop = true
num = 0
end
end
print(input)
return(num)
end
print (check())
I would've written your function like this:
function check()
io.write("Continue? (Y/N): ")
answer = io.read()
while( not (answer == "Y" or answer == "N") ) do
io.write("Invalid Answer! Try again (Y/N): ")
answer = io.read()
end
if answer == "Y" then
print("Ok!")
return 1
else
print("Fine...")
return 2
end
end
print(check())
Some examples of its use:
Continue? (Y/N): Huh?
Invalid Answer! Try again (Y/N): N
Fine...
2
>Exit code: 0
>lua -e "io.stdout:setvbuf 'no'" "a.lua"
Continue? (Y/N): Huh?
Invalid Answer! Try again (Y/N): Y
Ok!
1
A working version of your code would be:
function check()
local num = 0
local loop = true
io.write("Continue? (Y/N):")
while(loop==true) do
--User input
local input = io.read()
if (input == "y" or input == "Y") then
print("Ok!")
num = 1
loop = false --we want to stop looping if input is valid
elseif (input == "n" or input == "N") then
print("Fine...")
num = 2
loop = false --we want to stop looping if input is valid
else
print("Invalid Answser!")
-- loop = true no need to set looping to true again
num = 0
end
end
return(num)
end
The changes made were:
Get the user input inside the while loop, this way if the input is invalid and the loop goes again the same logic behind getting the input is used, we don't have to code two cases for getting input; one outside the loop the other within. It also pauses execution when the loop starts again, this was what was producing all that output!
input == "y" or "Y" doesn't do what you think. Instead it evaluates to (input == "y") or ("Y"), what you want it input == "y" or input == "Y".
You needed to set loop to false when the input was either "y" or "Y" or "n" or "N", otherwise the loop would continue.
Fourthly setting the loop to true inside the loop is unnecessary, it begins as true, and the only change you can make is to set it to false. And since each of the conditions are mutually exclusive i.e input being "y" or "Y" mutually exclusive to input being "n" or "N" or it being neither "y" or "Y" or "n" or "N". You don't need to worry about it being set to false unless you wanted the loop to end.
local function check()
io.write"Continue? (Y/N): "
local ans, num = {y = 1, n = 2}
repeat
num = ans[io.read():lower()] or 3
io.write(({"Ok!\n","Fine...\n","Invalid Answer! Try again (Y/N): "})[num])
until num < 3
return num
end
print (check())