And realized my collision code wasn't good enough.
I had originally gone for an overly simple collision model, which I hoped would be good enough: check for collisions at each corner of Robo-Ninja, and deal with whichever is the "most important" collision. Well, as Robo-Ninja is taller than a single 16x16 "block", I was running into instances where the head would go above the block without colliding, then the feet would collide with the block from beneath, and all sorts of brokenness would ensue. This also got me into trouble when I put ramps too close to other collisions, as it would get confused about what is colliding where.
So tonight I overhauled and reworked the collision system. Which, once again, leads me to my previous statement: Ramps are weird. It only took me about 30 minutes to get the basic collisions working with my new model (checking multiple points around the perimeter of the bounding box, processing each point's collision separately).
Then another 2 hours to get ramps working. Now I'm tired. The good news is that the ramps work more smoothly than before. Previously, going down a ramp, you'd run too far ahead, your feet would leave the ground, then you'd bounce down a bit, then run too far ahead again, and so forth. Which was bad, because it made it really hard to jump while running down a ramp. (you had to time it perfectly when your feet hit the ground). Now, your feet lock to the ramp on the way down.
So now I can continue on with my hard cave level. It took me about 25 tries to get through it while testing. My son was extremely excited about the existence of this cave level, but was rather unhappy that it was so hard.....