1

Background
I'm trying to write some modular style code in Maya (it's in 3D, but I'm doing it in a 2D style for now), where you make an object, and with each side (x,y,-x,-y), define a connector. There can be multiple connectors per side, and multiple sides/objects per connector. These also have a chance value, both on the connector and object, to determine how frequently they will be generated.

If I can eventually manage, I'll have it able to generate it's own content, so in a way this is more of the backbone of the project. Here is a quick example I've drawn up from a top down view, it has the object names and connector names shown so you can see the way I've designed it to work, currently in a tile based way - https://i.stack.imgur.com/actrW.png

Problem
I got the basic part of the selection code working, where it'll take an object, look up all connectors, pick one, look up all objects with matching connectors, and pick one, to have a seamless transition. However, I realised this is only useful for connecting to a single block, and it'd cause problems if you had any more, and that having more makes it a whole lot more complicated.

So, if there is 1 adjacent block, all that needs to be done is pick an side. If 'x' is chosen, just say that is connected to 'connector1', the code searches 'connector1' for all objects using it, chooses one, and places it in the correct place.
Now, if there are 2 adjancent blocks, it needs to find something that matches both connectors either side. If the sides are 'x' and 'y', and the connectors are 'xconnector' and 'yconnector', it needs to search for any block that uses both 'xconnector' and 'yconnector' with the two sides next to each other, meaning it could be xy, -xy, x-y, -x-y, either normal or mirrored, so there are 8 possible matching combinations.
However, it could be a lot more complicated, especially with 3 or 4 adjacent blocks, so I need to write something that would handle any value thrown at it



So basically, I hope I've explained it well enough, but it has gone slightly over my head so I could do with a little help if anyone has any idea about it :)

If it will help, here are sections of my current code, an example stored list is in the bottom link:
Add/remove object to list: http://pastebin.com/tX5rVLMi
Choose connected edge (works with 1 side): http://pastebin.com/gwDpZV8c
Output stored objects (for knowing what's going on): http://pastebin.com/dQD1i3XU

Peter
  • 3,186
  • 3
  • 26
  • 59
  • Your terminology is really unclear I'm afraid -- I was completely surprised by the linked image! E.g. "where you make an object, and with each side (x,y,-x,-y), define an 'edge'" -- after I got past the idea that "(x,y,-x,-y)" was trying to specify the endpoints of a line segment, this suggests that an "object" has 4 "edges". But the only way this would make sense is if "object" = "tile", which is what I originally thought, but I think you mean an object to be something like "a river" or "a road". – j_random_hacker Jul 03 '14 at 19:11
  • So yeah, I've updated the image and attempted to improve the terminology a little, and you're entirely correct with the tile idea there, sorry I didn't explain it well enough, the river idea was just to show different variations of the block connecting together through the 'river' connector. – Peter Jul 03 '14 at 19:42
  • Don't mean to nitpick, but by "where it'll take an object, look up all connectors, pick one, look up all objects with matching connectors" I guess you mean "where it'll take an object *that already occupies one or more placed tiles but is not yet complete*, look up all connectors *on tiles which that object occupies and which don't already border another tile*, pick one, look up all *tile types* with matching connectors"... – j_random_hacker Jul 03 '14 at 22:02
  • Anyway I think you're right -- I would build 15 lists of tiles, 1 for each valid combination of {neighbour present, neighbour absent} for all 4 sides (there are 16 combinations in total, but you will never be trying to add a tile that is not adjacent to a neighbouring tile on *any* side). If you order the connectors in some way (it can be totally arbitrary, e.g. by assigning different strings or integers to them) and keep each list sorted (see upcoming comment) then you can binary-search these lists to quickly find the valid tiles. – j_random_hacker Jul 03 '14 at 22:10
  • Your 15 lists will have various numbers (from 1 to 4) of connector constraints. You'll need a multi-key (lexicographic) sort to handle these -- e.g. in the list for "x present, -y present, y present, rest absent", every element will consist of an array of 3 connectors describing its constraints, plus the description of the tile itself, while in the list for "-y present, rest absent" every element will consist of a single connector "constraint" plus the description of the tile itself. – j_random_hacker Jul 03 '14 at 22:15
  • One more thing to note is that unless you have tiles for every possible combination of connectors, it will be possible to "back yourself into a wall" by adding tiles one at a time. I think you'll probably have to deal with this via backtracking (and thus recursion), though there may be other nicer algorithms. – j_random_hacker Jul 03 '14 at 22:19
  • Thanks, I want it to pick from the entire pool of stored blocks, which could potentially be separate from the creation (for some reason it didn't update the link, check the image again to clear things up) :) But yeah, do you mean 15 lists per block or overall? I have a feeling it'll literally take a good half a day of testing to figure out, so I'll try your way out with it. And with the latest comment, I have realised this and I was hoping it wouldn't be bad haha, but backtracking looks useful so I'll have a look into it, cheers :) – Peter Jul 04 '14 at 10:21
  • So if I understand correctly, you are dealing with a kind of puzzle. What is your question exactly? – user189 Jul 04 '14 at 12:04
  • @Peter: I meant 15 lists overall. A tile will usually belong to multiple lists -- e.g. if some particular tile is in the list for "x present, -y present, y present, rest absent" then it will also be in the 6 other lists that correspond to subsets of the "present edges" ({x}, {-y}, {y}, {x,-y}, {x,y}, {-y,y}). – j_random_hacker Jul 04 '14 at 13:08
  • Sorry about not picking it up fast aha, it's not the usual way I work so I'm trying to get my head around it. Are you suggesting to store each tile that has been placed in the matching lists (aside from the ones that have no empty slots), along with the connector info, which will allow easy searches? If so, would that still be usable with thousands of blocks, as it sounds like it'd use a lot of memory. I'll attempt to write the placement code soon, might make things a bit easier if I can see the results :) – Peter Jul 04 '14 at 18:31
  • I'm suggesting storing tiles that *haven't* been placed yet in these 15 matching lists. The idea is that you flesh out your map by repeatedly doing this: (1) pick (e.g. randomly) some existing position that is not yet covered by a tile, but has some subset of its neighbours covered by tiles; (2) find a tile that can legally go there. To answer the question for step (2) ("What tiles could legally go in this position?") you need 2 pieces of information: (1) what subset of neighbours are already present? (15 possibilities; this tells you *which* list to look in); ... – j_random_hacker Jul 06 '14 at 21:02
  • ... (2) the connectors that are on those already-present tiles (this tells you *what to look for* in that list -- all the legal tiles will be in one contiguous block somewhere in the list, because you have ordered them by the list of connectors that they "fit" -- which means that you can find this block efficiently with binary search). BTW I don't get notified of your comments unless you write "@j_random_hacker". – j_random_hacker Jul 06 '14 at 21:05

0 Answers0