robotica34, on 20 September 2013 - 12:46 AM, said:
One thing about parsing colors - how can I detect that the number value of the color is "pure" (let's say, 4 for magenta, but 3 is white and orange)? Is there a formula?
Yes there actually is, without going into too much detail as to why this very nice design choice was made, the colours are actually on a binary scale. This means that
Quote
white = 2^0
orange = 2^1
...
red = 2^14
black = 2^15
Knowing this, and knowing math, we can actually reverse a
2n number using
log2(n). Lua doesn't have an implementation however so we must make one like so
local function log2(num)
return math.log(num) / math.log(2)
end
Now what this will do is it will return us a number which we can the validate. Something like this would do the trick
local function validateColor(col)
col = log2(col)
if col < 0 or col > 15 then
return false --# it is out of bounds, white is 2^0 and black is 2^15
end
if col % 1 ~= 0 then
return false --# it is not a whole number, meaning its a combination of colours
end
return true
--# all the above can be compacted down to this
return col >= 0 and col <= 15 and (col % 1) == 0
end
Now the second if conditional may look confusing to you with the % operator, if it does open the spoiler and read, if not, just skip the spoiler
Now if you wanted to do something a little more true of how ComputerCraft deals with `impure` colors you can do the following
local function parseColor(col)
return 2 ^ math.floor(math.log(col) / math.log(2))
end
What we do there is break it down to the number from 0—15, we then round it down, so 5 is still 5, 5.1 is 5m but 5.9 is also 5 and then we return the binary of that number. So for example 3 would become 2. log
2(3) equals 1.58 rounded down equals 1, 2 ^ 1 equals 2.
The reason we do this
math.floor is because of the way they do it in the ComputerCraft code, without going into too much detail and explanation why Java works in this way, in the CC code they cast a double (iirc) into an integer, and the way that Java deals with double/float to int casting is to round the numbers down making the double 1.1 equal 1 when its an integer, or the double 1.9 also equal 1 when its an integer.
Now if you actually check the above method with how ComputerCraft actually does this you will notice that its the same, try the following
local function parseColor(col)
return 2 ^ math.floor(math.log(col)/math.log(2))
end
local c = colors.combine(colors.white, colors.orange)
term.setTextColor(c)
print("ComputerCraft's colour parsing")
term.setTextColor( parseColor(c) )
print("Our colour parsing, its the same color")
Hope this all makes sense and helps
— BIT