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

Computer automatically find disc drives, modems ect.

Started by Awsomehawk, 17 January 2013 - 02:09 PM
Awsomehawk #1
Posted 17 January 2013 - 03:09 PM
Hi everyone was wondering if someone can explain how to program a computer to automatically find disc drives and modems. My friend how a code he gave to me but it was quite messy and understandable. So can someone give me and example of code and explain it. It would be most helpful and thank you.
theoriginalbit #2
Posted 17 January 2013 - 03:16 PM
Code like the following will work… it searches all the sides and sees if one matches for what your looking for then returns the side its on…

local function findPeripheral( kind )
  for _, v in pairs( rs.getSides() ) do
	if peripheral.isPresent( v ) and peripheral.getType( v ) == kind then
	  return v
	end
  end
  return nil
end

Usage:

local modemSide = findPeripheral( "modem" )
local driveSide = findPeripheral( "drive" )

if not modemSide then
  print( "No modem found" )
end
if not driveSide then
  print( "No disk drive found" )
end

The main lines here are:
  1. for _, v in pairs( rs.getSides() ) do — This uses the redstone api to get all the sides of the computer, then goes through them one by one, storing each one into the variable v
  2. peripheral.isPresent( v ) — This checks to see if a peripheral is there on a given side
  3. peripheral.getType( v ) — This gets the peripheral type as a string, there are heaps of types but vanilla CC is here http://computercraft...ipheral.getType
  4. return v — This returns the side the peripheral is on if it has found one
Edited on 17 January 2013 - 02:20 PM
ChunLing #3
Posted 17 January 2013 - 06:37 PM
Here's a kinda theoretical question. Since rs.getSides() returns a sequential table (even without being called iteratively using pairs/ipairs), and the fastest way to search sequential tables is with an iterative for loop, wouldn't it be better to do:
local function findPeripheral( kind )
    local tsides = rs.getSides()
    for i=1,#tsides do
        if peripheral.isPresent(tsides[i]) and peripheral.getType(tsides[i]) == kind then
            return tsides[i]
        end
    end
    return nil
end
Granted that for a table this size we are talking about an almost infinitesimal savings in time, if we are saving any at all. Probably the bigger savings is that I can explain this code without having to explain iterative functions, which is enough of a pain that I usually don't.
theoriginalbit #4
Posted 17 January 2013 - 06:48 PM
For something this small either, either really… Only reason I typed it really was because thats what I've been using a lot of lately and thats what I automatically typed…
ChunLing #5
Posted 17 January 2013 - 07:00 PM
Well, I don't want to seem like I hate iterative functions or using the generic for (though I use the numeric for a lot more often for basic stuff). And certainly the code itself is slightly more compact using pairs().
theoriginalbit #6
Posted 17 January 2013 - 07:05 PM
Yeh generic for ( for-each / iterative for / enhanced for … or what ever you want to call it ) are defs an integral part of programming sometimes… Sometimes things become easier with them… I want to say that also using table[ index ] is a little more inefficient because of how it accesses vs the iterative method, but I'm not sure of Lua's impl so I can't really be sure if it is…
ChunLing #7
Posted 17 January 2013 - 07:25 PM
It's more efficient to index a table directly using the index than using pairs(). But it requires knowing the index, so it can only be done successfully for sequential tables, whereas pairs works for non-sequential tables (which I also love).
Lyqyd #8
Posted 18 January 2013 - 04:42 AM
I prefer pairs/ipairs when dealing with this sort of thing, especially rs.getSides(). It means not having to store the table someplace else, and you get the current key and value of the table in local variables. I would be interested in seeing benchmarking results for numeric/pairs/ipairs loops with a few sizes of tables and a differing number of table indexes per iteration. I have a suspicion that the more times you index your table per iteration, the better pairs/ipairs looping becomes, since it only needs to index the table once per iteration, and then you use the local variable it returns.
theoriginalbit #9
Posted 18 January 2013 - 09:56 AM
I have a suspicion that the more times you index your table per iteration, the better pairs/ipairs looping becomes, since it only needs to index the table once per iteration, and then you use the local variable it returns.
That's what I'd say too, because each time you access the table that's another lookup, meaning more time.
GopherAtl #10
Posted 18 January 2013 - 10:02 AM
ipairs is deprecated, gone in future (actually, latest) lua, precicely because it's less efficient than just doing i=1,#list. So I never use iPairs myself.

And you can easily index once by grabbing the variable the first time, ex:

for i=1,#items do
  local item=items[i]
  ...
end
it adds one line, granted, but a trivial one, and more efficient than ipairs.
theoriginalbit #11
Posted 18 January 2013 - 10:04 AM
ipairs is deprecated, gone in future (actually, latest) lua, precicely because it's less efficient than just doing i=1,#list. So I never use iPairs myself.

And you can easily index once by grabbing the variable the first time, ex:

for i=1,#items do
  local item=items[i]
  ...
end
it adds one line, granted, but a trivial one, and more efficient than ipairs.
Yeh I never really saw any point to ipairs… So I never used it…
GopherAtl #12
Posted 18 January 2013 - 10:06 AM
… lol. iPairs. Damn you, Apple!
ChunLing #13
Posted 18 January 2013 - 11:39 AM
My sentiments exactly.

As for table indexing, it makes essentially zero difference between accessing a table (one scope up) by index and accessing a local scoped variable. But there is a non-zero (though still very small) cost to access the table and save that in the local scoped variable.

Also, any iterative function suitable for use in a generic for is inherently costlier (in processing cycles, anyway) than sequential table lookups…it's just that they can do a lot of things that you really can't do with a sequential table. Lua would be a far poorer language if it were restricted to sequential tables, certainly many of my favorite solutions depend on having non-sequential tables and being able to access any table in a non-sequential manner.

But for basic solutions where you can use a sequential table access, it's a lot simpler to stay with that.
GopherAtl #14
Posted 18 January 2013 - 12:40 PM
We've gotten on a tangent here, but I have to note that I'm surprised I never see anyone (but myself) implement custom iterator functions. turtlex has a couple, for iterating forwards or backwards over the slots containing items of a specified type, and I'm thinking of adding more for iterating over all types themselves. Efficiency wins when it's easy, or when performance demands it, otherwise it's convenience all the way.
ChunLing #15
Posted 18 January 2013 - 01:15 PM
I've never really needed them, myself. I doubt that many people do write custom iterators. Generally, by the time I've resolved the requirements of a particular task to the point that I could put it into an iterator, it's already essentially functional code as is.
GopherAtl #16
Posted 18 January 2013 - 01:37 PM
well, turtlex uses the typeSlot iterators internally in several functions, so I made iterators out of them to avoid repeating the same code. I suppose I could maintain the list of slots containing each type, but that's more overhead on common actions (updating the inventory table) to optimize a couple of relatively rare actions. The reverse form was added for drop, which in turtlex can be given a type of thing to drop as well as a quantity, and the quantity can be more than a stack, causing it to iterate over multiple slots containing the specified type. Doing this from last slot backwards helps keep samples in the early slots, which helps keep stacking orderly when digging with the first slot selected instead of starting new stacks in an empty slot before it gets to later slot containing a partial stack of the same type.
NeverCast #17
Posted 18 January 2013 - 02:16 PM
I've written an iterator in the past, but only because I'd recently learnt about them. To be honest sometimes when you're in the middle of a whole lot of code, using some maybe less efficient loop is easier than scrolling up and writing out an iterator.

Only people that would use them are those that use them frequently and preemptively see they can use one, or those that plan their code.. and come on, who the hell plans code these days? Think of an idea, and let the fingers do the typing.
GopherAtl #18
Posted 18 January 2013 - 03:15 PM
oh, iterator functions are almost never (possibly just plain never?) going to be more efficient than doing the code in-place, except in terms of work efficiency, i.e., an iterator can be reused in many places.

The biolerplate loop my iterator replaces was doing:

for slot=1,16 do
  if inventory[slot].type==type then
    <do some code>
  end
end
and doing that in multiple places, so now it's just

for slot in typeSlots(type) do
  <some code here>
end
which is cleaner, but not actually faster.