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

getting 2 variables from a single user input?

Started by fusiomax, 26 September 2012 - 07:01 PM
fusiomax #1
Posted 26 September 2012 - 09:01 PM
Hi guys, so I started Direwolf20's ComputerCraft tutorials yesterday evening and I decided to install it on my server for me and my mate to mess with.

My mate asked me to make a simple turtle interface program so that he could move a turtle around and dig and do really basic commands (he wanted something to be able to dig obsidian as he's lazy) so I made this:
Spoiler

local version = 1.1
function forward()
	turtle.forward()
end
function backward()
	turtle.backward()
end
function left()
	turtle.turnLeft()
	turtle.forward()
	turtle.turnRight()
end
function right()
	turtle.turnRight()
	turtle.forward()
	turtle.turnLeft()
end
function up()
	turtle.up()
end
function down()
	turtle.down()
end
function turnRight()
	turtle.turnRight()
end
function turnLeft()
	turtle.turnLeft()
end
function dig()
	turtle.dig()
end
function digDown()
	turtle.digDown()
end
function digUp()
	turtle.digUp()
end
function fuelLevel()
	print("Fuel Level: "..turtle.getFuelLevel())
end
function refuel()
	turtle.refuel()
end
function exitTurtleUI()
	term.clear()
	term.setCursorPos(1,1)
	print("THANK YOU FOR USING T.U.I 1.0")
	os.reboot()
end
function tuiHelp()
	term.clear()
	term.setCursorPos(1,1)
	print("Available Commands:")
	print("forward, back")
	print("left, right")
	print("up, down")
	print("tright, tleft")
	print("dig, digup, digdown")
	print("fuel, refuel")
	print("exit, help")
	print()
	print("Press enter to continue...")
	read()
end
  
local run = 0
term.clear()
term.setCursorPos(1,1)
term.write("WELCOME TO T.U.I "..version)
sleep(2)
while run ~= 1 do
	term.clear()
	term.setCursorPos(1,1)
	term.write("Please enter Turtle do: ")
	command = read()
	if command == "forward" then
		forward()
	elseif command == "backward" then
		backward()
	elseif command == "left" then
		left()
	elseif command == "right" then
		right()
	elseif command == "up" then
		up()
	elseif command == "down" then
		down()
	elseif command == "tright" then
		turnRight()
	elseif command == "tleft" then
		turnLeft()
	elseif command == "dig" then
		dig()
	elseif command == "digup" then
		digUp()
	elseif command == "digdown" then
		digDown()
	elseif command == "fuel" then
		fuelLevel()
	elseif command == "refuel" then
		refuel()
	elseif command == "exit" then
		exitTurtleUI()
	elseif command == "help" then
		tuiHelp()
	else
		print("INVALID COMMAND")
		os.sleep(1)
	end
end

Now I'm pretty sure that is no where the best way to do it, but it works… except, I want to be able to type "forward 20" and have the turtle move forward 20 blocks, now I know how to loop it 20 times (well kinda, but I'm sure I can figure it out) but how can I take that input of "forward 20" and put it into 2 variables so I can execute forward, 20 times?

Sorry for the kinda drawn out question, thanks in advance for any help you can give me :P/>/>.
Doyle3694 #2
Posted 26 September 2012 - 09:21 PM
Working on it atm :P/>/>
GopherAtl #3
Posted 26 September 2012 - 09:23 PM
lua patterns can do this sort of thing. They're a little tricky - I keep meaning to write a whole tutorial on them one of these days - but for now I'll just show you how to use 'em here.

string.match() takes a string to search in and another string with the pattern to try to match.


input=read()
command,dist= string.match(input,"(%a+)%s*(%d*)")
if command~=nil then
  --match is all-or-nothing, so if first result is nil, the match failed, otherwise, it succeeded
  --dist was optonal, if it wasnt specified set to 1
  if dist=="" then
	dist=1
  else --if it WAS specified, convert from a string to number
	dist=tonumber(dist)
  end

  if command=="forward" then
	for i=1,dist do
	  forward()
	end
  elseif
	--..etc, cases for each command like you had originally, but using the dist parameter now as well
  end
else
  print("I don't understand that command.")
end

Some explanation of that pattern, so this isn't quite so "magic"

The match patterns use symbol sets, starting with %, to say what kind of characters to match. %a matches letters (alphabet), %d matches digits (0-9), %s matches whitespace (space or tab). By thesmevles, these mean "match one of these." They can be followed by another symbol to change that, for example, %a? matches 0 or 1 letter, %a+ matches one or more, and %a* matches zero or more.

Lastly, the ()s indicate the bits that will be returned; each set of () will return whatever matches the pattern inside as a result. Anything not inside ()s is matched, but not returned.

So, take the pattern above again, "(%a+)%s*(%d*)"
The first ()s contain "%a+", which matches one or more letters. If it matches, that'll be returned first, and caught in "command."
That's followed by %s*, which matches zero or more whitespace.
Last is %d*, also in ()s. This will match zero or more numbers. Because of the ()s, whatever matches %d* will be returned as the 2nd result, and caught in "dist." If it matches 0 characters, it will return an empty string "" rather than nil.

On the last two, we use * instead of +, allowing zero, so that the second number is optional, since some commands won't need it, so it won't make sense to require it always.

So, this would match anything with a word, some space, and a number, i.e. "forward 10", "back 2", or just any single word, "tleft", "back", etc. If the number is not specified, the "if dist=="" then dist=1" bit defaults dist to 1, so you can still type just "forward" to go forward one block.

Confusing at first, but once you get used to it, very powerful. :P/>/>
Cranium #4
Posted 26 September 2012 - 09:31 PM
Simpler answer:

for i = 1,10 do
--"i" is the iterator
--1 is the start point, 10 is the end point
print("Hello world") --simple print command
end --ends loop
--this will run starting from 1, ending at 10, printing each line
Slightly more complex:

local function forward(distance) --add a parameter to the function
  for i = 1, distance do --we are starting at 1, ending at the number distance
    turtle.forward() --our forward command
  end
end
print("How far do you want to move?")
write("Distance: ")
local input = tonumber(read())
--we are defining input by asking to "read" what the user types
--then converting it to a "number" that our next function can recognize
forward(input)
--calling back to our previously created function,
--plugging in the new parameter "input"
I have added notes on the relevant lines so I hope you can understand how the code works.
GopherAtl #5
Posted 26 September 2012 - 09:39 PM
simpler, yes… but answered the wrong question. He was asking to take 2 parameters in one read statement… :P/>/>
Cranium #6
Posted 26 September 2012 - 09:43 PM
Haha, derp. Way too tired to answer questions…..
Just read you post, and learned a bit more on string patterns.
fusiomax #7
Posted 26 September 2012 - 10:30 PM

input=read()
command,dist= string.match(input,"(%a+)%s*(%d*)")
if command~=nil then
  --match is all-or-nothing, so if first result is nil, the match failed, otherwise, it succeeded
  --dist was optonal, if it wasnt specified set to 1
  if dist=="" then
	dist=1
  else --if it WAS specified, convert from a string to number
	dist=tonumber(dist)
  end

  if command=="forward" then
	for i=1,tonumber(dist) do
	  forward()
	end
  elseif
	--..etc, cases for each command like you had originally, but using the dist parameter now as well
  end
else
  print("I don't understand that command.")
end

You explained that very well it would take me a bit of time to learn to apply this properly but I completely understand your explanation and am sure that with a bit of effort I could use this :P/>/> but I must ask, in the if statement handling the dist variable you set dist = tonumber(dist), but then in the for loop that handles the forward command you use tonumber(dist) again, Is there something I'm missing or is this redundant?
GopherAtl #8
Posted 26 September 2012 - 10:49 PM
oops, no, you're not missing anything, I did. Originally had the tonumber in the loop, then added it earlier and forgot to fix that one. Was writing that from work, so it was untested, just got home and tested and seems to work as intended :P/>/>

Glad you found the explanation helpful! There's more to patterns than just that, so I really will have to write a whole patterns tutorial sometime.
fusiomax #9
Posted 26 September 2012 - 10:54 PM

Glad you found the explanation helpful! There's more to patterns than just that, so I really will have to write a whole patterns tutorial sometime.

I can say I would be very interested in that, thanks for all your help, I should be good from here (on this subject at least :P/>/> )