Extended Rigid Bodies

So, it's nice to be able to push blocks around that are larger than 1x1. An initial effort to achieve this will look like this:

``````[ >  Player | BigBlock ] -> [  >  Player | > BigBlock  ]
[ Moving BigBlock | BigBlock ] -> [ Moving BigBlock | MOVING BigBlock ]``````

To the naked eye it will look splendid:

but upon closer inspection it will reveal itself to be rather a flimsy construction.

Here be a rabbit hole - there are many approaches of increasing complexity, depending on what you want to achieve - I'd advice to not read down any further into this document than you need to.

If you want rigidbodies that you can push, but without being able to push several objects in a row, you can use the following sort of code:

``````[ > Player | Box ] -> [ > Player | > Box ]

startloop

[ moving Box1 | Box1 ] -> [ moving Box1 | moving Box1 ]
[ moving Box2 | Box2 ] -> [ moving Box2 | moving Box2 ]
[ moving Box3 | Box3 ] -> [ moving Box3 | moving Box3 ]
[ moving Box4 | Box4 ] -> [ moving Box4 | moving Box4 ]

[ > Box | Box ] -> [ > Box | > Box ]

endloop

[ > Box | Wall ] -> cancel``````

This breaks if you have several characters that are trying to push blocks in a single turn - because if any single effort fails, the whole turn is canceled.

To my knowledge (please prove me wrong!) it's impossible to get full rigidity in the basic rules system already described, because the movements are all carried out independently in the moving phase, and it's a pain to figure out what moved successfully, what didn't, and even if you could find out that part of a block couldn't successfully move, how would you stop everything else from moving?

Anyway, it's a gigantic can of worms. The solution initially I thought would be to add a keyword to objects, to mark them as rigid. However, I later realized that it was far nicer, and cooler, and more in-keeping with the engine, to think of rigidity as something you could apply to rules.

So, a rigid object is one where, if one part can't move, no parts can. And a rigid rule is a rule where, if anything it tries to move can't move, then the rule doesn't apply at all (it actually marks itself as disabled and resimulates the entire turn).

So, for our example above

``````[ >  Player | BigBlock ] -> [  >  Player | > BigBlock  ]
[ Moving BigBlock | BigBlock ] -> [ Moving BigBlock | MOVING BigBlock ]``````

we want that, if any of the BigBlock pieces doesn't get to move, that whole rule just doesn't apply. Actually, we probably also don't want the first rule to apply. So what we do is that we group the rules together using the + symbol, and we mark them as rigid

``````rigid [ >  Player | BigBlock ] -> [  >  Player | > BigBlock  ]
+ rigid [ Moving BigBlock | BigBlock ] -> [ Moving BigBlock | MOVING BigBlock ]``````

and magically it works

So all's good if you have a single rigid block, but if you try to have blocks pushing other blocks it gets complicated. Let's say you want a big block to collide with little blocks. You end up with stuff like this:

``````[ > Player | LittleBlock ] -> [ > Player | > LittleBlock ]

[ > LittleBlock | LittleBlock ] -> [ > LittleBlock | > LittleBlock ]

rigid [ > LittleBlock | BigBlock ] -> [ > LittleBlock | > BigBlock ]
+ rigid [ >  Player | BigBlock ] -> [  >  Player | > BigBlock  ]
+ rigid [ moving BigBlock | BigBlock ] -> [ moving BigBlock | moving BigBlock ]
+ [ > BigBlock | LittleBlock ] -> [ > BigBlock | > LittleBlock ]``````

The rule is, anything that adds motion to a BigBlock has to be marked as rigid. Repeating the code twice isn't so bad, really, but if one has more than two block types, there's no nice way of encompassing all the ways that they can interact.

Let me illustrate with a simple example: let's try to model two crate types, where crates can push crates

``````=======
LEGEND
=======

Crate = OrangeCrate or BlueCrate
======
RULES
======

[ >  Player | Crate ] -> [  >  Player | > Crate  ]

[ > Crate | Crate ] -> [ > Crate | > Crate ]
``````

which works splendidly. But what if we weren't allowed to refer to crate or combine them together into a rulegroup in the second rule? We could try something like:

``````[ >  Player | Crate ] -> [  >  Player | > Crate  ]

[ > OrangeCrate | OrangeCrate ] -> [ > OrangeCrate | > OrangeCrate ]
[ > OrangeCrate | BlueCrate ] -> [ > OrangeCrate | > BlueCrate ]
[ > BlueCrate | OrangeCrate ] -> [ > BlueCrate | > OrangeCrate ]
[ > BlueCrate | BlueCrate ] -> [ > BlueCrate | > BlueCrate ]``````
you can push around pairs of blocks, but a big alternating sequence of blocks you can't deal with

If only there were some way of looping through these four rules. Well, adding them all to the same rulegroup is one way, but in the case of rigid rules we don't want to cancel the movement of EVERYTHING just because one block can't move - so we need another layer of loopiness. So, let's introduce startloop and endloop;

``````[ >  Player | Crate ] -> [  >  Player | > Crate  ]

startLoop

[ > OrangeCrate | OrangeCrate ] -> [ > OrangeCrate | > OrangeCrate ]
[ > OrangeCrate | BlueCrate ] -> [ > OrangeCrate | > BlueCrate ]
[ > BlueCrate | OrangeCrate ] -> [ > BlueCrate | > OrangeCrate ]
[ > BlueCrate | BlueCrate ] -> [ > BlueCrate | > BlueCrate ]

endLoop``````
and voila!

For the above example, this is identical to saying

``````[ >  Player | Crate ] -> [  >  Player | > Crate  ]

[ > OrangeCrate | OrangeCrate ] -> [ > OrangeCrate | > OrangeCrate ]
+[ > OrangeCrate | BlueCrate ] -> [ > OrangeCrate | > BlueCrate ]
+[ > BlueCrate | OrangeCrate ] -> [ > BlueCrate | > OrangeCrate ]
+[ > BlueCrate | BlueCrate ] -> [ > BlueCrate | > BlueCrate ]``````

However, we don't have this luxury for rigidbodies. So, with all that said, here's what code for a system with several rigid bodies and some small blocks looks like:

``````startloop

[ > Player | Smallcrate ] -> [ > Player | > SmallCrate ]

[ >  Player | RedCrate ] -> [  >  Player | > RedCrate  ]
+ rigid [ moving RedCrate | RedCrate ] -> [ moving RedCrate | moving RedCrate ]
+ [ >  Crate | RedCrate ] -> [  >  Crate | > RedCrate  ]

[ >  Player | GreenCrate ] -> [  >  Player | > GreenCrate  ]
+ rigid [ moving GreenCrate | GreenCrate ] -> [ moving GreenCrate | moving GreenCrate ]
+ [ >  Crate | GreenCrate ] -> [  >  Crate | > GreenCrate  ]

[ >  Player | BlueCrate ] -> [  >  Player | > BlueCrate  ]
+ rigid [ moving BlueCrate | BlueCrate ] -> [ moving BlueCrate | moving BlueCrate ]
+ [ >  Crate | BlueCrate ] -> [  >  Crate | > BlueCrate  ]

[ > Crate | SmallCrate ] -> [  > Crate | > SmallCrate ]

endloop``````

And this gives us the image at the beginning of this document:

I apologise that it's not easier to do. I really thought the idea of rigid rules would trivialize a lot of the hard work, but it still left things a bit gross. It's messy, code that uses it is going to be messy/hacky. But, it's there if you want it.

If anyone has understood this and has a suggestion for a way they think is better for dealing with extended bodies, I would really like to hear it - I'll happily rip out the current rigid body system if there's something nicer : )