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

Help with a typing program.

Started by Bossman201, 16 May 2012 - 11:58 PM
Bossman201 #1
Posted 17 May 2012 - 01:58 AM
Hello, I'm having some trouble with my code. I've declared a few functions or whatever and used them in a loop and the genius in me has gotten a bug in 5 lines of code. Anyway, I've looked through it a ton and can't find any reasonable errors. Then again, I've been like that since high school.

A little about me before I get on to posting the code. I'm 19, graduated from HS 2 years ago and started college but had to move so now I'm not in school and I haven't programmed in 3 years. Anyway now that you're all bored here's the code.

Spoiler

local cursorX = 1  --This is supposed to be a simple host/client chatroom program, so if it seems like it, it is.
local cursorY = 1  --I'll try to explain some of the parts
local hostID = 0
local clientID = 0
local username = tostring(hostID)
local cMessage = ""
local hMessage = ""
local letter = ""
local shift = false
function ClearScreen() --Nobody likes typing this s**t over and over again so I declared a function.
term.clear()
term.setCursorPos(1,1)
end
function AnyEvent()					 --The purpose of this program is to allow your program to keep running while accepting input. I don't
event, param1, param2 = os.pullEvent()  --like how io.read() halts your program and in a chatroom this command is
Decode()								--useless as you can't recieve new messages until you've pressed enter/return.
end
function Decode()  --This is how the program is supposed to decode os.pullEvent() events and prepare them for sending.
	if event == "key" and param1 == "42" and shift == false then shift = true  --Allows shift key functionality.
	elseif event == "key" and param1 == "42" and shift == true then shift = false
	end
if event == "char" and param1 == "1" and shift == false then letter = "1"  --Lots of code here but it's all exactly the same.
elseif event == "char" and param1 == "2" and shift == false then letter = "2"
elseif event == "char" and param1 == "3" and shift == false then letter = "3"
elseif event == "char" and param1 == "4" and shift == false then letter = "4"
elseif event == "char" and param1 == "5" and shift == false then letter = "5"
elseif event == "char" and param1 == "6" and shift == false then letter = "6"
elseif event == "char" and param1 == "7" and shift == false then letter = "7"
elseif event == "char" and param1 == "8" and shift == false then letter = "8"
elseif event == "char" and param1 == "9" and shift == false then letter = "9"
elseif event == "char" and param1 == "0" and shift == false then letter = "0"
elseif event == "char" and param1 == "1" and shift == true then letter = "!"  --Added a little part to test shift key, doesn't work.
elseif event == "char" and param1 == "2" and shift == true then letter = "@"
elseif event == "char" and param1 == "3" and shift == true then letter = "#"
elseif event == "char" and param1 == "4" and shift == true then letter = "$"
elseif event == "char" and param1 == "5" and shift == true then letter = "%"
elseif event == "char" and param1 == "6" and shift == true then letter = "^"
elseif event == "char" and param1 == "7" and shift == true then letter = "&"
elseif event == "char" and param1 == "8" and shift == true then letter = "*"
elseif event == "char" and param1 == "9" and shift == true then letter = "("
elseif event == "char" and param1 == "0" and shift == true then letter = ")"
elseif event == "char" and param1 == "a" and shift == false then letter = "a"
elseif event == "char" and param1 == "b" and shift == false then letter = "b"
elseif event == "char" and param1 == "c" and shift == false then letter = "c"
elseif event == "char" and param1 == "d" and shift == false then letter = "d"
elseif event == "char" and param1 == "e" and shift == false then letter = "e"
elseif event == "char" and param1 == "f" and shift == false then letter = "f"
elseif event == "char" and param1 == "g" and shift == false then letter = "g"
elseif event == "char" and param1 == "h" and shift == false then letter = "h"
elseif event == "char" and param1 == "i" and shift == false then letter = "i"
elseif event == "char" and param1 == "j" and shift == false then letter = "j"
elseif event == "char" and param1 == "k" and shift == false then letter = "k"
elseif event == "char" and param1 == "l" and shift == false then letter = "l"
elseif event == "char" and param1 == "m" and shift == false then letter = "m"
elseif event == "char" and param1 == "n" and shift == false then letter = "n"
elseif event == "char" and param1 == "o" and shift == false then letter = "o"
elseif event == "char" and param1 == "p" and shift == false then letter = "p"
elseif event == "char" and param1 == "q" and shift == false then letter = "q"
elseif event == "char" and param1 == "r" and shift == false then letter = "r"
elseif event == "char" and param1 == "s" and shift == false then letter = "s"
elseif event == "char" and param1 == "t" and shift == false then letter = "t"
elseif event == "char" and param1 == "u" and shift == false then letter = "u"
elseif event == "char" and param1 == "v" and shift == false then letter = "v"
elseif event == "char" and param1 == "w" and shift == false then letter = "w"
elseif event == "char" and param1 == "x" and shift == false then letter = "x"
elseif event == "char" and param1 == "y" and shift == false then letter = "y"
elseif event == "char" and param1 == "z" and shift == false then letter = "z"
elseif event == "key" and param1 == "1" then letter = "message received!"  --Little rednet testing.
																		   --(Early signs of a chat program)
end
end
ClearScreen()  --One line of code.
while true do  --Two lines of code.
term.write(letter)  --Three lines of code.
AnyEvent()  --Four lines of code.
end  --Five lines of code. (Yes it counts because without it your program will not work.)

I'll explain the error I'm having but putting the script on an in-game computer might help more. I guess my syntax is all okay since I can run the program, but when I try to give it input, the first time i press a button it's okay, it outputs normally, but when you hit another button it will print out again the last letter you typed and the new letter. I really just can't figure it out. Hopefully some fresh eyes will be able to help. Thanks in advance, guys.

EDIT: I think I messed up the commenting, sorry. I'll figure it out and fix it right away.
MysticT #2
Posted 17 May 2012 - 02:09 AM
First, some suggestions:
1) Don't use global variables, and definitely don't use them to pass vars between functions, that's what parameters and return are for.
2) The char event already returns the correct character when shift is pressed, so the Decode() function is kinda pointless.

The problem is that the variable letter stores the last input key, and you print it whenever there's an event, so you get a "key" event and then a "char" event, and you write the letter for both events (that's why it repeats the last one). It would also happen for every event you get (like "rednet_message", "redstone", etc.).
Try with the suggestions i gave you, that should help you solve the problem.
ComputerCraftFan11 #3
Posted 17 May 2012 - 02:16 AM
First, some suggestions:
1) Don't use global variables, and definitivly don't use them to pass vars between functions, that's what parameters and return are for.
2) The char event already returns the correct character when shift is pressed, so the Decode() function is kinda pointless.

The problem is that the variable letter stores the last input key, and you print it whenever there's an event, so you get a "key" event and then a "char" event, and you write the letter for both events (that's why it repeats the last one). It would also happen for every event you get (like "rednet_message", "redstone", etc.).
Try with the suggestions i gave you, that should help you solve the problem.

Another thing is the decode() function is broken since the event "key" doesn't return strings, it returns integers. So it would be:

function Decode()  --This is how the program is supposed to decode os.pullEvent() events and prepare them for sending.
		if event == "key" and param1 == 42 and shift == false then shift = true  --Allows shift key functionality.
		elseif event == "key" and param1 == 42 and shift == true then shift = false
		end
instead of


function Decode()  --This is how the program is supposed to decode os.pullEvent() events and prepare them for sending.
		if event == "key" and param1 == "42" and shift == false then shift = true  --Allows shift key functionality.
		elseif event == "key" and param1 == "42" and shift == true then shift = false
		end
BigSHinyToys #4
Posted 17 May 2012 - 02:27 AM
Simple bug keys are integers not strings.

		if event == "key" and param1 == "42" and shift == false then shift = true  --Allows shift key functionality.
		elseif event == "key" and param1 == "42" and shift == true then shift = false
-- Should be --
		if event == "key" and param1 == 42 and shift == false then shift = true  --Allows shift key functionality.
		elseif event == "key" and param1 == 42 and shift == true then shift = false

EDIT I got Ninja-ed :P/>/>
Bossman201 #5
Posted 17 May 2012 - 02:36 AM
So I'm guessing my global variables are event, param1, and param 2? I didn't really pay attention in that lecture haha so I don't know what global variables are and how to use them, so I try to stay away from them.

1. How can I get variable letter to only store either the key and number or the char and letter, and which one would be better? (I want to be able to use all the characters on a standard keyboard ex. | ] [ { } ' " ; : / ` ~ in addition to uppercase and lowercase letters and numbers and symbols.)

2. Okay I see what you mean about the key event not returning strings, so I need to keep myself from putting quotation marks around them.

3. When I declare a function, how do I declare and use the parameters? I know you need to put them in like this Decode(letter, compID) or whatever but not how to use them. (I may have slightly dozed off during this lecture as well.)

I'll add these things to the program and take out Decode() as soon as I figure out how to only grab the char event. Maybe os.pullEvent(char)?
ComputerCraftFan11 #6
Posted 17 May 2012 - 02:42 AM
So I'm guessing my global variables are event, param1, and param 2? I didn't really pay attention in that lecture haha so I don't know what global variables are and how to use them, so I try to stay away from them.

1. How can I get variable letter to only store either the key and number or the char and letter, and which one would be better? (I want to be able to use all the characters on a standard keyboard ex. | ] [ { } ' " ; : / ` ~ in addition to uppercase and lowercase letters and numbers and symbols.)

2. Okay I see what you mean about the key event not returning strings, so I need to keep myself from putting quotation marks around them.

3. When I declare a function, how do I declare and use the parameters? I know you need to put them in like this Decode(letter, compID) or whatever but not how to use them. (I may have slightly dozed off during this lecture as well.)

I'll add these things to the program and take out Decode() as soon as I figure out how to only grab the char event. Maybe os.pullEvent(char)?

For 3*
you would call Decode like this:
"Decode(3, 3)"
Then in decode(), it would print 33 if you type:

function decode(p1, p2)
print(p1..""..p2)
For the end*

its evt, letter = os.pullEvent("char")
MysticT #7
Posted 17 May 2012 - 02:49 PM
1) Well, I didn't see the local definition of the variables :P/>/>, but what i meant was that you could make the functions receive parameters and return values instead of having them change those vars. So you could have a function to get a letter like this:

local function getLetter()
  local evt, letter = os.pullEvent("char") -- get a "char" event
  return letter -- return the typed character
end
And then you use it like:

while true do
  local c = getLetter() -- get the letter and store it in a var
  write(c) -- write the letter
end
This would make the program write anything you type, but only characters, so you can't move the cursor, delete or press enter. You need a loop that checks for any type of event you want, like this:

while true do
  local evt, p1, p2 = os.pullEvent()
  if evt == "char" then
    writeChar(p1)
  elseif evt == "key" then
    handleKey(p1)
  elseif evt == "rednet_message" then
    messageReceived(p1, p2)
  end
end
And then you make the functions to handle them.

2) The "char" event gives a string containing the character typed, and if shift is pressed it handles that for you.

3) To use functions with parameters you do:

local function doSomething(p1, p2, p3) -- give a name to the received parameters
  print(p1) -- print the first parameter
  return p2 + p3 -- return the sum of the other parameters
end
And use it like:

local n = doSomething("Hello", 2, 4) -- give parameters "Hello", 2 and 4. Store the returned value in a variable
print(n)
It would print the first parameter ("Hello") and the print the returned value, wich is the sum of the second and third parameters (2 and 4, prints 6).
Bossman201 #8
Posted 18 May 2012 - 07:33 PM
Okay guys, two unfinished versions and three days later I finally have a functional program.

Spoiler


local cursorY = 17
local username = tostring(os.getComputerLabel)
local cMessage = ""
local hMessage = ""
local charNum = 1
local message = {}
local pastCount = 1
local pastMess = {}
local capOn = false
rednet.open("right")

for i = 1, 48 do
	message[i] = ""
end
for i = 1, 12 do
	pastMess[i] = ""
end

function clearScreen()
	term.clear()
	term.setCursorPos(1,1)
end

function resetMessage()
	for i = 1, 48 do
		message[i] = ""
	end
charNum = 1
end

function updatePast(newMess)
	for i = 1, 11 do
   pastMess[i] = pastMess[i + 1]
end
pastMess[12] = newMess
updateScreen()
end

function updateScreen()
for i = 4, 15 do
   term.setCursorPos(1, i)
term.clearLine()
end
for i = 4, 15 do
   term.setCursorPos(1, i)
term.write("|")
term.setCursorPos(50, i)
term.write("|")
end
	for i = 12, 1, -1 do
   term.setCursorPos(2, i + 3)
   term.write(pastMess[i])
end
end

function Border()
clearScreen()
	for i = 2, 49 do
		term.setCursorPos(i, 1)
		term.write("-")
term.setCursorPos(i, 3)
term.write("-")
		term.setCursorPos(i, 16)
		term.write("-")
term.setCursorPos(i, 18)
term.write("-")
	end
	for i = 1, 18 do
		term.setCursorPos(1, i)
		term.write("|")
		term.setCursorPos(50, i)
		term.write("|")
	end
	term.setCursorPos(2, 2)
	term.write("BossChat v.005")
end

function handleBackspace()
	if charNum + 1 >= 3 then
   charNum = charNum - 1
   message[charNum] = " "
   term.setCursorPos(charNum + 1, cursorY)
   term.write(" ")
   term.setCursorPos(charNum + 1, cursorY)
elseif charNum <= 1 then
charNum = 1
end
end

function handleSend(message)
for i = 1, charNum do
   hMessage = hMessage .. message[i]
end
term.setCursorPos(1, 17)
term.clearLine()
term.setCursorPos(1, 17)
term.write("|")
term.setCursorPos(50, 17)
term.write("|")
resetMessage()
if string.find(hMessage, "/") == 1 then
   handleCommand(hMessage)
elseif hMessage ~= "" then
   updatePast(hMessage)
   messageSend(hMessage)
end
return hMessage
end

function handleCaps(capOn)
	if capOn == false then
   term.setCursorPos(20, 2)
term.write("CAPS ON")
capOn = true
elseif capOn == true then
   term.setCursorPos(20, 2)
term.write("	   ")
capOn = false
end
end

function handleCommand(command)
	if command == "/exit" or command == "/Exit" or command == "/EXIT" then
   term.setCursorPos(2, 17)
   term.write("Thank you for using. Rebooting")
for i = 1, 5 do
   term.write(".")
sleep(0.30)
end
hMessage = ""
os.reboot()
end
end

function writeChar(char)
	term.setCursorPos(charNum + 1, cursorY)
	if charNum <= 48 then
		term.write(char)
message[charNum] = char
   charNum = charNum + 1
end
end

function handleKey(key)
	if key == 58 then
   handleCaps(capOn)
elseif key == 14 then
   handleBackspace()
elseif key == 28 then
		hMessage = handleSend(message)
hMessage = ""
end
end

function messageReceive(id, message)
	cMessage = message
updatePast(cMessage)
end

function messageSend(hMessage)
	rednet.broadcast(hMessage)
end

function handleEvent()
	evt, p1, p2 = os.pullEvent()
if evt == "char" then
   writeChar(p1)
	elseif evt == "key" then
   handleKey(p1)
elseif evt == "rednet_message" then
   messageReceive(p1, p2)
end
end

clearScreen()
Border()
term.setCursorPos(2, 17)

while true do
	handleEvent()
end

It's a host/client program so run the same program on two computers to use. I think I may stick with the project and add more features/stuff. Everybody say "inb4 'or you could just use minecraft chat'."!!!

EDIT: Question. What command do I use to copy/move a program into a disk, either using the lua program or in the programming environment? I've been wondering that for the past three days.

EDIT2: Simple typo in my code. typed "of" instead of "or" in the handleCommand() function.

EDIT3: Don't forget to edit the rednet.open() command if your modem is placed anywhere other than the right side or else it won't work. It's right under my variable declarations. Might add support to do this in the program later.
Edited on 18 May 2012 - 05:52 PM
MysticT #9
Posted 18 May 2012 - 07:40 PM
From a program you can use the fs api to manage files (copy, move, delete, open). To copy a file use: fs.copy("sourcePath", "destPath"). and move is the same but "move" instead of "copy".
Bossman201 #10
Posted 18 May 2012 - 09:34 PM
So how exactly would I move "myFile" to the disk using fs.copy()?
Luanub #11
Posted 18 May 2012 - 10:24 PM
If its on the computers root directory


fs.copy("myFile", "disk/myFile")
Bossman201 #12
Posted 18 May 2012 - 10:26 PM
So then if it's in another directory it would be


fs.copy("myFolder/myFile", "disk/myNewFolder/myFile")

right?
MysticT #13
Posted 18 May 2012 - 10:28 PM
Yes, but the directory must already exist on the disk (the "myNewFolder" folder).