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

Connect three problems

Started by Z23Adster, 20 November 2015 - 12:31 AM
Z23Adster #1
Posted 20 November 2015 - 01:31 AM
Alright, so I'd like to preface this by mentioning I'm just getting my feet wet in lua. Alright, so the problems I am having with this program are not errors sent back by the computer but rather things that are not happening as they should. I've isolated where the problems are, I simply do not know how to remedy them. So the problem is my program is supposed to have a user go to a specified spot and the computer should not be able to go the spot the user selected. Additionally, the program should not be selecting two spots to go to. So, basically in the repeat loop I'm trying to exclude values that have already been selected in a spot and the print("this is top bottom….) was to try and find if that's where the problem was(which it was). So, the point of that variable is to give a 50 percent chance of a spot on the bottom row being selected and a spot on the second row being selected. I hope I explained this thoroughly enough for a solution :D/>. I'm also going to pastebin the entire program in case that is necessary. http://pastebin.com/h101pGHr
Oh yes, and one additional side note. If I say string.find(command, "10") then and I've already said if string.find(command, "1") then it will output a redstone signal for both of those since it is seeing the 1 digit in both of those. I am aware of the issue, but is there a good way to fix this? Finally if there's a more efficient way to do the things I'm doing in my program if you look at the pastebin, please mention it!(I love to learn new and efficient ways to do things!) Thanks in advance for the help and solutions!



KingofGamesYami #2
Posted 20 November 2015 - 02:14 AM
For finding the number inside the chat, I'd use string.match.


local num = tonumber( command:match( "%d+" ) )

The patter %d+ simply asks the match command to find one or more digits (0-9). % tells the pattern the next character will be special, d tells the pattern to look for digits, and + tells the pattern to look for 1 or more matches.

Of course, num could be nil - if a player said something without a number in it. Therefor I would use a repeat loop:


local num
repeat
  local player, event, command = os.pullEvent("chat")
  num = tonumber( command:match( "%d+" ) )
until num

Hope this helps :)/>/>

Part II!

I would recommend a table for storing moves. Specifically, I would store the previous moves like this:


local tMovesMade = {}

local function makeRandomMove()
  local move --#pre-define move as local
  repeat
    move = math.random( 1, 5 ) --#generate a random move
  until not tMovesMade[ move ] --#if the move isn't in the table, loop will stop
  tMovesMade[ move ] = true --#add the move to the table
  return move --#returns the number we ended up with
end
Edited on 20 November 2015 - 01:19 AM
Z23Adster #3
Posted 20 November 2015 - 02:34 AM
Alright so now I'm getting this error and I don't really understand it, haha. Also, is there something wrong with my code below "if topBottom == 2 then" that is causing it to print out twice?
Bomb Bloke #4
Posted 20 November 2015 - 02:35 AM
A function definition would be worthwhile here:

Spoiler
local function doCommand(val)
	if val == 1 then
		redstone.setOutput("back", true)
	elseif val == 2 then
		redstone.setOutput("top", true)
	elseif val == 3 then
		redstone.setOutput("left",true)
	elseif val == 4 then
		redstone.setOutput("bottom", true)
	elseif val == 5 then
		rednet.send(52, "redstone5", "redstone5")
	elseif val == 6 then
		rednet.send(51, "redstone6", "redstone6")
	elseif val == 7 then
		rednet.send(53, "redstone7", "redstone7")
	elseif val == 8 then
		rednet.send(55, "redstone", "redstone8")
	elseif val == 9 then
		rednet.send(54, "redstone", "redstone9")
	elseif val == 10 then
		rednet.send(56, "redstone", "redstone10")
	elseif val == 11 then
		rednet.send(61, "redstone", "redstone11")
	end
end

Say you stuck this at the top of your script. You'd then be able to replace your current lines 5-19 with "doCommand(a)", and lines 87-119 with "doCommand(aa)".

Lines 27-59 are a bit different, because (as mentioned above) "command" is a string, and the function expects a number. So in regards to converting it, we might replace line 22 with this bit of logic:

local commandNum
repeat
	local player, event, command = os.pullEvent("chat")
	commandNum = tonumber(command)  -- tonumber() returns a number if the message represented something valid, or nil if not.
until commandNum and commandNum > 0 and commandNum < 12  -- Loop stops once commandNum is non-nil, and within our desired number range.

Lines 27-59 can then be replaced with just "doCommand(commandNum)".

So the problem is my program is supposed to have a user go to a specified spot and the computer should not be able to go the spot the user selected. So, basically in the repeat loop I'm trying to exclude values that have already been selected in a spot and the print("this is top bottom….) was to try and find if that's where the problem was(which it was). So, the point of that variable is to give a 50 percent chance of a spot on the bottom row being selected and a spot on the second row being selected.

Presumably at some point you're going to be extending things so that both the player and the computer can take more than one turn. In which case a table would be the way to go: When the script starts, define an empty one:

local grid = {}

Then whenever a move is made, set the matching index to true:

grid[a / aa / whatever] = true

You can then perform checks to see which values have been set:

repeat
  -- Ask user for move / figure out move for computer here.
until not grid[move]

Using this technique, it's important that all moves are represented as the same variable type, as grid[1] and grid["1"] won't refer to the same table index. Converting "command" using tonumber() (as demonstrated above) solves that problem.
Z23Adster #5
Posted 20 November 2015 - 03:44 AM
Alright everything is fixed, just need to add the arrays. However, I am still having this problem:


I am pretty sure it's happening at the very end of the code but I still can't figure it out :/
Here is the revised code:
http://pastebin.com/QTq0Lrbe
And I appreciate this help, I would never figured this out, haha.
Bomb Bloke #6
Posted 20 November 2015 - 05:51 AM
Well, down the bottom we've got this:

chat.say("Alright, my turn again.")

if topBottom == 1 then
	repeat
		aa = math.random(1,5)
		print(aa)
	until aa~= a and aa ~= command
	
	sleep(2)
	chat.say("I will go to spot "..aa)  -- This is the first message.
end

if topBottom == 2 then
	-- Do nothing, apparently.
end

if commandNum == a +5 then
	aa = commandNum +5
	sleep(2)
	chat.say("I will go to spot "..aa)  -- And either this'll be the second,
elseif commandNum ~= a+5 then
	aa = a+5
	sleep(2)
	chat.say("I will go to spot "..aa)  -- ... or this will.
end

I guess you were going for this:

chat.say("Alright, my turn again.")

if topBottom == 1 then
	repeat
		aa = math.random(1,5)
		print(aa)
	until aa~= a and aa ~= command
	
	sleep(2)
	chat.say("I will go to spot "..aa)
elseif topBottom == 2 then
	if commandNum == a +5 then
		aa = commandNum +5
		sleep(2)
		chat.say("I will go to spot "..aa)
	elseif commandNum ~= a+5 then
		aa = a+5
		sleep(2)
		chat.say("I will go to spot "..aa)
	end
end
Z23Adster #7
Posted 11 December 2015 - 11:52 PM
Alright so several weeks later I've been taking a bit of a break but more problems surprise, surprise. I'm having troubles with arrays and trying to determine when a player wins, take a look:

http://pastebin.com/9b8rVxZa

So, basically I make an array with all the possible winning combinations and the a table with all the turns(so far). As I'm sure you can see, I have no idea what I'm doing. What I'm trying to do though is check if the turns taken thus far are a win. Now you might wonder why I'm checking both the computer's turns and the player's turns for a win. I'm just doing that for now because otherwise it would almost never be a win since I only have several turns in for the pc and the player so far. I'm pretty new to arrays and what not, so thanks in advance for the help, you guys are always great :D/>! Also, I'm not getting errors when I run the program, it just doesn't check for wins at all and kind of skips it I guess.
Edited on 12 December 2015 - 12:09 AM
Bomb Bloke #8
Posted 12 December 2015 - 11:57 AM
You have a "seewin()" function, but you never appear to be calling it.

You've also got this line:

if  win == turns[1] and turns[2] and turns[3] and turns[4] and turns[5] then

… which translates to:

if the win table is the same as turns[1], and turns[2] is a value, and turns[3] is a value, and etc...

The content of the turns table is:

turns = {a,ab, aa, commandNum, commandNumTwo }

What're a, ab, aa, commandNum, and commandNumTwo supposed to be? I see you reference variables by those names later in the script, but that won't magically change the values you assigned into the turns table!

Also note that two different tables will never compare as the same, even if their contents are the same. The reason is that when you assign a table to a variable, the variable actually ends up holding a pointer that leads to the table - like a shortcut, or alias. When you compare that pointer to another table pointer, what's being checked is whether they point to the same table in memory. If you want to compare the contents, you have to specifically go through and check the contents. Each one of them.

Truth be told, you're better off refactoring this. The idea is to write the code for the computer's turn once, and the code for the player's turn once. Have a think about how you might build a function that can handle taking the player's turn no matter what moves have already been made, for example.

Of course, I won't begrudge you if you stick with your current design - you're presumably more interested in writing the code for learning purposes than you are in its efficiency. I just feel it's worth pointing out that a little bit of "hard" work thinking up a complex system tends to be easier than a great deal of "easy" work making a simple one.
Z23Adster #9
Posted 12 December 2015 - 09:23 PM
Hey, so I think I found a clever way to go about this. I just wanted to get your take on it. So, I'll give you a rundown of what I did. Basically I took a look at all the win combinations and tried adding up each combination. For example 22, 23, 24 is 69. 2,8,14 is 24. 3,7,11 is 21. You get the point. So I did this for all 47 and noticed that all of them are divisible by three. Which, in turn means I can add up three turns a player has took at a time and take the mod of that number. If it is 0 then it is win because it must be a combination if it is divisible by three. If it's not 0 then there is no win. I'll do the same thing for the computer as well. Take a look and give me some suggestions please! Also, this is off topic but if anyone knows a good book for learning lua, please recommend one :D/>
Here's the revised code:

http://pastebin.com/ZM4NkrMJ
KingofGamesYami #10
Posted 12 December 2015 - 09:28 PM
What if I placed at 1, 6, and 8? That wouldn't be a win, but adds up to 15, which is a multiple of three.

As for a book, Programming in Lua is a decent resource. I didn't use it to learn lua, but I do refer to it often.
Edited on 12 December 2015 - 08:29 PM
Z23Adster #11
Posted 12 December 2015 - 09:36 PM
That's true, I can exclude exceptions though in the function I suppose. Also, thanks for the link I'll take a look at it.
Edited on 12 December 2015 - 08:37 PM
KingofGamesYami #12
Posted 12 December 2015 - 10:11 PM
I'm not sure if it helps or not, as your system of storing moves is different than mine, but I made a game* which had to check things along the six "lines". The function checkMove is what I'm referring to.
Z23Adster #13
Posted 12 December 2015 - 11:01 PM
It might help but I don't really understand your code, haha. My comprehension of foreign code is pretty basic. :/ I'm trying to find a way to exclude right now because if I excluded individual combinations it would take forever. There's probably hundreds of possible combinations that meet the criteria of %0 but aren't actually a win.