Autojoining

by Forum_account
Autojoining
Helpful procs for creating autojoining turfs and objects.
ID:738093
 
The library provides autojoin16, autojoin47, and autojoin256 procs for turfs and movable atoms. This lets you easily set the state of a turf or add an overlay to create autojoining effects.

To create an outline around walls, all you have to do is:

turf
New()
..()

if(density)
var/n = autojoin16("density")
overlays += icon('outline.dmi', "[n]")

The autojoin16() proc checks the density var of each neighbor and returns a number in the 0 .. 15 range based on which neighbors are dense. You can use this value to change the turf's icon_state or add an overlay that creates a visually consistent effect from tile to tile.
The library isn't terribly complex but it contains code I've written in lots of projects. I may create other resources that use these procs so it makes sense to have autojoining procs in their own library so other resources can just include that.

For 16 states, the bit values increase in clockwise order starting from the top (top = 1, right = 2, bottom = 4, left = 8). For 256 states, it's clockwise order starting from the top-left (top-left = 1, top = 2, top-right = 4, right = 8, bottom-right = 16, bottom = 32, bottom-left = 64, left = 128). 47-state autojoining uses the same values as 256-state, it just doesn't include all states (ex: there's no state for 2, 3, or 6 - if the 2 bit is set, so are the 1 and 4 bits).

This library also crosses A off the list of letters I didn't have libraries for. I still have B, C, E, G, J, L, N, Q, U, X, Y, and Z left, if anyone can think of a topic for one of those letters. I'm afraid I'll have to make xylophone, yo-yo, and zebra libraries =)
In response to Forum_account
May I suggest using the bit values defined in Lummox JR's All Together Now? I've been using it as the standard in my own libraries for years so that the graphics produced by IconCutter would match.
It's possible that someone uses different bit values than both the library and IconCutter, so there's always a chance the default values will be wrong for someone. I can try to find a way to let developers customize the bit values but I wouldn't want it to hurt its performance (considering these are procs that may be called on every turf in the world).

I'll try to come up with something but if you want to use the library with different bit values, the best approach is to just modify its constants directly.
This library also crosses A off the list of letters I didn't have libraries for. I still have B, C, E, G, J, L, N, Q, U, X, Y, and Z left, if anyone can think of a topic for one of those letters. I'm afraid I'll have to make xylophone, yo-yo, and zebra libraries =)

A X-ray library be nice
I was recently made aware of the bitflags being a different choice in this library vs. the long-established BYOND standard. It'd definitely be a good idea to at least put in an option to handle the different types. The bitflags I use, putting NORTH at 1, come from an older standard developed by Pmikell, and these have been worked into many games. (Until your library the only exceptions I was aware of were from Foomer and Xooxer. Foomer used only simple 13-state joins. Xooxer attempted 47-state joining but with a choice of flags that made bitwise manipulation difficult, putting all diagonals in the upper nybble.)

Performance-wise, I think you'll actually do better switching a lot of these procs to use get_step() instead of locate(). The locate() implementation has to be much less efficient than get_step() over a large number of runs, because you're doing match operations on x and y instead of letting the system handle it, which is just running more instructions than you need. I prefer to use loops for my implementations, but perhaps the unrolling you use is faster.

From what I can tell, it also looks like your 47-state joining is broken. The logic in your code says the corner is filled if 1) either side is a match, or 2) the corner itself is a match. In 47-state joining a corner should only be filled if both adjacent sides and the corner all match. This is simple to calculate by doing just a 256-state join and then some bit twiddling. The bit twiddling would be the same for your bitflags as the standard ones, except that you'd use an OR of 170 instead of 85.