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

(Kind of) Slotmachine help?

Started by Exofile, 28 December 2013 - 07:54 PM
Exofile #1
Posted 28 December 2013 - 08:54 PM
Ok, so i've just gotten back into ComputerCraft, and i wanted(with help of a friend), to make a little slot machine.
Ive got some of the program written, but ive hit a bit of a wall. You see, i wanted to make the randomizer in a function, so i could use it several times, and save on the writing. Heres what i got so far, but i get a error when i try to set the background in the function. What have i done wrong?
local m = peripheral.wrap("top")
m.setBackgroundColor(colors.black)
m.clear()
m.setTextScale(1)
m.setCursorPos(1,1)
m.setTextColor(colors.magenta)
m.write("SLOTS")

function ColorDefine()
  number = {math.random(1, 4), "nil"}
  if number[1] == 1 then
	number[2] = "colors.blue"
  elseif number[1] == 2 then
	number[2] = "colors.red"
  elseif number[1] == 3 then
	number[2] = "colors.yellow"
  elseif number[1] == 4 then
	number[2] = "colors.green"
  end

end

function slot1(x1,y1,x2,y2,color)
  x1,y1,x2,y2 = 1,2,2,2
  for i = x1,x2 do
	for o = y1,y2 do
	m.setCursorPos(i,o)
	m.setBackgroundColor(number[2])
	m.write(" ")
	end
  end
end

if number[1] == 1 then
  slot1(x1,y1,x2,y2,number[2])
  print("test")		
elseif number[1] == 2 then
  slot1(x1,y1,x2,y2,number[2])
elseif number[1] == 3 then
  slot1(x1,y1,x2,y2,number[2])
elseif number[1] == 4 then
  slot1(x1,y1,x2,y2,number[2])
end
OReezy #2
Posted 29 December 2013 - 12:20 AM
colors.red is referring to a table. When you put
m.setBackgroundColor(number[2])
you are supplying a string instead of the table variable. To fix this change your ColorDefine function variables to
number[2] = "blue"
and the background code to
m.setBackgroundColor(colors[number[2]])
Imprivate #3
Posted 29 December 2013 - 06:41 AM
I ran your program with OReezy's fix and got error at line 34: attempt to index ? (a nil value).

Fix: "pastebin get nmb0Kxiv" (or remove 'end' at line 21 and put it at the very end of your code).

Hope this fixes it :)/>
Edited on 29 December 2013 - 08:41 AM
OReezy #4
Posted 29 December 2013 - 01:40 PM
The reason you got that error is because his table is local to the ColorDefine function, meaning the other function can't access it. It was late so i didn't really read through his whole program but to fix that he needs to have ColorDefine return a variable the other function can use or store the table outside the ColorDefine function.

What is the purpose of the number table? Since you are using a chain of elseif statements, why do you not just do something like this?

if number == 1 then
  local color = blue
  return color
elseif number == 2
  local color = red
  return color
end
Imprivate #5
Posted 29 December 2013 - 08:02 PM
Yea, using a bunch of elseif's is more straight forward and probably less lines of code
Exofile #6
Posted 30 December 2013 - 10:33 AM
Thanks! Thanks to you guys, i sort of re-wrote the script, with precautions about what you said. So now its all in one functions ;-)


local side = nil
for r,s in pairs(rs.getSides()) do
  if peripheral.getType(s) == 'monitor' then
    side = s
    break
  end
end

m = peripheral.wrap(side)
m.setBackgroundColor(1)
m.clear()
m.setTextScale(1)
m.setCursorPos(2, 1)
m.setTextColor(2)
m.write("SLOTS")
m.setCursorPos(1, 2)
local Slot = 0

function Slotter(xmin, xmax, ymin, ymax)
  local number = math.random(1, 3)
  local color = 0
  Slot = number
  if number == 1 then
    color = 16384
  elseif number == 2 then
    color = 2048
  elseif number == 3 then
    color = 16
  end
  for i = xmin, xmax do
    for o = ymin, ymax do
	  m.setCursorPos(i,o)
	  m.setBackgroundColor(color)
	  m.write(" ")
    end
  end
end

Slotter(2, 2, 2, 2)
print(Slot)
Slotter1 = Slot
Slotter(4, 4, 2, 2)
print(Slot)
Slotter2 = Slot
Slotter(6, 6, 2, 2)
print(Slot)
Slotter3 = Slot

if Slotter1 == Slotter2 and Slotter2 == Slotter3 then
  print("Jackpot!")
end
Imprivate #7
Posted 30 December 2013 - 12:04 PM
Awesome program (got Jackpot first try ^^). Can I just make one suggestion? It's annoying having to exit the computers GUI to see the colors on the monitor, why dont you use os.pullEvent("monitor_touch") to let the user right click the monitor to run the program? I tried this myself and it works unbelievably well. Here is the code:

local side = nil
for r,s in pairs(rs.getSides()) do
  if peripheral.getType(s) == 'monitor' then
	side = s
	break
  end
end
m = peripheral.wrap(side)
m.setBackgroundColor(1)
m.clear()
m.setTextScale(1)
m.setCursorPos(2, 1)
m.setTextColor(2)
m.write("SLOTS")
m.setCursorPos(1, 2)
local Slot = 0
function Slotter(xmin, xmax, ymin, ymax)
  local number = math.random(1, 3)
  local color = 0
  Slot = number
  if number == 1 then
	color = 16384
  elseif number == 2 then
	color = 2048
  elseif number == 3 then
	color = 16
  end
  for i = xmin, xmax do
	for o = ymin, ymax do
		  m.setCursorPos(i,o)
		  m.setBackgroundColor(color)
		  m.write(" ")
	end
  end
end
repeat
event, side, xPos, yPos = os.pullEvent("monitor_touch")
term.redirect(m)
Slotter(2, 2, 2, 2)
print(Slot)
Slotter1 = Slot
Slotter(4, 4, 2, 2)
print(Slot)
Slotter2 = Slot
Slotter(6, 6, 2, 2)
print(Slot)
Slotter3 = Slot
if Slotter1 == Slotter2 and Slotter2 == Slotter3 then
  print("Jackpot!")
end
term.restore()
until nil

I hate to dominate your program, but if you want me to add something I'd love to (I love working with monitors), such as a score that counts your jackpots, etc. Once again nice program :)/>
Edited on 30 December 2013 - 11:28 AM
Exofile #8
Posted 30 December 2013 - 12:34 PM
Actually right after i wrote my comment, i made some tweaks to it, so you currently click on the screen to spin it ;-) Only problem i have is that if you click outside the "button" ("#SPIN") it goes out of my While loop, how can i fix this?


local side = nil
for r,s in pairs(rs.getSides()) do
  if peripheral.getType(s) == 'monitor' then
    side = s
    break
  end
end

m = peripheral.wrap(side)
m.setBackgroundColor(32768)
m.clear()
m.setTextScale(1)
m.setCursorPos(2, 1)
m.setTextColor(2)
m.write("SLOTS")
m.setCursorPos(1, 2)
local Slot = 0

function Slotter(xmin, xmax, ymin, ymax)
  local number = math.random(1, 3)
  local color = 0
  Slot = number
  if number == 1 then
    color = 16384
  elseif number == 2 then
    color = 2048
  elseif number == 3 then
    color = 16
  end
  for i = xmin, xmax do
    for o = ymin, ymax do
	  m.setCursorPos(i,o)
	  m.setBackgroundColor(color)
	  m.write(" ")
    end
  end
end

local loop = true

while loop == true do
  loop = false
  Slotter(2, 2, 2, 2)
  print(Slot)
  Slotter1 = Slot
  Slotter(4, 4, 2, 2)
  print(Slot)
  Slotter2 = Slot
  Slotter(6, 6, 2, 2)
  print(Slot)
  Slotter3 = Slot
  if Slotter1 == Slotter2 and Slotter2 == Slotter3 then
    print("Jackpot!")
  end
  m.setCursorPos(2,4)
  m.setBackgroundColor(32768)
  m.setTextColor(2)
  m.write("#SPIN")
  event, button, x, y = os.pullEvent("monitor_touch")
  print(x,y)
  if x > 1 and x < 7 and y > 3 and y < 5 then
    print("SPIN")
    loop = true
  else
    print("NOT SPIN")
  end
end
CometWolf #9
Posted 30 December 2013 - 02:06 PM
All you need to do is move your code around a little, and always leave the loop running. This way, it will wait for user input with the pullEvent, then depending on the input perfrom the desired action, then loop around to wait for another input.

while true do
  m.setCursorPos(2,4)
  m.setBackgroundColor(32768)
  m.setTextColor(2)
  m.write("#SPIN")
  event, button, x, y = os.pullEvent("monitor_touch")
  print(x,y)
  if x > 1 and x < 7 and y > 3 and y < 5 then
    print("SPIN")
    Slotter(2, 2, 2, 2)
    print(Slot)
    Slotter1 = Slot
    Slotter(4, 4, 2, 2)
    print(Slot)
    Slotter2 = Slot
    Slotter(6, 6, 2, 2)
    print(Slot)
    Slotter3 = Slot
    if Slotter1 == Slotter2 and Slotter2 == Slotter3 then
      print("Jackpot!")
    end
  else
    print("NOT SPIN")
  end
end
You might also want to throw in some term.clear along with a term.setCursorPos(1,1) at the respective prints to keep only one message displayed at a time.
Imprivate #10
Posted 30 December 2013 - 02:09 PM
Simple as adding

  else
	print("NOT SPIN")
	loop = true
  end
end

Is that good or did you want it to cancel the event, so it only works if they click on the #SPIN 'button'?

EDIT: Just saw CometWolf's comment (^) and that way works aswell, infact it is probably simpler and better practice doing it his way :)/>
Edited on 30 December 2013 - 01:14 PM
Exofile #11
Posted 30 December 2013 - 02:19 PM
That worked! Thanks! ;-) Note that i also moved all my Slotter function callings, into the pullevent section, under the "Print("SPIN") LOOP = TRUE…Any more suggestions you now have for the program? Note, that i dont want to clear the terminal, its actually not supposed to be accessible for users of the slotmachine, so i use it to see if everything still works, probably gone soon ;-)

Current program

Edited - I've noticed that whenever i unload/load chunks, its a bit buggy? Is that just a server im playing on, or? It works, but i have to go into terminal everytime its to Spin?
Edited on 30 December 2013 - 01:43 PM
CometWolf #12
Posted 30 December 2013 - 02:50 PM
a few things could be done to make it a bit more compact and clean


local side = nil
for r,s in pairs(rs.getSides()) do
  if peripheral.getType(s) == 'monitor' then
	side = s
	break
  end
end

m = peripheral.wrap(side)

This can be changed to this


for r,s in pairs(rs.getSides()) do
  if peripheral.getType(s) == 'monitor' then
	m = peripheral.wrap(s)
	break
  end
end
No reason to do the wrapping outside the for loop.


This is more of a bad practice thing, but when you use a variable from a function outside a function, you should return it from the function instead of declaring it globally within the function.

function Slotter(xmin, xmax, ymin, ymax)
  local number = math.random(1, 3)
  local color = 0
  Slot = number
  if number == 1 then
	color = 16384
  elseif number == 2 then
	color = 2048
  elseif number == 3 then
	color = 16
  end
  for i = xmin, xmax do
	for o = ymin, ymax do
	  m.setCursorPos(i,o)
	  m.setBackgroundColor(color)
	  m.write(" ")
	end
  end
end

could instead be


function Slotter(xmin, xmax, ymin, ymax)
  local number = math.random(1, 3)
  local color = 0
  if number == 1 then
	color = 16384
  elseif number == 2 then
	color = 2048
  elseif number == 3 then
	color = 16
  end
  for i = xmin, xmax do
	for o = ymin, ymax do
	  m.setCursorPos(i,o)
	  m.setBackgroundColor(color)
	  m.write(" ")
	end
  end
  return number
end

Then when you call it, you simply assign the return value to slotter like so



	print("SPIN")
	Slotter3 = Slotter(2, 2, 2, 2)
	print(Slotter3)

	Slotter2 = Slotter(4, 4, 2, 2)
	print(Slotter2)

	Slotter1 = Slotter(6, 6, 2, 2)
	print(Slotter1)

While we're at it, declaring anything with a capital first letter is not something you should do in LUA. The name for it right now escapes me, but the usual practice is to name things like so: variableName
functionName()

also, we could do this last bit with a for loop


print("SPIN")
for i=2,6,2 -- this loop will loop once where i = 2, then it will increase i by 2 and loop again, and keep doing this until i == 6
	Slotter..(i/2) = Slotter(i, i, 2, 2)
	print(Slotter..(i/2)
end

Edited - I've noticed that whenever i unload/load chunks, its a bit buggy? Is that just a server im playing on, or? It works, but i have to go into terminal everytime its to Spin?
I assume you mean you have to start the program over again? Whenever a computer is unloaded and reloaded it will restart. This means any program running will stop. only way around this is to name your program "startup" and place it in the root directory. The computer will run the startup file whenever it's rebooted.
Edited on 30 December 2013 - 01:50 PM
Imprivate #13
Posted 30 December 2013 - 02:50 PM
I suggest creating a 'Wins' counter that shows how many times you have got the jackpot out of how many roles. Infact, I've already made it :)/>:


local side = nil
for r,s in pairs(rs.getSides()) do
  if peripheral.getType(s) == 'monitor' then
    side = s
    break
  end
end

m = peripheral.wrap(side)
m.setBackgroundColor(32768)
m.clear()
m.setTextScale(1)
m.setCursorPos(2, 1)
m.setTextColor(2)
m.write("SLOTS")
m.setCursorPos(1, 2)
local Slot = 0
local wins = 0
local rolls = 0

function Slotter(xmin, xmax, ymin, ymax)
  local number = math.random(1, 3)
  local color = 0
  Slot = number
  if number == 1 then
    color = 16384
  elseif number == 2 then
    color = 2048
  elseif number == 3 then
    color = 16
  end
  for i = xmin, xmax do
    for o = ymin, ymax do
      m.setCursorPos(i,o)
      m.setBackgroundColor(color)
      m.write(" ")
    end
  end
end

local loop = true

while loop == true do
  loop = false
  m.setCursorPos(2,4)
  m.setBackgroundColor(32768)
  m.setTextColor(2)
  m.write("#SPIN")
  m.setCursorPos(1, 6)
  m.write("Roll/Win Ratio: ")
  event, button, x, y = os.pullEvent("monitor_touch")
  print(x,y)
  if x > 1 and x < 7 and y > 3 and y < 5 then
    rolls = rolls+1
    print("SPIN")
    Slotter(2, 2, 2, 2)
    print(Slot)
    Slotter3 = Slot

    Slotter(4, 4, 2, 2)
    print(Slot)
    Slotter2 = Slot

    Slotter(6, 6, 2, 2)
    print(Slot)
    Slotter1 = Slot

    if Slotter1 == Slotter2 and Slotter1 == Slotter3 then
      print("Jackpot!")
      wins = wins+1
    end
    m.setCursorPos(1, 7)
    m.setTextColor(colors.white)
    m.write(wins.."/"..rolls)
    loop = true

  else
    print("NOT SPIN")
    loop = true
  end
end

I don't know how big of a monitor your using, i'm using a 4x3 monitor and this displays fine (although the format is pretty ugly :P/>)
Exofile #14
Posted 30 December 2013 - 03:11 PM
Im planning later to make a casino on the server. So it will all be connected to a hive data. You login, and it tells how many spins you have left etc. Then you can also cash in etc. ;-) Also, i wanna just use a 1 wide and 1 tall computer, so i then can hide it using microblocks, as i use Ftb ;-) This helps with making it compact. Ik its alot to ask, but how do i then make a login on each slotmachine, which saves data, and it then access whenever it wants, from one hive computer?
Imprivate #15
Posted 30 December 2013 - 03:24 PM
So what you need is a central 'server' that stores all the players login details. What I would suggest is using Rednet and when you register it sends the data to the server, then when the try and login it checks it against the servers information. Wouldn't be TOO hard to do on a small scale, might take awhile though.
Wobbo #16
Posted 30 December 2013 - 03:28 PM
You could also use wired modems on each computer and connect them all to a disk drive. Then you could create one file per user that each slot machine can acces. This file could simply be a serialised table with the amount of spins left and all the other data you would like to store.
CometWolf #17
Posted 30 December 2013 - 03:41 PM
could do some cool things with a setup like that depending on what peripherals you have acess to. The player detector would be a nice and simple login solution, as it gives the computer the name of the player clicking on it. Set one up by each slot machine connected to it's respective computer. Then this computer will have to communicate with the main server computer. On the main computer you could simply store the player data in a file with their name. so the code would be very simple

while true do
  local id, message = rednet.receive()  -- receive rednet communications
  local command,user, param = message:gmatch"a%+" -- splits the received string into seperate values, seperate them with a space
  local file = fs.open("/".."user","r") -- opens user file
  if command ==  "read" then
	local wins = file.readLine() --reads first line, where you can store the wins value
	local cashMoneyDerps = file.readLine() -- second line, where you can store money or whatever
	rednet.send(id,wins.." "..cashMoneyDerps) --puts the info into one string and sends it back over rednet
  elseif command == "update" then
	--same stuff except you change the file
  end
end
you get the general idea, not that complex
Edited on 30 December 2013 - 02:42 PM
Exofile #18
Posted 30 December 2013 - 04:13 PM
Ok thanks for all these suggestions, ill be sure to add some, and tweak a bit ;-) And CometWolf, no offence, but i prefer to only use things i know of, in the system. So i know whats going on xD Need to look into this Rednet here ! Personally, i found the idea of the Disk pretty smart, although i have no idea how to generate files, in a program. Also ImPrivate, about yuor win/roll, i think that that information also would be sent to a "hive", soi got one storing all information ;-) This program would mostly be to gather information etc
CometWolf #19
Posted 30 December 2013 - 04:28 PM
Not really sure what you're reffering to so i'll consider both possibilities

The player detector is quite simple, it just fires an event with the username that clicked on it, similar to how the monitor touch event works.
as for the code i posted, im not saying you should use that, it's an example. Hence it not being done.

generating files is simple with the fs API, check it out on the Wiki
Edited on 30 December 2013 - 03:28 PM