From 27a603f0e1448d8996052404f047c5884b2a268f Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 12 Jan 2025 22:14:04 -0500 Subject: [PATCH] Yes, feel the burn. --- shiterator.hpp | 88 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/shiterator.hpp b/shiterator.hpp index c2a7dbe..bbbd6af 100644 --- a/shiterator.hpp +++ b/shiterator.hpp @@ -13,20 +13,92 @@ /* * # What is This Shit? * - * Announcing the Shape Iterators, or `shiterators` for short. You could also say these are Shaw's Iterators, but - * either way they are the _shit_. Or are they shit? You decide. Maybe they're "shite"? + * Announcing the Shape Iterators, or "shiterators" for short. The best shite + * for C++ for-loops since that [one youtube + * video](https://www.youtube.com/watch?v=rX0ItVEVjHc) told everyone to + * recreate SQL databases with structs. You could also say these are Shaw's + * Iterators, but either way they are the _shite_. Or are they shit? You decide. + * Maybe they're "shite"? * - * A shiterator is a simple generator that converts 2D shapes into a 1D stream of x/y coordinates. You give it a matrix, some parameters like start, end, etc. and each time you call `next()` you the next viable x/y coordinate to complete the shape. + * A shiterator is a simple generator that converts 2D shapes into a 1D stream + * of x/y coordinates. You give it a matrix, some parameters like start, end, + * etc. and each time you call `next()` you get the next viable x/y coordinate to + * complete the shape. This makes them far superior to _any_ existing for-loop + * technology because shiterators operate _intelligently_ in shapes. Other + * [programming pundits](https://www.youtube.com/watch?v=tD5NrevFtbU) will say + * their 7000 line "easy to maintain" switch statements are better at drawing + * shapes, but they're wrong. My way of making a for-loop do stuff is vastly + * superior because it doesn't use a switch _or_ a virtual function _or_ + * inheritance at all. That means they have to be the _fastest_. Feel free to run + * them 1000 times and bask in the glory of 1 nanosecond difference performance. * - * A shiterator tries to ensure a few things: + * It's science and shite. * - * 1. All x/y values will be within the Matrix you give it. + * More importantly, shiterators are simple and easy to use. They're so easy to + * use you _don't even use the 3rd part of the for-loop_. What? You read that right, + * not only have I managed to eliminate _both_ massive horrible to maintain switches, + * and also avoided virtual functions, but I've also _eliminated one entire part + * of the for-loop_. This obviously makes them way faster than other inferior + * three-clause-loop-trash. Just look at this comparison: + * + * ```cpp + * for(it = trash.begin(); it != trash.end(); trash++) { + * std::cout << it << std::endl; + * } + * ``` + * + * ```cpp + * for(each_cell it{mat}; it.next();) { + * std::cout << mat[it.y][it.x] << std::endl; + * } + * ``` + * + * Obviously this will outperform _any_ iterator invented in the last 30 years, but the best + * thing about shiterators is their composability and ability to work simultaneously across + * multiple matrices in one loop: + * + * ```cpp + * for(line it{start, end}; it.next();) { + * for(compass neighbor{walls, it.x, it.y}; neighbor.next();) { + * if(walls[neighbor.y][neighbor.x] == 1) { + * wall_update[it.y][it.x] = walls[it.y][it.x] + 10; + * } + * } + * } + * ``` + * + * This code sample (maybe, because I didn't run it) draws a line from + * `start` to `end` then looks at each neighbor on a compass (north, south, east, west) + * at each point to see if it's set to 1. If it is then it copies that cell over to + * another matrix with +10. Why would you need this? Your Wizard just shot a fireball + * down a corridor and you need to see if anything in the path is within 1 square of it. + * + * You _also_ don't even need to use a for-loop. Yes, you can harken back to the old + * days when we did everything RAW inside a Duff's Device between a while-loop for + * that PERFORMANCE because who cares about maintenance? You're a game developer! Tests? + * Don't need a test if it runs fine on Sony Playstation only. Maintenance? You're moving + * on to the next project in two weeks anyway right?! Use that while-loop and a shiterator + * to really help that next guy: + * + * ```cpp + * box it{walls, center_x, center_y, 20}; + * while(it.next()) { + * walls[it.y][it.x] = 1; + * } + * ``` + * + * ## Shiterator "Guarantees" + * + * Just like Rust [guarantees no memory leaks](https://github.com/pop-os/cosmic-comp/issues/1133), + * a shiterator tries to ensure a few things, if it can: + * + * 1. All x/y values will be within the Matrix you give it. The `line` shiterator doesn't though. * 2. They try to not store anything and only calculate the math necessary to linearlize the shape. * 3. You can store them and incrementally call next to get the next value. * 4. You should be able to compose them together on the same Matrix or different matrices of the same dimensions. * 5. Most of them will only require 1 for-loop, the few that require 2 only do this so you can draw the inside of a shape. `circle` is like this. * 6. They don't assume any particular classes or require subclassing. As long as the type given enables `mat[y][x]` (row major) access then it'll work. - * 7. The matrix given to a shiterator isn't actually attached to it, so you can use one matrix to setup an iterator, then apply the x/y values to any other matrix of the same dimensions. + * 7. The matrix given to a shiterator isn't actually attached to it, so you can use one matrix to setup an iterator, then apply the x/y values to any other matrix of the same dimensions. Great for smart copying and transforming. * 8. More importantly, shiterators _do not return any values from the matrix_. They only do the math for coordinates and leave it to you to work your matrix. * * These shiterators are used all over the game to do map rendering, randomization, drawing, nearly everything that involves a shape. @@ -47,11 +119,11 @@ * * ## Thanks * - * Special thanks for Amit and hirdrac for their help with the math and for + * Special thanks to Amit and hirdrac for their help with the math and for * giving me the initial idea. hirdrac doesn't want to be held responsible for * this travesty but he showed me that you can do iteration and _not_ use the * weird C++ iterators. Amit did a lot to show me how to do these calculations - * without branching. Thanks to you both and everyone helping me while I + * without branching. Thanks to you both--and to everyone else--for helping me while I * stream my development. */ namespace shiterator { using std::vector, std::queue, std::array; using