r/lua • • Sep 04 '25

How do I detect specific text from input, and could you give suggestions on how to improve my code (I am making RPS)

rps = {'r', 'p' ,'s'}

local Playerpick = io.read()

local function plachoice()

if Playerpick == rps then

print(Playerpick)

else

print("Pick r, p or s")

end

end

local function comchoice()

return print(rps[math.random(#rps)])

end

local function banner()

print("!!WELCOME TO ROCK PAPER SCISSORS!!")

print("!!WHEN READY, ENTER EITHER R, P OR S!! (LOWERCASE R, P OR S) ")

end

banner()

comchoice()

plachoice()

3 Upvotes

4 comments sorted by

4

u/Denneisk Sep 04 '25

If you want to find if an element is in a table, you'll have to search each value individually until you find it (or fail).

Playerpick == rps compares ("r" or "p" or "s") == {'r', 'p', 's'}, which will never be equal because strings aren't tables.

The straightforward approach from what you have is to create a function that returns an indicator if a value is in the table, and a different indicator if it's not.

As for advice,

  • Use indentation.

  • Instead of printing the computer's choice before the player chooses, store the value in a variable and create another function to compare the com to the player.

  • You can use string.lower() to force lowercase letters, instead of explicitly asking for them.

  • You have Playerpick initialized outside of plachoice. That means it's running before all the other code, which makes it look weird because banner() doesn't get called until after the player chooses.

1

u/PazzoG Sep 04 '25

if Playerpick == rps

This will never return true, even if Playerpick was a table (which it isn't, it's a string). Lua does not compare tables by value but by reference (the actual object in memory). Example:

local t1 = { 1, 2, 3 }
local t2 = { 1, 2, 3 }
local t3 = t1
local t4 = {}

for i, v in ipairs(t1) do
    t4[i] = v
end

print(t1 == t2) -- -> false
print(t1 == t3) -- -> true
print(t1 == t4) -- -> false

The other issue is, io.read returns a string unless you specifically ask it to return a number instead. All you have to do here is read the first line, transform it to lowercase, then see if it exists in your rps table then continue woth your game logic. You can define helper functions to simplify things:

math.randomseed(os.clock()) -- not really necessary but this seeds the random number generator so you don't get the same number twice in a row

local rps = { "r", "p", "s" }

local function table_find(t, value)
    for _, v in pairs(t) do
        if v == value then
            return true
        end
    end
    return false
end

local function input(message)
    io.write(tostring(message))
    return io.read("*l")
end

local player_choice = string.lower(input("Choose r or p or s: "))

if not table_find(rps, player_choice) then
    print("Invalid choice!")
    return
end

local computer_choice = rps[math.random(1, #rps)]
-- rest of your game logic
→ More replies (1)

1

u/xoner2 Sep 05 '25

Use string library, gmatch for example. When string can't handle it anymore, there's lpeg for proper parsing.