[video output=day630 member=cmuratori stream_platform=twitch stream_username=handmade_hero  project=code title="Adding Interesting Tile Patterns" vod_platform=youtube id=CVt1TBeI4q8 annotator=Miblo]
[0:01][Recap and set the stage for the day][:speech]
[2:19][Balancing random and hand-coded :"procedural generation"][:speech]
[6:00][Demo the door pressure plates][:"entity system" :run]
[7:21][Describe our entity pattern generator][:"entity system" :"procedural generation" :research]
[10:03][Augment gen_entity_pattern with a Difficulty for TileSwitchPattern() to use][:"data structure" :"entity system" :"procedural generation"]
[14:09][Discover ~4coder's Index (Project)][:admin]
[16:38][Set up TileSwitchPattern() to generate difficulty-based patterns][:"entity system" :prng :"procedural generation"]
[20:02][Introduce tile_pattern for TileSwitchPattern() to use][:"data structure" :"entity system" :"procedural generation"]
[22:41][Separate game design from engine programming][:speech]
[24:17][Introduce TileAlreadyExists()][:"entity system" :"procedural generation"]
[24:59][~4coder's indentation and f4_search_for_definition__project_wide][:admin]
[27:33][Finish implementing TileAlreadyExists()][:"entity system" :"procedural generation"]
[29:15][Make TileSwitchPattern() generate a pattern that avoids existing tiles][:"entity system" :"procedural generation"]
[35:34][Introduce AppendTile()][:"entity system" :"procedural generation"]
[36:41][We have no tiles][:"entity system" :"procedural generation" :run]
[36:59][Fix the TileAlreadyExists() test in TileSwitchPattern()][:"entity system" :"procedural generation"]
[37:07][We still only get one tile][:"entity system" :"procedural generation" :run]
[37:18][Fix TileSwitchPattern() to pass random numbers to FindRandomOpenTile()][:"entity system" :prng :"procedural generation"]
[37:35][We still only get one tile][:"entity system" :"procedural generation" :run]
[37:48][Double-check FindRandomOpenTile()][:"entity system" :"procedural generation" :research]
[39:21][Slightly rewrite TileAlreadyExists() for consistency and clarity][:"entity system" :prng :"procedural generation"]
[40:28][We're still only placing one tile][:"entity system" :"procedural generation" :run]
[40:59][Make TileSwitchPattern() generate exactly four tiles in the lowest Difficulty case][:"entity system" :"procedural generation"]
[41:11][We generated four tiles][:"entity system" :"procedural generation" :run]
[41:52][Check our random number generator][:prng :research]
[42:35][Test our random number generator in TileSwitchPattern()][:prng]
[46:14][Our random number generator seems well distributed][:prng :run]
[46:34][Decrease our random number generator test's sample count from 1000000 to 100][:prng]
[46:43][Our random number generator has a touch of bias towards the second quadrant][:prng :run]
[47:29][Increase our random number generator test's sample count from 100 to 1000][:prng]
[47:34][Our random number generator seems well distributed][:prng :run]
[47:48][Test _mm_aesdec_si128()[ref
    site=Intel
    page="Intel Intrinsics Guide"
    url=https://software.intel.com/sites/landingpage/IntrinsicsGuide/] in TileSwitchPattern()][:prng]
[52:36][_mm_aesdec_si128() has a similar distribution to our generator][:prng :run]
[52:57][Add a mixing step to our _mm_aesdec_si128() test][:prng]
[53:04][_mm_aesdec_si128()'s distribution remains similar][:prng :run]
[53:16][Decrease our _mm_aesdec_si128() test's sample count from 1000 to 100][:prng]
[53:28][_mm_aesdec_si128() has a similar distribution to our generator][:prng :run]
[53:40][Increase our _mm_aesdec_si128() test's sample count from 100 to 1000000][:prng]
[53:46][_mm_aesdec_si128() remains well distributed][:prng :run]
[53:59][Remove our :prng test]
[54:54][Set up TileSwitchPattern() to generate specified patterns][:"entity system" :"procedural generation"]
[59:04][@krrsplat][Q: After stream, you should mirror webcam so you are looking at the code]
[1:00:08][@an0nymal][Q: [@cmuratori Casey], I don't know if it's local to me, but I'm getting a lot of pixel flickering on the ~4coder capture. Cam is fine]
[1:01:44][@binarium][On source, it's very subtle, not an issue]
[1:03:27][Spec out the pattern rules in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:10:17][Create an overloaded v3s version of +=][:language]
[1:11:30][We have horizontal patterns][:"entity system" :"procedural generation" :run]
[1:12:11][Implement the TilePattern_Scatter case in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:13:59][Split out the pattern computation and generation in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:15:39][We have vertical patterns][:"entity system" :"procedural generation" :run]
[1:16:42][Pick the TilePattern_Snake in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:16:59][We have snake patterns][:"entity system" :"procedural generation" :run]
[1:17:30][Increase our Tiles.MaxCount from 4 to 8 in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:17:40][We have longer snake patterns][:"entity system" :"procedural generation" :run]
[1:18:39][Increase our Tiles.MaxCount from 8 to 16 in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:18:51][Hit our out-of-bounds assertion in RegisterEntity()][:"entity system" :"procedural generation" :run]
[1:19:23][Enlarge the Tiles array from 12 to 16 in brain_switches][:"data structure" :"entity system"]
[1:19:47][We have even longer snake patterns][:"entity system" :"procedural generation" :run]
[1:20:13][Augment tile_pattern with a RequiredEmptyNeighborCount, for TileSwitchPattern() to use in the TilePattern_Snake case][:"data structure" :"entity system" :"procedural generation"]
[1:24:56][Our snake patterns work beautifully][:"entity system" :"procedural generation" :run]
[1:26:00][Pick the TilePattern_Branching in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:26:11][We have branching patterns][:"entity system" :"procedural generation" :run]
[1:26:30][++SwearCount][:speech :swear]
[1:26:51][We need a cuss word counter in the Episode Guide][:speech]
[1:27:39][Pick the TilePattern_Scatter in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:27:54][We have scatter patterns][:"entity system" :"procedural generation" :run]
[1:28:02][Increase the Tiles.RequiredEmptyNeighborCount from 3 to 4 in TileSwitchPattern()][:"entity system" :"procedural generation"]
[1:28:08][We have disconnected scatter patterns][:"entity system" :"procedural generation" :run]
[1:28:52][Determine to fix the stairs-to-nowhere problem, and add a light to pressure plates][:"entity system" :lighting :"procedural generation" :run]
[1:29:42][Make TileSwitchPattern() add a light to the pressure plates][:"entity system" :lighting :"procedural generation"]
[1:30:51][We cannot see our lights][:"entity system" :lighting :"procedural generation" :run]
[1:31:12][Make UpdateAndRenderEntities() draw the light outlines][:"debug visualisation" :"entity system" :lighting]
[1:31:29][See our lights][:"debug visualisation" :"entity system" :lighting :run]
[1:31:40][Make TileSwitchPattern() elevate the lights][:"entity system" :lighting :"procedural generation"]
[1:31:46][Our lights sit above our pressure plates][:"entity system" :lighting :run]
[1:32:11][Make our pressure plates light up when pressed][:"entity system" :lighting :"procedural generation"]
[1:33:35][Our lights are no longer there][:"entity system" :lighting :run]
[1:35:21][Double-check our pressure plate light code][:"entity system" :lighting :research]
[1:37:10][Make TileSwitchPattern() initialise the light with 5.0f Emission][:"entity system" :lighting :"procedural generation"]
[1:37:37][Our lights are back][:"entity system" :lighting :run]
[1:38:30][Make UpdateAndRenderEntities() keep the light Color's fourth component at 1.0f][:"entity system" :lighting :"procedural generation"]
[1:39:48][Our lights remain][:"entity system" :lighting :run]
[1:39:52][Try increasing the pressed light intensity from 5 to 10 in ExecuteBrainSwitches()][:"entity system" :lighting :"procedural generation"]
[1:40:27][Our pressure plates never light up][:"entity system" :lighting :"procedural generation" :run]
[1:41:17][Try making ExecuteBrainSwitches() operate on Pieces\[2\]][:"entity system" :lighting :"procedural generation"]
[1:42:25][Our pressure plates remain unlit][:"entity system" :lighting :"procedural generation" :run]
[1:42:50][Step on to the AddPieceLight() call in TileSwitchPattern()][:"entity system" :lighting :"procedural generation" :run]
[1:44:49][GenerateRoom() places occluders in the environment][:"entity system" :lighting :"procedural generation" :research]
[1:46:11][Fix GenerateRoom() to place occluders more sensibly][:"entity system" :lighting :"procedural generation"]
[1:46:59][Make ExecuteBrainSwitches() loop through the pressure plate pieces to find its light][:"entity system" :lighting :"procedural generation"]
[1:49:02][@Molly][Hello there][:speech]
[1:50:27][Our pressure plates light up][:"entity system" :lighting :"procedural generation" :run]
[1:51:10][Comment out AddPattern() in CreateDungeon()][:"entity system" :lighting :"procedural generation"]
[1:51:28][@Molly][I'm back][:speech]
[1:51:51][Our dungeon is more brightly lit than expected][:"entity system" :lighting :"procedural generation" :run]
[1:52:15][Double-check our pressure plate lights][:"entity system" :lighting :"procedural generation" :research]
[1:52:38][Our dungeon is not dark][:"entity system" :lighting :"procedural generation" :run]
[1:53:40][Restrict GenerateRoom() to generate a stairwell from a Lower to Upper floor (and not also the other way)][:"entity system" :"procedural generation"]
[1:55:25][Our stairwells are better placed][:"entity system" :"procedural generation" :run]
[1:55:32][Make GenerateRoom() prevent traversal under staircases][:"entity system" :"procedural generation"]
[1:58:18][We can't go under the stairs][:"entity system" :"procedural generation" :run]
[1:59:12][Q&A][:speech]
[2:00:25][@frozenzerker][Audio was good]
[2:01:10][@mindmark42][Q: Any idea how to stop the snakes from getting stuck?][:"entity system" :movement]
[2:04:03][@i_love_codes][Q: Following up on the question I asked you before… I thought about what you said, and I'm not sure I understand. I'm sending this now just so you know I'm writing the question right now]
[2:04:34][@an0nymal][Q: Ouroboros! How about taking the thing we want to prevent and creating a unique game feature that emerges from it, i.e. Let the snake eat itself to become unstuck, etc?]
[2:05:02][@bulmanator][Q: I've seen things about having a fixed update clock for the game (60Hz etc) but rendering at a higher frame rate requires you to interpolate between states. To do this would you just duplicate your game state each time and interpolate between the current and previous for every entity etc? That seems quite expensive][:timing]
[2:06:06][@mattiamanzati][Q: I am looking up for a lightweight way to traverse 3D voxels along a ray and accumulate a color in OpenGL. Any suggestion about algorithms that are mostly branchless (if I remember correctly this was covered in [~hero Handmade Hero] only on CPU)?[ref
    author="Samuli Laine, Tero Karras"
    title="Efficient Sparse Voxel Octrees"
    url=http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.208.9830]]
[2:07:47][@incodegames][Q: I want to get deeper into C / assembly, but I already have three projects ongoing in C# and running my business. How do / did you manage learning new topics while inundated with other work?]
[2:10:08][@s0llygaming][Q: One thing that always gets me: How do you stop yourself from over-complicating things? I always seem to try be "clever" and it almost always seems to be a bad idea]
[2:13:26][@combicombi][Q: Would it be possible to have two switch tiles in very distant rooms that you have to hop on to open a door or unlock something?][:"entity system"]
[2:15:18][@yungkev_][Hi [@cmuratori Casey], you are looking very handsome today]
[2:15:44][@maliusarth][That cat hair floating around]
[2:16:24][@i_love_codes][Q: From what I understand, you started [~hero Handmade Hero] because you thought people didn't know what it took to make a real game and it would be good if they did, so it seems that you do care about influencing people to do things a certain way. Don't you think that teaching is more than just giving people the facts? You also need to show them why they should care and that takes convincing]
[2:23:18][@mvargasmoran][@handmade_hero I still enjoy your rants. There's truth to them]
[2:24:13][@longboolean][Q: Do you find value in checking out other parts of the computing space, even those you disagree with? Without interfering, of course]
[2:26:45][@i_love_codes][Q: Hope it's okay to ask one last question. If tomorrow everyone started using JavaScript for everything, you wouldn't care at all? Like, you will probably always use software written by other people. Wouldn't it be better that software was of good quality and, if you agree with that, shouldn't you try to influence people to care about software being high quality?]
[2:30:56][@filmore3][Why does JavaScript suck? Modern JavaScript is pretty nice][:language]
[2:32:47][Wrap it up][:speech]
[/video]
