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

Advanced Detection of Color (Works on all versions)

Started by TrinaryAtom, 15 December 2012 - 01:15 AM
TrinaryAtom #1
Posted 15 December 2012 - 02:15 AM
After a little digging, I have discovered a way to have ComputerCraft discover if it can use color or not. Now i know it already has one built in, but, i needed something that tested if it was also being ran on an older version of ComputerCraft. One that didn't have the Color API yet. And this is what i came up with. Runs perfectly on my program that I'm building.

It provides the ability to run the program on literally any computer, old or new, with or without color!

function advIsColor()
	local booColor = false -- Create variable local to only the function
	if term.isColor ~= nil then -- Test to see if term.isColor even exists within ComputerCraft
		booColor = term.isColor() -- If it is then set the booColor to either true or false
		if booColor == false then
			print("Colors Disabled") -- This will trigger if on a Stone Computer of the latest version
		else
			print("Colors Initialized.) -- This will trigger if on a Advanced Computer of the latest version
		end
	else
		print("Colors Disabled, Older Ver CC") -- This will trigger if on an older version of ComputerCraft
	end
	return booColor -- Function returns result to the program
end

-- Puts result into a variable
local verColor = advIsColor()

-- Repeat this, as needed, right before more text or terminal clears. Change the colors as well
if verColor == true then term.setTextColor(colors.black) term.setBackgroundColor(colors.lightBlue) end

-- The Programs Code
print("Are my Colors Different?")

Simple Version
local verColor = (term.isColor or false) and term.isColor()
if verColor == true then term.setTextColor(colors.black) term.setBackgroundColor(colors.lightBlue) end
print("Code/Text of Program")

Just thought I would share this discovery with the rest of the world. :)/>/>

Edit: Corrected an Error.
Edit: Added Simple Version.
theoriginalbit #2
Posted 15 December 2012 - 02:43 AM
Good job :)/> EDIT: I never thought of doing multi-os compatibility in this way.

FYI: This technique uses what is called function pointers, they are very neat. I discovered them once with the following code
Spoiler

currX, currY, currZ = 0, 0, 0
-- lots of stuff moving turtle around
function goToY(y)
  dirFunc
  if (y > currY) then
	 dirFunc = turtle.down
  elseif (y < currY) then
	 dirFunc = turtle.up
  else
	 return
  end
  while (currY ~= y) do
	 dirFunc()
  end
end
TrinaryAtom #3
Posted 15 December 2012 - 02:50 AM
Good job :)/> EDIT: I never thought of doing multi-os compatibility in this way.

FYI: This technique uses what is called function pointers, they are very neat. I discovered them once with the following code
Spoiler

currX, currY, currZ = 0, 0, 0
-- lots of stuff moving turtle around
function goToY(y)
  dirFunc
  if (y > currY) then
	 dirFunc = turtle.down
  elseif (y < currY) then
	 dirFunc = turtle.up
  else
	 return
  end
  while (currY ~= y) do
	 dirFunc()
  end
end
Thanks :)/>
and
Woah.. umm… i cant seem to follow what you did there. As soon as i think i get it, it totally looses me. >< But I think i understand what you were trying to show me.
theoriginalbit #4
Posted 15 December 2012 - 03:13 AM
Good job :)/> EDIT: I never thought of doing multi-os compatibility in this way.

FYI: This technique uses what is called function pointers, they are very neat. I discovered them once with the following code
Spoiler

currX, currY, currZ = 0, 0, 0
-- lots of stuff moving turtle around
function goToY(y)
  dirFunc
  if (y > currY) then
	 dirFunc = turtle.down
  elseif (y < currY) then
	 dirFunc = turtle.up
  else
	 return
  end
  while (currY ~= y) do
	 dirFunc()
  end
end
Thanks :)/>
and
Woah.. umm… i cant seem to follow what you did there. As soon as i think i get it, it totally looses me. >< But I think i understand what you were trying to show me.

If you wish to read my attempt at explaining how function pointers work and what I did in that example read the spoiler below :)/>
SpoilerBasically what it does is this.

A function can be seen as a set of instructions in memory. A pointer 'points' ( :o/> WHAT?! :P/> ) to this location in memory. If you were to use print(turtle.up) it would print some hexadecimal number if that function exists, nil if it doesn't. So by doing
dirFunc = turtle.up
we are actually assigning the pointer to the turtle.up function to our variable dirFunc. Then when it comes to wanting to execute this function thats where you add ( ) (in lua, other languages are different ) to the end of the variable. This tells the compiler/runtime env (depending on the language) that you want to call the function that it points to.

So what my little code snippet did was it moved the turtle back to its origin y position. If the turtle was above the origin it would move it down, if it was below the origin it would move it up.

However using function pointers in the example I gave is kinda pointless. The code below is obviously a little smaller, and easier for most to understand, but function pointers can be used for some interesting purposes, case and point, your multi-os programs.

Alt method of doing the same thing:
Spoiler

function goToY(y)
  while (currY ~= y) do
    if (y > currY) then
      turtle.down()
    elseif (y < currY) then
      turtle.up()
    end
  end
end
TrinaryAtom #5
Posted 15 December 2012 - 03:20 AM
If you wish to read my attempt at explaining how function pointers work and what I did in that example read the spoiler below :)/>
SpoilerBasically what it does is this.

A function can be seen as a set of instructions in memory. A pointer 'points' ( :o/> WHAT?! :P/> ) to this location in memory. If you were to use print(turtle.up) it would print some hexadecimal number if that function exists, nil if it doesn't. So by doing
dirFunc = turtle.up
we are actually assigning the pointer to the turtle.up function to our variable dirFunc. Then when it comes to wanting to execute this function thats where you add ( ) (in lua, other languages are different ) to the end of the variable. This tells the compiler/runtime env (depending on the language) that you want to call the function that it points to.

So what my little code snippet did was it moved the turtle back to its origin y position. If the turtle was above the origin it would move it down, if it was below the origin it would move it up.

However using function pointers in the example I gave is kinda pointless. The code below is obviously a little smaller, and easier for most to understand, but function pointers can be used for some interesting purposes, case and point, your multi-os programs.

Alt method of doing the same thing:
Spoiler

function goToY(y)
  while (currY ~= y) do
	if (y > currY) then
	  turtle.down()
	elseif (y < currY) then
	  turtle.up()
	end
  end
end
Excellent Read. I completely understand. Thanks :D/>
theoriginalbit #6
Posted 15 December 2012 - 03:23 AM
If you wish to read my attempt at explaining how function pointers work and what I did in that example read the spoiler below :)/>
SpoilerBasically what it does is this.

A function can be seen as a set of instructions in memory. A pointer 'points' ( :o/> WHAT?! :P/> ) to this location in memory. If you were to use print(turtle.up) it would print some hexadecimal number if that function exists, nil if it doesn't. So by doing
dirFunc = turtle.up
we are actually assigning the pointer to the turtle.up function to our variable dirFunc. Then when it comes to wanting to execute this function thats where you add ( ) (in lua, other languages are different ) to the end of the variable. This tells the compiler/runtime env (depending on the language) that you want to call the function that it points to.

So what my little code snippet did was it moved the turtle back to its origin y position. If the turtle was above the origin it would move it down, if it was below the origin it would move it up.

However using function pointers in the example I gave is kinda pointless. The code below is obviously a little smaller, and easier for most to understand, but function pointers can be used for some interesting purposes, case and point, your multi-os programs.

Alt method of doing the same thing:
Spoiler

function goToY(y)
  while (currY ~= y) do
	if (y > currY) then
	  turtle.down()
	elseif (y < currY) then
	  turtle.up()
	end
  end
end
Excellent Read. I completely understand. Thanks :D/>

Cool. Sometimes its hard to put it into words easy enough for people to understand.

You should rep me up ;)/>
Tiin57 #7
Posted 15 December 2012 - 05:09 AM
TheOriginalBIT said:
You should rep me up ;)/>/>
Asking for rep is bad manners and will in the long run earn you less.
theoriginalbit #8
Posted 15 December 2012 - 05:26 AM
TheOriginalBIT said:
You should rep me up ;)/>/>
Asking for rep is bad manners and will in the long run earn you less.

Very well……..

For the record. how do u actually do it? I was trying to do it for someone yesterday and couldn't find out how.
TrinaryAtom #9
Posted 15 December 2012 - 01:28 PM
I see a green arrow on there post. ( bottom right corner)
theoriginalbit #10
Posted 15 December 2012 - 01:43 PM
I see a green arrow on there post. ( bottom right corner)

Weird, didn't work when I tried it
immibis #11
Posted 15 December 2012 - 01:49 PM

function advIsColor()
    return term.isColor and term.isColor()
end
theoriginalbit #12
Posted 15 December 2012 - 01:55 PM

function advIsColor()
	return term.isColor and term.isColor()
end

Doesn't exactly print like his does ;)/> :P/>
immibis #13
Posted 15 December 2012 - 01:57 PM

function advIsColor()
	return term.isColor and term.isColor()
end

Doesn't exactly print like his does ;)/> :P/>
Why would you want it to print?
KillaVanilla #14
Posted 15 December 2012 - 02:14 PM

function advIsColor()
	return term.isColor and term.isColor()
end
I always assumed that that snippit would crash on older systems with an "attempt to call nil" error, but I realized that Lua would find that term.isColor would equal nil and immediately return false.

In any case, this "program" (it's more of a snippet, actually) is just an overly fancy and complex way to avoid errors while calling functions, so I'm not going to use it myself.

Also, I'm back from my hiatus, so…Hello again?
theoriginalbit #15
Posted 15 December 2012 - 02:20 PM

function advIsColor()
	return term.isColor and term.isColor()
end
I always assumed that that snippit would crash on older systems with an "attempt to call nil" error, but I realized that Lua would find that term.isColor would equal nil and immediately return false.

In any case, this "program" (it's more of a snippet, actually) is just an overly fancy and complex way to avoid errors while calling functions, so I'm not going to use it myself.

Also, I'm back from my hiatus, so…Hello again?

yes it doesn't actually return an "attempt to call nil" error as it first checks the function pointer, which would either be nil, or a pointer. if its nil it returns nil, if its not nil it would continue


function advIsColor()
	return term.isColor and term.isColor()
end

Doesn't exactly print like his does ;)/> :P/>
Why would you want it to print?

idk. but he had his print :P/>
immibis #16
Posted 15 December 2012 - 02:28 PM

function advIsColor()
	return term.isColor and term.isColor()
end
I always assumed that that snippit would crash on older systems with an "attempt to call nil" error, but I realized that Lua would find that term.isColor would equal nil and immediately return false.
It returns nil, actually.
KillaVanilla #17
Posted 15 December 2012 - 03:03 PM
-snip-

It returns nil, actually.

…Odd. I wonder why; I assumed that it would return false because it was part of an AND statement.
theoriginalbit #18
Posted 15 December 2012 - 03:41 PM
-snip-

It returns nil, actually.

…Odd. I wonder why; I assumed that it would return false because it was part of an AND statement.

i believe that 'and' actually works as a ternary operator :)/>
TrinaryAtom #19
Posted 15 December 2012 - 04:05 PM
Wow… i don't know weather to be hurt or puzzled. All i was doing was show casing a discovery i made that took me a while to figure out.
Also, if your going to post a "snippet" of code please place some text explaning it. I'm still relativly new to this and am still learning most of it. So when one person posts code and says nothing then the other person could quite easily take it as an insult. (Sorta like your showing me up for being stupid).

Also that "snippet" of code i submitted was purely for show. It was designed to show the person exactly how it works, as its working. The printing obviously isn't meant for any real programs. Du!

So with all that said, this is me "showing you up" with no explination.
local verColor = (term.isColor and term.isColor())
if verColor == true then term.setTextColor(colors.black) term.setBackgroundColor(colors.lightBlue) end
print("Code/Text of Program")
Added to OP

i believe that 'and' actually works as a ternary operator :)/>/>/>
I'm still learning here, but, i thought "and" could only be used with things like "if".
(To clarify, i have no idea what ternary operator is and this is more of a question.)
immibis #20
Posted 15 December 2012 - 09:00 PM
So with all that said, this is me "showing you up" with no explination.
local verColor = (term.isColor and term.isColor())
if verColor == true then term.setTextColor(colors.black) term.setBackgroundColor(colors.lightBlue) end
print("Code/Text of Program")
I'm not sure how that's "showing me up," whatever that means, because it's just my code inlined (taken out of a function and inserted directly, in place of the function call)

I'm still learning here, but, i thought "and" could only be used with things like "if".
(To clarify, i have no idea what ternary operator is and this is more of a question.)

Okay, this is how it works.
In Lua, everything that is not false or nil is considered true.
Note that nil is not equal to false, even though they act the same way in an if statement.

What "X and Y" actually does is it returns X, if X is false or nil. Otherwise, it returns Y.
If X is false or nil, it does not attempt to evaluate Y, so nothing will happen if Y would have raised an error.
So

return term.isColor and term.isColor()
can be rewritten as:

if term.isColor == false or term.isColor == nil then -- this line is equivalent to "if not term.isColor then"
   return term.isColor
else
   return term.isColor()
end

The default value of variables and table fields in Lua is nil, so on CC versions without colours, term.isColor is nil, and the function returns nil.
This is mostly equivalent to returning false, unless you test for false specifically, eg:

function advIsColor()
   return term.isColor and term.isColor()
end

-- This won't work if term.isColor doesn't exist, since advIsColor will return nil, which is not equal to false.
if advIsColor() == false then print("Not colour") end

-- All of these will work
if advIsColor() ~= true then print("Not colour") end
if advIsColor() then print("Colour") end
if not advIsColor() then print("Not colour") end



Your version returns false if term.isColor doesn't exist, and mine returns nil. If you wanted to modify mine to return only true or false, either of these work:

function advIsColor()
  return (term.isColor or false) and term.isColor()
end
function advIsColor()
  return (term.isColor and term.isColor()) or false
end
These work because "or" does the opposite of "and".
In "X or Y", X is returned if it is not nil or false, otherwise Y is returned.

The first one is equivalent to:

function advIsColor()
  local temp
  -- the "or" part. I save the result in temp to save repeating this part twice.
  if term.isColor ~= false and term.isColor ~= nil then -- again, this can be abbreviated as just "if term.isColor then"
	temp = term.isColor
  else
	temp = false
  end

  -- Now temp is either false, or term.isColor

  -- the "and" part
  if temp == false or temp == nil then
	-- Temp can't be nil, because it was either false or term.isColor, so it must be false
	return temp
  else
	return term.isColor()
  end
end





Edit: The "ternary operator" is something that Lua doesn't have, but it's found in other languages like Java and C. In these languages, instead of writing, for example:

if X then
  return Y
else
  return Z
end
you can write:

return (X ? Y : Z)
as a shortcut.
"(X and Y) or Z" does the same thing in Lua as long as Y is not nil or false.
TrinaryAtom #21
Posted 15 December 2012 - 10:43 PM
I'm not sure how that's "showing me up," whatever that means, because it's just my code inlined (taken out of a function and inserted directly, in place of the function call)
I guess i might have jumped off the deep end there. I guess i took it too far. I apologize for said action. I do appreciate you presenting all of this delicious info. couple questions tho.

function advIsColor()
  return (term.isColor or false) and term.isColor()
end
I had a thought, why put this in a function (i know i did). I wonder if functions are more designed for multiple uses. I guess my question is, would it be better to place this bit of code directly into a variable?

function advIsColor()
  local temp
  -- the "or" part. I save the result in temp to save repeating this part twice.
  if term.isColor ~= false and term.isColor ~= nil then -- again, this can be abbreviated as just "if term.isColor then"
		temp = term.isColor
  else
		temp = false
  end

  -- Now temp is either false, or term.isColor

  -- the "and" part
  if temp == false or temp == nil then
		-- Temp can't be nil, because it was either false or term.isColor, so it must be false
		return temp
  else
		return term.isColor()
  end
end
You mentioned here that it would be either false or term.isColor. If what i'm thinking is correct then that is actually false or (true or false) correct?

Also, I had no idea that lua stopped at the first "and" if it doesn't work. That's good to know, i'll be rewriting bits and parts of my projects to take advantage of that.

Edit: This shorter version is awesome. But, if i were to write in entire program as short as possible i think i would fail most of the time. For me, it seems so much easier to view it in the way i wrote.
Edit 2: I wonder, is this an appropriate way to do things? Or is there a better method.
local verColor = (term.isColor or false) and term.isColor()

function animUI(varColor, varb, varb)
   if varColor == true then term.setBackgroundColor(color.green) end
   Code
   Code
   Text
   Code
end

function random(varColor)
  Code
  Code
end

animUI(verColor, blah, blah)
random(verColor)
Edit 3: let's put a spin on it, what if I was loading all of the functions from an external file?