[video output=day629 member=cmuratori stream_platform=twitch stream_username=handmade_hero  project=code title="Removing Entity Generators" vod_platform=youtube id=i2apXO999EM annotator=Miblo]
[0:02][Recap and set the stage for the day][:speech]
[0:59][Plan to optionally start the player in the dungeon][:run]
[4:08][Try making CreateWorld() set StartRoom to the Dungeon.EntranceRoom][:"procedural generation"]
[4:47][We didn't start in the dungeon][:"procedural generation" :run]
[5:09][Make CreateWorld() set HeroRoom to the Dungeon.EntranceRoom->Vol][:"procedural generation"]
[5:48][We start in the dungeon][:"procedural generation" :run]
[6:07][Plan to place the door switch tiles in interesting formations][:"entity system" :"procedural generation" :run]
[10:12][Begin to introduce gen_entity_pattern][:"data structure" :"entity system"]
[12:54][Consider replacing entity creators with custom-written pattern generators][:"entity system" :research]
[15:58][Remove gen_entity_pattern][:"data structure" :"entity system"]
[16:02][Plan to remove entity generators][:"entity system" :"procedural generation" :research]
[18:00][Introduce GEN_CREATE_ENTITY_PATTERN() as a function creator][:"entity system" :"procedural generation"]
[19:58][Introduce an AddCat GEN_CREATE_ENTITY_PATTERN, and remove the old GEN_CREATE_ENTITY][:"entity system" :"procedural generation"]
[25:03][Remove GEN_CREATE_ENTITY and get_entity_tag_builder][:"data structure" :"entity system" :"procedural generation"]
[27:08][Make gen_create_pattern a function pointer in gen_entity, and remove unneeded values][:"data structure" :"entity system" :"procedural generation"]
[29:23][Change all the GEN_CREATE_ENTITY() functions to be regular functions][:"entity system" :"procedural generation"]
[32:13][Respecify the GenEntityAt*() functions as PlaceEntityAt*() and introduce PlaceEntityOnTraversable()][:"entity system" :"procedural generation"]
[35:13][Replace PlaceSnake(), AddSnakeHead() and AddSnakeBody() with an AddSnake GEN_CREATE_ENTITY_PATTERN][:"entity system" :"procedural generation"]
[43:07][Augment gen_entity with an asset_tag_hash for AddSnake to set][:"data structure" :"entity system"]
[44:20][Make CreateDungeon() call AddPattern(), renaming AddSnake to SnakePattern][:"entity system" :"procedural generation"]
[47:41][Consider ending up with gen_create_pattern as a flags field][:"entity system" :"procedural generation" :research]
[49:20][Introduce TileSwitchPattern and NPCPattern GEN_CREATE_ENTITY_PATTERN][:"entity system" :"procedural generation"]
[54:24][Streamline base_game.hht][:admin :"asset system"]
[57:13][Add asset_tag_id for Molly, Fred and Hannah][:"asset system"]
[59:08][Remove RecursiveOpenTileSearch(), FindPlaceToPutEntityGroup(), GetPieceAsset() and ChangeHash()][:"entity system" :"procedural generation"]
[1:08:06][Implement TileSwitchPattern][:"entity system" :"procedural generation"]
[1:10:51][Implement NPCPattern][:"entity system" :"procedural generation"]
[1:14:51][Respecify AddEntity() as AddPattern(), and remove AddTag() and AppendEntity()][:"entity system" :"procedural generation"]
[1:16:11][Weld gen_entity in to gen_entity_group as gen_entity_pattern][:"data structure" :"entity system" :"procedural generation"]
[1:21:43][Introduce AddTree() and replace GetTreeTags()][:"entity system" :"procedural generation"]
[1:26:32][Port the Lamp and Door creation code][:"entity system" :"procedural generation"]
[1:33:26][Port the pattern creator dispatch loop][:"entity system" :"procedural generation"]
[1:34:56][Port the apron and tree placement code in GenerateApron()][:"entity system" :"procedural generation"]
[1:36:11][Consider pattern placement][:"entity system" :"procedural generation" :research]
[1:37:21][Spec out pattern placement in SnakePattern, NPCPattern and TileSwitchPattern][:"entity system" :"procedural generation"]
[1:46:08][Introduce FindRandomOpenTile() and FindAdjacentOpenTile()][:"entity system" :"procedural generation"]
[2:13:00][Hit our Contents assertion in GenerateRoom()][:"entity system" :"procedural generation" :run]
[2:13:59][Mark TraversableIsOpen() as NotImplemented][:"entity system" :"procedural generation"]
[2:15:37][GenerateRoom() is indexing beyond the extent of the tile's Y dimension][:"entity system" :"procedural generation" :run]
[2:16:19][Fix Advance() to work in X and Y (not Z)][:"entity system" :"procedural generation"]
[2:16:47][Hit our NotImplemented marker in TraversableIsOpen()][:"entity system" :"procedural generation" :run]
[2:16:50][Implement TraversableIsOpen()][:"entity system" :"procedural generation"]
[2:19:35][Hit our assertion in GetTraversable()][:"entity system" :"procedural generation" :run]
[2:20:30][Fix TraversableIsOpen() to require a TraversableCount][:"entity system" :"procedural generation"]
[2:21:08][We generated a lot of actual stuff][:"entity system" :"procedural generation" :run]
[2:22:13][Scan FindAdjacentOpenTile() for bugs][:"entity system" :"procedural generation" :research]
[2:23:10][Step through FindAdjacentOpenTile()][:"entity system" :"procedural generation" :run]
[2:25:11][Consider TileSwitchPattern to be doing what we've told it to][:"entity system" :"procedural generation" :research]
[2:26:17][Fix AddPlayer() to use our stripped down set of tags][:"entity system" :"procedural generation"]
[2:26:49][Our stone walls are broken][:"entity system" :"procedural generation" :run]
[2:27:19][Make CreateWorld() start the hero in the bedroom][:"entity system" :"procedural generation"]
[2:28:30][Our orphans work, but the conversation tile is considered occupied][:"entity system" :"procedural generation" :run]
[2:28:55][Fix the edit_tile version of PlaceEntityAtTraversable() to call its namesake][:"entity system" :"procedural generation"]
[2:29:05][Our conversation tiles are unoccupied again][:"entity system" :"procedural generation" :run]
[2:29:25][Set the cats' asset alignment points][:"asset system" :run :ui]
[2:34:47][Introduce a StandardLightingPattern GEN_CREATE_ENTITY_PATTERN][:"entity system" :lighting :"procedural generation"]
[2:39:05][Our orphanage lacks light][:"entity system" :lighting :"procedural generation" :run]
[2:39:22][Make CreateDungeon() use our StandardLightingPattern][:"entity system" :lighting :"procedural generation"]
[2:40:34][Our dungeon is spectacularly lit][:"entity system" :lighting :"procedural generation" :run]
[2:41:52][Make CreateOrphanage() use our StandardLightingPattern][:"entity system" :lighting :"procedural generation"]
[2:43:35][Our orphanage is lit][:"entity system" :lighting :"procedural generation" :run]
[2:44:00][Spec out a light spacing rule in StandardLightingPattern, enabling Advance() to operate on passed Base and dGrid parameters, and introducing CalcBasePForOffset()][:"entity system" :lighting :"procedural generation"]
[2:50:32][Crash in GetSimSpaceTraversable()][:"entity system" :lighting :"procedural generation" :run]
[2:50:47][Fix StandardLightingPattern to use a newly introduced version of PlaceEntityAtP() that takes an edit_tile][:"entity system" :lighting :"procedural generation"]
[2:52:27][Our orphanage is well lit][:"entity system" :lighting :"procedural generation" :run]
[2:53:01][Make StandardLightingPattern decrease the light intensity][:"entity system" :lighting :"procedural generation"]
[2:53:15][Our orphanage is better lit][:"entity system" :lighting :"procedural generation" :run]
[2:53:50][Make UpdateAndRenderEntities() draw the lights][:"debug visualisation" :"entity system" :lighting]
[2:55:12][Our lights are well distributed][:"entity system" :lighting :"procedural generation" :run]
[2:56:35][Remove the snake segment lights][:"entity system" :lighting :"procedural generation"]
[2:57:34][Start to make CalcBasePForOffset() work from the centre][:"entity system" :lighting :"procedural generation"]
[2:59:47][Introduce AddBlock() for GenerateRoom() to use for doors][:"entity system" :"procedural generation"]
[3:09:46][Our doors remain invisible][:"entity system" :"procedural generation" :run]
[3:10:07][Make CreateWorld() set HeroRoom to the Dungeon.EntranceRoom->Vol][:"procedural generation"]
[3:10:25][We start in the dungeon][:"procedural generation" :run]
[3:10:41][Scan AddBlock() for bugs][:"entity system" :"procedural generation" :research]
[3:11:31][Our door is placed, just invisible][:"entity system" :"procedural generation" :run]
[3:13:24][Try making GenerateRoom() pass Tag_Floor to AddBlock()][:"asset system" :"procedural generation"]
[3:13:33][Our door is placed and visible][:"asset system" :"procedural generation" :run]
[3:13:51][Make GenerateRoom() set the DoorDim][:"entity system" :"procedural generation"]
[3:16:08][Our doors are visible and operable][:"entity system" :"procedural generation" :run]
[3:16:49][Make ExecuteBrainSwitches() move unlocked doors further into the floor][:"entity system"]
[3:17:11][Our doors drop fully into the floor][:"entity system" :run]
[3:18:01][Q&A][:speech]
[3:18:33][@ablindorphan][@handmade_hero Maybe it could actually be a :gameplay feature for the door movement to obscure the tiles one floor down?][:"entity system"]
[3:18:52][@longboolean][Q: When plopping down furniture / props do you want to allow for pattern variations, e.g. desk above, chair below desk, lamp on the right? But another pattern on a side wall would require a completely different arrangement][:"procedural generation"]
[3:19:29][@mindmark42][Q: Can you explain again why only one switch is being added to a room?][:"entity system" :"procedural generation"]
[3:20:24][@technicbeam][Q: You were talking about switching bodies vs switching heads. Would you be able to switch to have a snake / cat / bird / dragon body? That would be pretty cool, especially if it was required to accomplish something later in the game, like using the snake body to press down on multiple adjacent buttons at the same time][:gameplay]
[3:22:05][@hexadecimalinteger][Q: Will you add normal maps to sprites for :lighting effects?]
[3:22:20][@ablindorphan][Q: Are you intending for it to be a mix of hand-authored rooms and generated patterns, or pure generation?][:"procedural generation"]
[3:22:52][@longboolean][Q: Gameplay-wise are you going for something like needing to enter a pattern in a particular way, monsters get in the way, clearing the room makes it feasible to enter the code to unlock the door? Or are you thinking, have monsters that can't die that you need to look at their behavior and wrangle them into opening the doors for you?][:gameplay]
[3:23:17][@x1bzzr][@handmade_hero I've heard you say before that you don't believe it's good or necessary to know many programming languages because, in your words, "programming works from first principles". I do hear all the time, though, that you shouldn't be married to a programming :language and you should always use the best language for the problem you're trying to solve. Why do you think people think this way and can you elaborate on why you disagree?]
[3:26:29][@ablindorphan][Q: Do you find it harder to design the engine without the concrete requirements of a specific game design? I find sometimes I rathole on abstractions / generalisations I'll never end up using if I don't have a specific goal in mind]
[3:26:55][@maciejzbj1992][Q: I don't know if I can ask these here, but how's Star Code Galaxy doing? When will something be available?]
[3:27:39][@guybru5h_vi][Q: How do you avoid overcomplicating your code?]
[3:29:38][@hexadecimalinteger][Q: If I like a low level :language like C, but a syntax feature like member function, what's the solution? :Metaprogramming?]
[3:30:17][@hexadecimalinteger][Q: Yeah, I meant a feature that doesn't exist][:language]
[3:30:57][Plug Discord[ref
    site=Discord
    page="MollyRocket"
    url=https://discord.gg/mollyrocket] for questions on Star Code Galaxy][:research]
[3:31:50][@cyberdyneyeah][Q: When someone notes "// TODO(casey)", does that mean it's a TODO casey noted or a TODO for casey to do?][:language]
[3:32:46][@x1bzzr][Q: Following up on the question about programming languages. A lot of people seem to think that dynamic languages are way more expressive than non-dynamic ones in the sense that you can accomplish a lot with very little code. When you say these languages are limited do you mostly mean they don't allow you to write performant code or do you mean more than that?][:language]
[3:41:37][@vivonner][@handmade_hero It took me 400 lines of code to write a 2D plotting calculator in JavaScript. I don't know why it takes so much for a simple crud website though][:language]
[3:43:33][Thank you, everyone, with a plug of Wednesday's lecture for the University of Twente about optimising the grass and plant distribution code in The Witness][:speech]
[/video]
