Jump to content


LBPHacker's Content

There have been 40 items by LBPHacker (Search limited from 10-February 22)


By content type

See this member's


Sort by                Order  

#256063 attempt to concatenate nil and string

Posted by LBPHacker on 13 July 2016 - 07:26 AM in Ask a Pro

The message is blaming line 13, not line 14. So, yeah, you'd better take a look at that line instead. Also, I'm pretty sure there are more words following unexpected symbol. Those are there to help you and, well, us, so if you're still having a hard time fixing it, it might be a good idea to post the full error message. If I had to guess, I'd say you typed something like
local result = {]



#256026 attempt to concatenate nil and string

Posted by LBPHacker on 12 July 2016 - 01:22 PM in Ask a Pro

Well, you didn't exactly tell us on which line the error occurs, but I'm going to assume it's line 36, where you try to concatenate cappedPower with constant strings. A couple of lines above you made the mistake of typing cappePower instead of cappedPower, thus leaving cappedPower undefined, or nil.

EDIT: Oh, forgot the second part. You could try this to insert commas:
local function insertCommas(number)
    local result = {}
    for chars in tostring(number):reverse():gmatch("..?.?") do
        table.insert(result, chars)
    end
    return table.concat(result, ","):reverse()
end



#255993 Lua identifier

Posted by LBPHacker on 11 July 2016 - 07:37 PM in Ask a Pro

Nope, the '-' section won't match anything. As I've stated above, '-' will match the least possible number of characters, which is, in this case, 0. The '-' is used in situations in which it's followed by other sections, such as
local command, arguments = command_line:match("^%s*(.-) (.*)%s*$")
This way only the first chunk of non-whitespace characters is stored in command and the rest in arguments, for '-' matches the least possible number of characters. Yes, it could match an empty string had the leading spaces not been already matched by %s*, thus leaving only non-spaces for (.-) to match.



#255988 Lua identifier

Posted by LBPHacker on 11 July 2016 - 06:46 PM in Ask a Pro

Come again? Gape? You mean gap? Nope, that's not how it works. [%w_]* comes after [%a_], so whatever [%w_]* matched must come after whatever [%a_] matched. [%w_]- will match the least possible characters, which since you already have an [%a_] in there will be an empty string.



#255981 Lua identifier

Posted by LBPHacker on 11 July 2016 - 05:19 PM in Ask a Pro

If the identifier starts at the first character of the string, then yeah, almost. I'd use
^[%a_][%w_]*
though, since underscore can lead the way too and you don't need more than 0 of the second class.



#255753 LUAC binary files and CC

Posted by LBPHacker on 08 July 2016 - 10:20 AM in Ask a Pro

It's not impossible, you can use string.dump to dump a function and loadstring the dump back into a function. On never versions of CC though, you only have load (which you would call with the dump and a string "b" as the third parameter) and you get a Lua-level error, something like "binary chunk loading is prohibited", but you can get around that with a modified bios.lua.

If you "compile" a Lua source with luac, it'll dump bytecode compatible with the Lua library it was built with. The last time I checked, the bytecode of the official implementation of the Lua library is incompatible with LuaJ's bytecode, so that might be why you get Java-level errors. I get a NullPointerException when I try to loadstring("\27Lua"), so it's not too well protected, you can easily get it to throw a Java-level error with invalid bytecode.



#255701 Checking how much memory is used

Posted by LBPHacker on 07 July 2016 - 09:55 AM in Ask a Pro

It really is the table (and other) structures, the size of which you cannot control or even query, that make it next to impossible, unless you have a VM with its own virtual memory (probably a huge string). Also, how would you dump it into a file?

View PostCrazyPyroEagle, on 07 July 2016 - 08:53 AM, said:

Check the wiki next time. If you're looking for another type of memory, you can't.
The OP might have checked the wiki and found nothing while searching for memory usage, which has nothing to do with the filesystem. Finding nothing on a wiki is among the things that make people ask questions.



#255497 for loop is only able to run once?

Posted by LBPHacker on 04 July 2016 - 06:38 PM in Ask a Pro

Oh, and yeah, code tags do that. Just don't copy the one I used for showing it; it's escaped.

[​code]print("you type stuff here")[/​code]

and you get

print("you type stuff here")

Unfortunately they cannot be used inline.



#255488 for loop is only able to run once?

Posted by LBPHacker on 04 July 2016 - 06:26 PM in Ask a Pro

Yeah, that's something I couldn't have noticed. I couldn't tell whether foundvalue was local to the function or not. I guessed it was but, apparently, it wasn't.

Nice catch, though. Solving it yourself, that is.



#255486 for loop is only able to run once?

Posted by LBPHacker on 04 July 2016 - 06:14 PM in Ask a Pro

It'd be best if you posted the full code. The code above doesn't seem to be prone to errors.

Also, use [​code][​/code] tags.
print("They make things more readabe.")



#255424 Calculating Bytes in a AE2 Storage Cell on CC

Posted by LBPHacker on 03 July 2016 - 08:56 PM in Ask a Pro

Hmm. Funny. LuaJ doesn't seem to like %f.

It seems to be LuaJ's fault

Well, in that case ...
local cell = 327680

local KILO = 1024
local units = {"B", "KiB", "MiB", "GiB", "TiB"}
local magnitude = math.floor(math.log(cell) / math.log(KILO))

local str = tostring(cell / KILO ^ magnitude):match("^(%d+%.?%d?%d?)%d*0*$") .. units[magnitude + 1]

print(str) -- or something



#255420 Implementing High Score?

Posted by LBPHacker on 03 July 2016 - 08:11 PM in Ask a Pro

If you want to keep the high scores only as long as the program runs, you could wrap the entire program in a loop and save the high score in a variable outside the loop. If you want high scores to persist, though, you're in for a tougher ride. You'll want to write the high score to a file and read it back on program startup. The FS API will help with that.



#255417 Calculating Bytes in a AE2 Storage Cell on CC

Posted by LBPHacker on 03 July 2016 - 08:00 PM in Ask a Pro

If that's the case, Google seems to use "business megabytes". Usually the K (kilo) prefix means "multiply this by 1000". Well, 1000 is not a power of 2, but 1024 is. So there are cases when a different prefix system is used, with the prefixes Ki (kibi), Mi (mebi), Gi (gibi), etc. This is the one I used in the code. 1 MiB = 1024 KiB = 1048576 B.

This is how you end up with 298 GB of space on a 320 GB external HDD. It's 320 business gigabytes, which translates to 298.02 gibibytes = something around 320000000000 bytes. Pretty awful, I know.



#255411 send a script through rednet to be executed on the other side

Posted by LBPHacker on 03 July 2016 - 07:16 PM in Ask a Pro

Oh, okay, you got stuck on the receiving side of things. Sure, there is a way. When a program is loaded from a file, the content of the file is passed to the standard Lua function load (or loadstring, depending on which version of Lua is used). load returns a function, which then can be called and thus the program can be run.

The second argument to both load and loadstring is the so called chunkname. This is what you see in an error message before the line number.

local program_string = ... -- receive the string through rednet, whatever

local program_function, load_error = load(program_string, "came-through-rednet") -- you could also send the chunkname over rednet

-- beware, program_function might be nil, which means that program_string wasn't a valid Lua source;
-- in that case load_error will hold the error message
program_function()

You could even send the arguments to the program over rednet. You'd have to pass them to program_function.



#255410 Calculating Bytes in a AE2 Storage Cell on CC

Posted by LBPHacker on 03 July 2016 - 07:06 PM in Ask a Pro

Well, I'm just going to add a :gsub call here. I couldn't think of any way to do it with just :format.

local cell = 327680

local KILO = 1024
local units = {"B", "KiB", "MiB", "GiB", "TiB"}
local magnitude = math.floor(math.log(cell) / math.log(KILO))

local str = ("%.2f"):format(cell / KILO ^ magnitude):gsub("%.?0+$", "") .. units[magnitude + 1]

print(str) -- or something



#255405 send a script through rednet to be executed on the other side

Posted by LBPHacker on 03 July 2016 - 05:37 PM in Ask a Pro

Well, you can send strings over rednet, and programs are stored in files which you can load into strings. Therefore you can send programs, eh?

Here's your todo list:
  • open a file (hint)
  • read its contents into a string
  • send the string over rednet (hint)



#255399 Calculating Bytes in a AE2 Storage Cell on CC

Posted by LBPHacker on 03 July 2016 - 04:07 PM in Ask a Pro

local cell = 327680

local KILO = 1024
local prefixes = {"", "Ki", "Mi", "Gi", "Ti"}
local magnitude = math.floor(math.log(cell) / math.log(KILO))

local str = ("%.2f %sB"):format(cell / KILO ^ magnitude, prefixes[magnitude + 1])

print(str) -- or something

The only interesting thing in there is the double-math.log trick, the "Change of base formula", explained here.



#255385 events lost in my coroutine manager

Posted by LBPHacker on 03 July 2016 - 11:29 AM in Ask a Pro

I'm just going to butt into this, sorry BB.

Schedulers (or planifiers, whatever) IRL are used to balance resources, such as keeping a process that requested, for example, a file from the disk frozen until said file can be read from memory, while giving CPU time to other processes that need no files or have already loaded whatever files they're operating with and are actually doing useful work. They might also decide which processes are to be given more CPU time than others, depending on their priority.

In CC there are not too many resources you can balance, and the event model and the environment make it even more difficult to find these things. You can't really balance CPU load, since Lua multitasking is cooperative, not preemptive, so coroutines themselves decide when to yield, not the scheduler. The only other thing that can get coroutines to yield in CC is a piece of code in Java throwing "too long without yielding" errors, but that's pretty much deus ex machina. You can't balance I/O load either since the filesystem functions are blocking as it is. You can't balance events because it makes no sense to do so. What else is there then?

The only use I can see for prioritized scheduling in CC is to ensure that some low level processes (such as a GUI framework driver) get the events before userspace applications do, thus eliminating any chance if the framework falling behind and returning old data when queried by the userspace applications. This could be implemented using a simple well-organized array, which you probably already have anyway in a coroutine manager. Or you could just have multiple arrays, grouping coroutines by priority and resuming the coroutines in the highest priority array first, etc. But this would still just pass an event to every coroutine as soon as possible.


TL;DR: It is possible, but probably not the way you imagined.



#255380 How to split a string at specified character

Posted by LBPHacker on 03 July 2016 - 10:36 AM in Ask a Pro

string.gmatch (or anyString:gmatch) return iterators (read them about here). This "advanced" for loop is just another variant that can be used to, well, iterate using these iterators. The page I linked explains it better.



#255378 How to split a string at specified character

Posted by LBPHacker on 03 July 2016 - 10:27 AM in Ask a Pro

There is a solution that involves a for loop checking every letter. It'd add a letter to a buffer if it wasn't a space, and would flush the buffer (would insert its content into a table and empty it) if it was a space. That's the more tedious one, and I won't be explaining that.

Here's one with string.gmatch (read about it here):
local words = {}
for word in str:gmatch("%S+") do
    table.insert(words, word)
end

The above code splits str into words not containing anything that matches the character class "%s" (remeber, not containing, hence the "%S" with the uppercase S), which would be space, newline, tabs and form feed, if I recall correctly. It also ignores empty matches, so splitting
"a  b" -- note the double space
would result in
{"a", "b"}
, not in
{"a", "", "b"}
.

You could use "[^ ]+" instead of "%S" to allow anything but space in the resulting words, or also anything else, for example "[^;]+" would split str along semicolons.

Since you're planning to parse command lines with this, I must add that this solution is a bit complicated to extend to allow commands with quotes or backslashes to escape spaces, such as
program arg1 arg2 "this is arg3"
program arg1 arg2 this\ is\ arg3



#255232 Help with elevator program

Posted by LBPHacker on 01 July 2016 - 08:03 AM in Ask a Pro

It stops at each floor because your program doesn't wait until the elevator gets to where it should be, it instead just waits for 3 seconds after asserting either the green or the red wire and after it, it goes back into the infinite loop.

I suggest two changes:
  • Make it all event driven: don't poll the input, wait for "redstone" events instead
  • Use tables: store the floors and relevant data in tables, iterate those tables when a redstone event occurs
This is the code I had in mind

Code works and is tested. It should give you an idea of how I think it should work.

How do the green and red wires work though? Does the elevator just move by itself when they are asserted? Is there a circuit generating the pulses needed by the frame motors? I assumed there is one, so the above code does too.



#255107 How to count people inside the sensor radius

Posted by LBPHacker on 29 June 2016 - 05:00 PM in Ask a Pro

I can't see how that'd be "working perfectly", as the variable name doesn't seem to be set when it's passed to .getTargetDetails on line 6.

In any case, you'd count the targets the same way you iterate them, except you'd increment a counter instead of checking their names.
local target_count = 0
for name, basicDetails in pairs(targets) do
	target_count = target_count + 1
end

Then you'd only let through anyone if target_count was 1.

There's also room for optimization in your code. You could just have a table at the top that'd hold all the players to whom access is to be granted, and the infinite loop should iterate over that table and check its entries against targets.



#255105 read() add string into read before writing

Posted by LBPHacker on 29 June 2016 - 04:51 PM in Ask a Pro

EDIT: Do check out the answer below this one first. It's way more crafty and simple.

Re-implementing read in a way that it accepts a 4th parameter which defaults to an empty string if not passed is an option. You'd probably end up with more code than sense, though. For example, the history code is completely useless here.

local function read( _sReplaceChar, _tHistory, _fnComplete, initial_sLine ) -- note the new parameter initial_sLine
	term.setCursorBlink( true )

	local sLine = initial_sLine or "" -- empty string used if initial_sLine is not passed (or it's nil/false)

	... -- the rest of read() as seen in bios.lua
end

read(nil, nil, nil, "initial text") -- you'd call it like this

Full code, in case you have never seen bios.lua before

EDIT: You can just call it with the last result it returned if you want it to remember the input.

local last
while ... -- some loop
	last = read(nil, nil, nil, last)
end



#244997 Triangle filling and UV coordinates

Posted by LBPHacker on 06 February 2016 - 07:34 PM in Ask a Pro

Search results for "filling triangles" (hint: first hit is exactly what you need)

Search results for "calculating barycentric coordinates" (hint: first hit is exactly what you need)



#242219 Chest Peripheral Error

Posted by LBPHacker on 02 January 2016 - 09:45 PM in Ask a Pro

Well, that means that password is nil. If the error is the same, that is. I'm guessing it's because your program checks for an item at startup and not when you put your tile.extrautils:chandelier in the chest.