Tag: complexity

  • little treasures

    I like food.  

    I mean, I like the culture and the feeling of food, the idea of it as a thing that links us and propels us and drives us to become more than eaters harvesting nurtients from organic objects, but instead seekers of taste and flavour and aroma and texture and everything that strikes the senses as we dine and indulge.

    It’s no wonder then that when a local international food market opened up near me, sitting here in my quasi-career change retirement and looking for something interesting to occupy me in the hours of the day when I wasn’t behind a keyboard or writing code or making art or studying for the next phase of my serious career, when that market opened that I found myself with a part time job amongst all that interesting sort of food culture.

    It was a fit. And then it wasn’t.

    I left that place and still had food culture on the brain.  And that analytical, data-processing brain of mine had already long been thinking about how I would automate many of our frustratingly manual processes with a good database and some customer model simulations, y’know, in code of course. It would be an interesting exercise, no? To walk through the aisles of a grocery store and map it into a complex digital economic simulation, figuring out all the maths of supply and demand clashing with the forces of microbiology and human pyschology.  Complex and challenging and—

    Politics. I forgot about politics.

    About the same time I was thinking about starting work on a simulation of that store I found myself weighing my future at the same, and internal politics played my hand for me and I gave notice.  I had been through one career burnout already. I wasn’t queued up quite yet for another—or a retriggering of the last one.

    You may know the next two months of that story if you’ve read this blog. 

    I started coding anyhow and my food market simulator idea became the foundations of a silly little cozy game roguelike pixel party coding project now known as Pleck’s Mart.

    But as politics are wont to do, the politics played out, calmed, resolved somewhat, and the vibe of the store reverted—and me, keeping my finger on the pulse of that place, a sudden found myself being offered a chance to go back and do that thing which I had originally thought would be my job: be a food culture guy working in a trendy local international food market. In other words, I am back at work at the place that lightly inspired me towards a video game idea.

    The coding may slow somewhat, but the fresh opportunity to observe a real food market with the eyes of a guy who has been trying to simulate one in said code—that is a priceless opportunity, no?

  • keys to gamer success

    My carefree days of hours-long coding sessions are on hiatus, it seems.

    Well, at least are coming in more sproadic than in the throes of mid-winter.

    I still am managing to find good blocks of free time to work through tickets, adding small enhancements, squashing bugs, and tweaking algorithms. The game creeps towards some kind of state of playability.

    And that’s the first key here, I think. 

    I spent two months working and committing code almost every single day, and all of that culminated in a thing that looked and played like an alpha-state game. Which is a big deal.

    Getting that same game to beta? That’s going to be the work of a few more months of work, lots of art, lots of writing, lots of hunting bugs. I mean, I now have an entire category of tickets that is called “playtesting” by which I sort things that I’m pretty sure I have fixed but until they crop up naturally in the middle of play—or I play long enough to feel confident that I fixed them—there isn’t much to do (besides maybe writing some tests) to ensure that they are working.

    And that’s the second key here, I think.

    This game thing I made is big and complex and—hell—its a simulation and it rolls along simulating and doing stuff behind the scenes that are the result of compound effects of algorithms that I wrote. Calculate this, math that, compute these. And it is deeply fascinating to see that at work—but it is anything but simple to untangle in my own head to know if it is actually working.

    I did the most dad-gamer thing the other day.  I ordered a copy of Civilization VII (which recently released) for my PS5, but I ordered it using airline points. Yeah, I had enough spare points to buy a ninety-dollar new release game and yet I still have bank.  But I have been watching the reviews of the new game (and I have played all six previous versions when they were new plus the spin offs) and people are pickyAF about the mechanics.  This game that is so complex it is almost an organic lifeform in an of itself, doesn’t behave exactly how people expect and they rant and scream online about how terrible it is. 

    And that’s the third key here, I think.

    Players can be particular. They want complex things but they also seem to hate complexity. Pleck’s Mart is no Civ 7 on the complexity scale, but I wrote about complexity previously when I compared this creation to Dwarf Fortress and the complexity of Pleck’s Mart has definiely increased since that post.  Yet, with complexity comes unpredictability, and simultaneously the inability to game out ever combination of that complexity. 

    How do you trust it other than to play it and have many other people play it and then be ready to nudge it back into balance if the balance is not as tuned as one might think? 

  • my great big spreadsheet ledger user interface adventure

    I’ve been thinking a lot this week about Dwarf Fortress. 

    Have you played Dwarf Fortress?

    Have you even heard of Dwarf Fortress? It’s a bit of a #iykyk kind of game, but one that some gamers have #k about for almost as long as the game has been in active development, which is well over 20 years.

    Two guys. One dream. One insanely complex game engine that fools you into thinking it is simplistic because its graphic design is, bluntly, outwardly visually rudimentary and (until recently) completely composed of colourful ASCII text characters.

    I’ve been thinking about this game, Dwarf Fortress, because as I develop my own little game project I’ve come to realize that many games, at their core, are essentially just pretty user interfaces for databases of varying complexity. I mean, I knew this. It’s always been my core understanding that to be a good games designer that at among many things you need a solid awareness of database design in your toolkit.

    My game is a database at its core. 

    I’ve mentioned this in a past post, but in creating my game I’m essentially designing a fancy UI for a really complex accounting ledger spreadsheet. THAT doesn’t sound nearly as much fun as a Science Fictional Supermarket, so you can see why I don’t lean into the former description in my marketing copy. That said, I am friends with more than a few accountants who might be into that, so—

    But I digress.

    Dwarf Fortress has been in active development for more than twenty years, because as the (perhaps apocryphal) story goes, the developers can’t seem to stop adding more rows and columns and macros to that game-as-spreadsheet metaphor.  The game is insanely complex. It is like the Matrix of database queries but with the cascading text representing dwarves and sheep and weapons and logs and, heck, I can’t even begin to name a fraction of a fraction of the elements here. I sure there is complexity layers in the game that are games in and of themselves that barely a handful of players have even discovered. It’s complex. Have I mentioned it is complex? 

    This complexity is on purpose, of course. (I assume.)

    I know many gamers who are (you know who you are) into wildly complex games with rules spanning many dozens or hundreds of pages, and in some cases, rule systems. DnD is essentially a giant rule system, that has depth and a bit of complexity but tries to keep it simple enough for our human brains to keep up. But Dwarf Fortress seems to embrace the complexity in the other direction and has both depth and complexity. Thousands of variables tangled in around themselves.

    Pleck’s Mart has from nearly the beginning had a database. But until yesterday that database was almost entirely about saving states and progressively loading game data.  Yesterday, tho, I added objects. And objects, see, are more than just a picture of something that appears in the game. Objects are the start of data complexity in the game. Objects are containers with variable states and value and properties that affect how they ultimately matter in the game. Objects are rows in that spreadsheet whose values react to conditions of the game, the passage of time, and the interaction by the player.

    It’s that start of my own game complexity that begins on one end of the spectrum with merely a virtual caselot of imaginary potatoes and ends all the way at the other scale with Dwarf Fortress.

    I’ve been thinking a lot about Dwarf Fortress this week not because Pleck’s Mart will ever be that complex but because it will always now, going forward, be some fraction as complex as Dwarf Fortress. 

    You might even call that a Dwarf Fortress Complexity Quotient, like as in Pleck’s Mart DFCQ equals about 0.01 as of right now. I’m striving for maybe about a 0.2, subjectively speaking of course.

    I have a long way to go, but the journey into a wildly entertaining spreadsheet ledger user interface adventure has begun. But let’s keep calling a game, ok.

  • incrementally npc

    In building this game world as it is, filled with floors and walls and shelves and light swtiches and everything else, I knew I was eventually going to run headlong into what I perceived as my biggest challenge: the NPC.

    What is an NPC? For all you non-gaming folks out there, the term NPC stands for Non Player Character, or anything in your game world that is for all intents and purposes “alive” and mobile. Mostly though, the term NPC refers to the people, animals and (in some games but so far not mine) monsters or enemies.

    The thing is, it is all fine and simple to build a wall or a shelf, but it’s a whole other undertaking to build in code something that has behaviours—behaviours like walking around the room and interacting with objects and having conversations with the player, et cetera, et cetera. 

    I mean, think about it this way: to move the player around the screen I have (of course) lots of hard rules built into the system about boundary collisions and input directions and all of that can be negotiated in real time by a human being playing the game with a brain inside their head poking at a keyboard.  

    But on the other hand, an NPC needs to be literally programmed to do things in the game. These are not magic or automatic. They are code, and carefully plotted tangles of logic loops. Like, simply to appear to move, an NPC needs to have a route to follow around the room, a kind of connect the dots map, and then of course to follow that map completely independently of whatever the player (with the aforementioned brain) is doing in the foreground and too, while everything else is going on. In every frame of game time, a hundred times per second, I need to have coded in a “what do I do now” kind of command that also tracks a “what have I already done” and a “what do I need to do next” and “where the heck am I in this multi-dimensional universe anyways” state of existence. 

    Sounds pretty straightforward, huh?

    To be fair, it is only just mathematics around geometry and timers and coordinate planes and incremental counters, joined together in an elaborate choreography upon an invisible stage that needs to itself be tracked and moved in perfect synchronization with the player movement and the more little factors that are considered the more lifelike it all appears until the player (and sometimes event the programmer) forgets that the little pixel art moving around the screen isn’t really a person or an animal and is instead a picture being projected in perfect and elaborate lockstep to everything else already going on.

    The game kinda resembles a digital layer cake of geometric planes. For our purposes in discussing the NPC challenge, there are three key layers: 

    1. the player layer on top which is little more than a picture (that never actually moves anywhere) of a little dude moving his legs or whatever, 
    2. the room plane on the bottom, which is a grid map to which every square of a matrix of about thirty by thirty is bolted an image of a single floor tiles or a single wall, maybe a single decoration or a single object, or aything else that doesn’t move, essentially a thousand times over to form a literal gridded map that comes together to make the picture of what looks like a furnished room, and 
    3. an NPC plane upon which the in-game life-forms persist through time and are continually moved  from square to square like upon an invisible chess board, revealed when they are in the same room as the player or hidden when not.  

    When the player moves anywhere—around the geometry of a room or through a door to another room—both the room plane and the NPC plane shift around on the screen.  It’s as if—to go back to the chess analogy—you were holding your player piece still in your hand just barely above the board and someone was shifting the board around under your piece.  And then you held your piece in the air while they swapped everything out for a new board from another game, over and over, every time you made your move in one game, swapping to the next board, for thirty five different boards. 

    Convoluted, huh? 

    It really kinda is, and so you see the challenge I faced.

    how does this all work, really tho?

    Like everything, though, I worked through this incrementally.:

    Can I spawn that middle layer? Yup.

    Now, can I spawn an NPC sprite onto that middle layer independent of the other two layers? Ok, that works, but it doesn’t move relative to the player.

    Okay, so can I make my NPC sprite seem to stand in one spot in the room? Yes. I lock the coordinate geometry of the NPC plane to the plane of the room.

    Next I need to make it move around realistically relative to the room, so can I do that? Well, I add a coordinate path vector and loop through that moving the NPC around on its own plane while tracking its progress along the track.

    Okay, can I do that with more than one NPC in different rooms? Sure. Add a conditional loop to spawn a second NPC linked to a different room id.

    Oops, now both NPCs appear in both rooms, each following their own path, can I fix that? Of course. I trigger a check and change in visiblity when whenever the player moves rooms. 

    Great, but now how do I interact with my new NPCs? Um. One more system to check if the player and the NPC “collide” geometrically in game plane maths and then pass that state along to the rest of the game to await further instruction.

    Yikes. It works.

    The result of all this is a complex—but actually robustly elegant-ish—tool that lets me spawn as many NPCs as I may need in the game simply by adding new “data” to a file with some simple starting and trigger variables. I even tested having 250 spiders walking around one room just to check and it seemed pretty solid.

    The whole process of building this game has been something like this. 

    Ask a question, then increment through the solution until something works, then refine until it works well. Then move onto the next question.

    Game design, huh?

  • error, error on the wall

    I reached an interesting point in the development cycle that necessitated that I learn more about the root of the application.

    If that sounds a little sketchy for a programmer to, you know, not fully grasp the intracacies of the main() loop of the software, keep in mind that for most every simple program the main loop is simple, too. And even for a Bevy application, most every simple app you can build in that game library (or importantly for this anecdote, every online code sample) follows the same basic and simple structure: add a system to initiate, then start up, then update and run.

    And while up until now I have been building a pretty complex little game, the system upon which it runs has been very simple: Launch the game and the game launches. 

    Except, that’s not how games usually work. 

    You usually launch the game and at the very least a title card appears, and then often a main menu. The main menu is, of course, the important part.  And in game design speak, the main menu isn’t part of the game-proper, but a kind of pre-launch state.

    And similarly, another task I had set for this milestone was building an in-game menu.  Both of these things are part of the capital-G Game, but they are not part of the game, if you follow.

    In other words, I had to learn about game states, and the whole complexity in my main.rs file of conditionally running bits of the application depending on a game state. 

    And all this started off okay, too. I found some code samples, and dug through the API docs, and started building. And then? Then, well, I added a function to trigger the game state to switch to the menu state and put it into my game loop.  That’s to say, there are a bunch of little functions that are run over and over and over again, updating the graphics, checking the keyboard for input, monitoring the location of the character on the screen, etc, etc, and I needed to add another one that would check to see if the key that opens the menu had been pressed (and if so switch that game state over to the menu mode).

    After everything I’d built it was a simple little keyboard check, except when I ran the application I got a strange error:

    trait bounds were not satisfied
    
    rust error E0599

    Okay.

    I searched online. I dug through the API for the input commands I was using. I even asked ChatGPT for some ideas about why I might get that error from the very simple code snippet that I showed it.

    No help anywhere.

    Now to be clear, this little game I have been making is starting to get very complex. Lots of moving parts. Lots of systems that run sequentially or simultaenously or (now) conditionally.  And the game loop consists of a long list of check_this, animate_that, move_littledudearoundthescreen-type systems.

    I spent two hours digging and prodding and simplifying my new function. 

    No use.

    Then I tried putting in some code that I knew worked from another function, I mean, not just adding but completely replacing that new fn call temporarily with a different function’s guts.

    Nothing.

    And then I did something that any good debugger worth his salt should probably do: I started methodically flipping switches until the problem disappeared. And—well, that’s the odd part. The first switch I flipped, that is to say, the first thing I turned off—which happened to be an animation function—fixed the whole damn thing.

    It just suddenly worked—well, except for that animation function.

    Was something wrong with the animation function?

    I tried flipping the animation back on and then flipping something else off in it’s place, just to see.

    Now? Now the animation was working but the picker highlights were off and yet it still all (minus the picker highlights) worked without that error.

    So, naturally, I turned everything back on and—Error.

    Look. I had a hunch. There had been something I was suspicious about and yet no matter where I looked (or what AI bots I asked) I always got the same answer:

    How many systems can I add to an Update’s parameters. —I would ask or search or troll through message boards seeking a clue about.

    There is theoretically no limit.” —was always the answer.

    Except. And here is the suspicious thing—remember how I mentioned that my app was (up until now) pretty simplistic? Yeah. So, when I say simplistic what I’m really saying is that I had neither organized nor really done any management of my function groupings.  In fact, prior to adding that function that broke everything, my .add_system(Update… parameters for my game loop had exactly twenty functions being called from it. 

    My menucheck was number 21. 

    I spent a solid forty-five minutes breaking things up into categories and smaller chunks.  Add the room systems. Add the animation systems. Add the input monitoring systems. Five systems in one, eight in another, and so on, and so on, until there were those same twenty one orignal systems that had broken my original scheme but now organized into four separate Update calls.

    And?

    Well, I wouldn’t be writing a blog post about it if it hadn’t worked, now would I? I don’t know for sure if there is a function limit specifically or maybe if there is a character limit for the parameters, or if I tripped over some other invisible fence but whatever it was I seemingly had breached it and caused an error.  

    If you have come here to read a programming anecdote, that’s it. That’s how this works. That’s how a guy can bang his head on his desk for four hours on a Sunday afternoon trying to puzzle out something simple and yet completely unobvious, something that no one thought to document because programmers with more experience, maybe, would naturally organize things a bit more meticulously.

    Or, if you have come here because you are searching for a solution to that same problem and because I have helpfully copied the error messages and codes verbatim into the text to assist you with you own struggles, then cool. I hope this helps. And then drop a little love and check out my game.