ID:1785631
 
(See the best response by DarkCampainger.)
Code: http://pastebin.com/iqcLAFW5
/obj/conduit/power
icon = 'icons/obj/conduits/power.dmi'
name = "power conduit"
desc = "A cheap, efficient power conduit for transferring electricity across the station"
anchored = 1
gender = NEUTER
var/insulated = 0 // It gets a new icon and walking over it/touching it doesnt shock you.
var/mangled = 0 // It gets a new icon, It will occasionally "spark" causing a small area flash effect to mobs, and draining a percentage of power.
var/ccolor = rgb(0,0,0) //Color of the wires insulation.
var/channel = 0 // Channel the wire is connected to, between 0 and 3.
var/connecting = 0 // Directions the wire connects to, Bitflag. 1 is up, 2 is down, 4 is left, 8 is right, or something.
var/insheat = 200 // How much heat does it take to destroy the insulation? Higher heat means less chance to melt, but more damage when it does.
var/resistance = 50 // How much energy is lost when passing through conduit. Affects the heat of the cable.
var/datum/conduit/powernet/parent = null // The powernet parent of the cable.
var/drop = null // The object dropped when this cable is removed.
var/list/siblings // Pipes of the same channel, in the cardinals of this pipe, that are also connected to it. Cleans up building and stuff.



/obj/conduit/power/initialize() // Called at round start. Its really just a more intensive build process.
if (insulated)
if (!rand(0,100))
strip() // Low chance for wire to start stripped.

if (!rand(0,500))
mangle() // Really low chance for wire to start mangled.

build()



/obj/conduit/power/process() // Called every few frames or so. Powernets dont really need all that much for processing.
if (mangled)
if (parent.power)
if (prob(5))
spark()
parent.power *= 0.9 // Instantly lose 10% of energy in powernet. If there are lots of mangled wires, this is a serious issue.



/obj/conduit/power/proc/build() // Called whenever a new cable is placed.
var/turf/M = get_turf(src)
for (var/obj/conduit/power/C in orange(1)) // Generate Siblings.
if (C.channel == channel)
var/turf/V = get_turf(C)
if (((connecting&1) && (C.connecting&2) && (V.y == M.y-1) && (V.x == M.x)) | ((connecting&2) && (C.connecting&1) && (V.y == M.y+1) && (V.x == M.x)) | ((connecting&4) && (C.connecting&8) && (V.y == M.y) && (V.x == M.x-1)) | ((connecting&8) && (C.connecting&4) && (V.y == M.y) && (V.x == M.x+1)))
siblings += C
C.siblings += src

for (var/obj/conduit/power/C in siblings) // Merge sibling pipenets, adopt yourself a parent.
if (C.parent)
if (parent)
parent.merge(C.parent)
else
parent = C.parent
parent.children += src
parent.eff += resistance

else
world.log << "[get_timestamp()] - [src] found orphan pipe [C] at [get_turf(C)]."

if (!parent) // Create your own pipenetwork if you dont have one already.
parent = new /datum/conduit/powernet()
parent.children += src
parent.eff += resistance



/obj/conduit/power/proc/rebuild() // Called by powernet whenever a cable is removed.
build() // This is really innefficient, Workin' on it.



/obj/conduit/power/proc/remove() // Called when this cable is removed.
for (var/obj/conduit/power/P in siblings)
P.siblings -= src

parent.eff -= resistance
parent.rebuild() // Calls rebuild() proc on all of its children to ensure they are rebuilt once, and only once.



/obj/conduit/power/proc/mangle() // Mangle the wire.
if (insulated)
insulated = 0
mangled = 0
update_icon()



/obj/conduit/power/proc/strip() // Strip the wire.
if (insulated)
insulated = 0



/obj/conduit/power/proc/melt() // Melt the wire. Heat the atmosphere.
strip()
var/turf/M = get_turf(src)
//M.air.heat(insheat)



/obj/conduit/power/proc/spark() // Make sparks! Wont spark without power going through it.
if (parent.power)
if (mangled)
//spark AND flash!
else
//just spark...



/obj/conduit/power/update_icon() // Make sure the wire looks like it should.
if (mangled)
icon_state = ("power_mangled_[channel]_[connect]")
if (insulated)
icon_state = ("power_[channel]_[connect]")
//blend to color
else
icon_state = ("power_[channel]_[connect]")


Problem description:

I get the idea im doing something very wrong.
You're going to need to specify what the issue is here, otherwise we can't help.
I feel like theres a better, more proper way to do most of the things im doing. I'm worried about the binary logic on line 44 mostly.

The rest is mostly just me second guessing myself, wondering what little details im missing, If theres already some bitflag direction thing defined i should use instead, etc.

For some context, The cable is only supposed to be able to connect in the cardinal directions.
Best response
You can use a backslash to break things across multiple lines, makes it a lot more readable:
            if (((connecting&1) && (C.connecting&2) && (V.y == M.y-1) && (V.x == M.x)) || \
((connecting&2) && (C.connecting&1) && (V.y == M.y+1) && (V.x == M.x)) || \
((connecting&4) && (C.connecting&8) && (V.y == M.y) && (V.x == M.x-1)) || \
((connecting&8) && (C.connecting&4) && (V.y == M.y) && (V.x == M.x+1)))


The logic looks correct, assuming the connecting flags are manually set somewhere else. You might want to use the NORTH, SOUTH, EAST, WEST constants if you have trouble remembering which is which:
            if (((connecting&NORTH) && (C.connecting&SOUTH) && (V.y == M.y-1) && (V.x == M.x)) || \
((connecting&SOUTH) && (C.connecting&NORTH) && (V.y == M.y+1) && (V.x == M.x)) || \
((connecting&EAST) && (C.connecting&WEST) && (V.y == M.y) && (V.x == M.x-1)) || \
((connecting&WEST) && (C.connecting&EAST) && (V.y == M.y) && (V.x == M.x+1)))



I was bored, so I wrote this alternative implementation just to do some bit twiddling. I didn't test or profile it, though, but if you wanted examples of other ways to implement it:
/obj/conduit/power/proc/build() // Called whenever a new cable is placed.
var/connectTo = ( ((connecting&(NORTH|EAST)) << 1) | ((connecting&(SOUTH|WEST)) >> 1) ) & ~connecting
if (connectTo & NORTH)
for (var/obj/conduit/power/C in locate(x,y+1,z))
if (C.channel == channel && C.connecting&SOUTH)
siblings += C
C.siblings += src
if (connectTo & SOUTH)
for (var/obj/conduit/power/C in locate(x,y-1,z))
if (C.channel == channel && C.connecting&NORTH)
siblings += C
C.siblings += src
if (connectTo & EAST)
for (var/obj/conduit/power/C in locate(x+1,y,z))
if (C.channel == channel && C.connecting&WEST)
siblings += C
C.siblings += src
if (connectTo & WEST)
for (var/obj/conduit/power/C in locate(x-1,y,z))
if (C.channel == channel && C.connecting&EAST)
siblings += C
C.siblings += src
// ...


<edit> Whoops, was using dir instead of connecting to calculate connectTo
Okay... so i should use TWO ampersands and || thingies?

As well, I didn't know you could use locate like that, from the reference docs i got the impression it moves src to those coords.
In response to Nullbear
Nullbear wrote:
Okay... so i should use TWO ampersands and || thingies?

&& and || are logical AND and OR, whereas & and | are the bitwise AND and OR.

When you're comparing booleans (true/false values) you want to use the logical && and ||.

When you're masking and combining bits, you want to use the bitwise & and |.


As well, I didn't know you could use locate like that, from the reference docs i got the impression it moves src to those coords.

locate(x,y,z) just returns a turf at a particular coordinate. You can search inside that turf's contents as I did above, or you can set an object's loc to the turf to forcibly move it there, or really anything.


Oh, and I just noticed I was using dir instead of connecting to generate connectTo in my example. I edited the original post in case anyone actually uses it.