Archive

Monthly Archives: May 2015

EveHeader

I’m super ready to be not working on pathfinding any more, but it keeps not being done. What was supposed to be a couple of weeks of work has turned into about a month of noodling. I feel like I learned some stuff, but still. It’s frustrating.

As far as I can tell the navigation map generation is done – but I thought it was done once before, so I’m prepared to be unpleasantly surprised. Mostly what’s left, though, is working on the movement code for the entity, making sure it makes all of the jumps properly, making sure it doesn’t get confused about where it is and stop moving, making sure it doesn’t break when trying to jump from a weird angle, etcetera. In addition to those big tweaks, I also need to do a bunch of smaller ones, less vital for the navigation of the levels per se but more to tune up the feel of the movement — little pauses in between jumps and landings, a bit of acceleration and deceleration, just whatever I can think of to make the enemy’s movement more fluid, with more character

At the same time as I’m working on enemy movement in the programmatic sense, I’ll also start working on animating the movement of the sprite. This should provide some much needed relief from incessant pathfinding programming, as well as making the enemy come to life in a much more concrete way.

This has definitely taken too long, but so it goes. Hopefully once I get past this swamp I can start to build up momentum again.

exMachina

What obligation do we have to our creations?

In the film Ex Machina, the character Nathan, designer of an apparently fully conscious artificial intelligence, is shown through the story to be abusive to his creations, a tyrant, a monster. He is willing to murder and abuse his ‘children’ without remorse. And how subtly he must have shifted, from software engineer, to hardware developer, to father, without ever knowing where the line between each was, without ever becoming aware of when his pragmatic approach to development became an abusive approach to fatherhood, when he stopped treating objects like people and started treating people like objects. What does it mean to be a software developer when every revision and every rollback is intrusive, a lobotomy? When does it turn from maintenance and upgrades into surgery?

It may be many years, or it may never be, that we create a thinking machine – but, perhaps, long before that point we will find ourselves as abusers, violating our never-understood obligations to what we create. How do we know that we aren’t already?

What about characters? Characters are a kind of artificial intelligence, a mind emulated through the mind of a writer, or simulated in fragments by an audience, layered through multiple interpretations, projected in quantum superposition through the mind of a crowd. Is it really okay to do whatever we want with them, to make them suffer or die, all for the purpose of parable? Does it start off as okay when we write it, but become more unethical as our audience grows, as the simulated intelligence of the character becomes more robust and runs on more client minds, becomes more independent of its creator?

As customers clamor to declare creators are obligated to them, and as creators defensively affirm their obligations to themselves, it’s perhaps worth wondering if the creator has an obligation to the creation, itself – aside from any agency or perceived agency on part of the creation, is it important to respect what we create, to treat it with dignity?

There may be no answer to these questions. This may be a paradox, created from a superstitious belief in something called ‘consciousness’, separated from the universe of objects and machines by a cloudy barrier.

Well, whatever. Whether or not there’s a self to be aware of, we have created the concept of self-awareness. Regardless of whether we are separate from the world in our perception, we are certainly separate from it in our capacity for targeted creation. And, whether or not the things we create ever become like us, in some ineffable way, whether they become the artificial children we’ve always wanted, to live vicariously through, to shore up or manifold imperfections – no matter what we make, it is an extension of us, and when we share it it becomes an extension of others as well. We are all connected, even weird loners like us, like me.

So be kind.

EveHeader

Slow but steady progress this week, finding little bugs in the nav map building functions, introducing and fixing problems in the jump trajectory projection, and writing the code to interpret the navigation path and make the entity follow it. It’s not quite done, but it’s getting there.

PathfindingTest00

It looks pretty solid in this example, but unfortunately there’s a lot of cases where it doesn’t work so well. In particular, if the character is directly above the entity the entity has a very difficult time navigating to her, mostly because it tends to hit its head trying to jump up, fall back down, and find itself not in the place it expected to be. Still, I’m now in the very desirable stage where I can see what’s going on, test it with different values, and gradually fix it up until it works right.

Well, it’s desirable in the respect that the process is a lot more hands-on and intuitive now, but less so in the sense that I’ve spent like three weeks working on this now and I’m getting a bit burned out on it. Hopefully, this will only be a few more days of work, and then I can start adding animations and more sophisticated behaviors to this entity to make it really come alive.

MonsterChase

There’s an issue I’ve noticed comes up a lot in game design, particularly when it comes to balancing items and abilities against each other: The differentiation and conflation of absolute and relative values.

Here’s the first place I noticed it: I haven’t really played Crusader Kings 2 myself, but I was watching someone else play it and he was talking about one of the traits an army’s general could have, ‘experimental’. This trait makes it so in each encounter the commanded army is at 50-150% strength, or +/-50% of the normal strength. This seems reasonable at first: You’re gambling, and if you win you get 50 and if you lose you pay 50. However, the problem with this approach becomes clear if you experiment with increasing the numbers: Say +/-100%. With these values, on an exceptionally lucky roll you’d be at 200% power, and able to fight an army twice your size, which is a pretty nice bonus to be sure. However, on an exceptionally unlucky roll you’d be at 0% power, and would lose to an ‘army’ of three asthmatic soldiers with one sword between them. These are not even close to equivalent, and the same is true of a 50% power army, which would lose to an army half its size, and a 150% power army, which would lose to an army 3/2 its size.

It’s easy to gravitate towards tradeoffs that are balanced in absolute terms, because they’re simple and easy to understand. 50% is 50%, right? Conversely, calculating the relative benefits/tradeoffs, while not exactly advanced mathematics, is a non-trivial step. Rather than merely looking at how each upgrade or drawback relates to the norm, you have to start looking at how it relates to every other upgrade and drawback, which can become overwhelming.

It’s important to keep in mind the relative vs absolute benefits of a given upgrade or downgrade at all times, and it can lead to unpredictable results. At first glance, it seems like the engine upgrades in FTL give you diminishing returns, starting at 5% dodge chance and eventually going down to a piddling 3%, with the final upgrade popping back up to 4% for whatever reason. However, given the relative dodge value before and after upgrades, it turns out that that last 4% is actually one of the most valuable of all the upgrades

FTL Dodge Chance

Another striking example lies in Diablo 2, in which the Necromancer class has a curse called amplify damage which reduces damage resistance of enemies by 100%. In early areas, this has the effect of doubling damage: A useful ability to be sure, but roughly equivalent to the other, mutually exclusive, curses at his disposal. However, in later areas, where enemies had some existing resistance to damage, this curse became incredibly powerful: An enemy with a base resistance of 95% damage would now take more than 20 times the damage they would normally. Many other skills in Diablo 2 have diminishing returns as they increase in level, while those which boost damage passively do so at a consistent rate of 5% per level, content that as that level increases those returns will diminish naturally. After all, the difference in scale between 200% damage and 205% damage is only half the difference between 100% damage and 105% damage

That’s not to say that all tradeoffs should be based on relative values. If a player has the ability to gamble resources with an expected payout of either losing half their resources or doubling their resources, it will almost always be in their interest to gamble, since it will take them half as much time to recover their lost 50%, in the case of a loss, as the time they would save collecting the same amount again by winning. As a general rule of thumb, if the player is making a big one-time decision, a strategic decision that will change their abilities or a one-shot opportunity to gamble on a resource that is extremely scarce, the benefits should probably be scaled relative to the penalties. However, when this is a frequently made decision where the stakes are low and renewable, the investment and payout should be balanced in absolute terms, a penny for a penny, to keep the system from being game-able.

bartmath

The other big concern is thresholding. Not all bonuses or penalties are equal: if the most common or troublesome enemy you face has 100hp and you do 99 damage, a 2% damage upgrade becomes far more valuable than a 1% damage upgrade. This can get really tricky, and requires paying a lot of attention to the specifics of numbers.

This is something of a contentious example, but I think this is a big problem with the weapon The Enforcer in Team Fortress 2. This is a weapon for the spy which has a +20% damage bonus at the cost of firing 20% slower. On paper this doesn’t seem so bad – possibly even slightly underpowered, since it should have 96% of the damage output of the normal revolver which it is an alternative to – but in practice this ends up being a big problem for a few reasons. First, the damage bonus for this weapon makes it just powerful enough that at close range two shots will do 132 damage, enough to kill 4 out of 9 classes, since the standard is 125 hp. So first we have a thresholding problem, which makes it clearly superior to the stock revolver. Second, in terms of actual practical use, it’s extremely uncommon for a spy to actually fire their revolver as quickly as possible, usually trying to pick shots carefully to make sure they land, so the speed penalty is barely a factor. Third, after the stock revolver, it’s in competition with the spy’s other revolvers, all of which have damage penalties to make up for their other abilities. So, relative to the Diamondback and Ambassador, which both have a -15% damage penalty, it does +41% damage. Compared to the L’Etranger, which has a -20% damage penalty, it does +50% damage.

So the point I’m trying to make is that numbers are tricky. You can’t balance a game based on percentage increases and decreases without looking at how each option is positioned relative to each other and its place in the greater design of the game. Pragmatically, most of these situations have a way of working themselves out, either via balance patches or players finding ways around the problem or simple word-of-mouth spreading that this option which seems useless is actually quite strong. Still, it’s something worth considering.

EveHeader

Pathfinding is getting close to wrapping up I think. I’ve got the path selection algorithm working, and I think it’s properly detecting when there’s something blocking a chosen path and redirecting around it just as it should. However, testing has revealed some flaws in the initial generation of the level navigation map, with some ground nodes not connecting to others which they logically should, and sometimes connecting when they shouldn’t as well.

With another day or two I should be able to fix that problem and make the nav map as perfect as I thought it was until a couple of hours ago. After that, assuming that doesn’t lead me to discover a new algorithmic problem, I move on to stage three of pathfinding, which will I think be the easiest: Taking the waypoints generated by the pathfinding algorithm, giving them to the entity, and having the entity use them to traverse the level. I’m kind of wondering whether it would be better to have the entity actually moving and jumping like the player character does, and hope that all the calculations are accurate enough that it doesn’t find itself obstructed in an unexpected way, or to just generate a high resolution series of interpolated waypoints and just move the entity along that like a roller-coaster track, playing the appropriate animations to make it look like it’s moving the normal way. The latter definitely seems less likely to break, but more likely to look weird or conflict with something else.

I guess probably the way to go is to start out doing it the legit way, like an AI-controlled little player navigating the level, and then if that doesn’t work well I can keep the track-path method as a backup. In any case, I hope to have these guys moving around by the end of the week, at which point I can go in and add a bit more nuance to their behavior and start working on their prototype animations for real.

 

DarkSign

Dark souls is frequently described as masochistically difficult. I don’t think this is very apt: Masochism implies a state of being acted upon, of being made to suffer by an outside force. Dark Souls never makes you do anything, only invites you to do it to yourself. Dark Souls is a raw onion, a bottle of sriracha placed suggestively next to the sandwich fixings on the table. Nothing is required of you, but the challenge is implied.

The distinction becomes clear when you compare it with other games described as masochistically difficult, such as I Wanna Be The Guy. IWBTG acts upon the player, manipulates their expectations only to betray them. It pulls the carpet out from under the player, instead of laying out a carpet of spikes and inviting the player to walk upon it. Dark Souls isn’t hard just to fuck with you – well, usually. It’s hard because that difficulty is the only way to convey the oppression and disease that is endemic to the story it is trying to tell.

Dark Souls is a game that shows more than it tells, but it’s also a game that listens more than it speaks. Playing most games is like a conversation with someone who you can tell is listening to you just long enough to construct and express the thoughts that are in their head. They tell the player who they are, how they act, why they’re there, and why that’s awesome. Dark Souls is content to let the player be who they are and act as they will. It doesn’t care why they’re there, and it doesn’t think that it’s particularly awesome that they are. It just presents itself, and waits, and lets the player occupy that space in whatever way suits them.

The silence and withholding stoicism of Dark Souls isn’t just about minimalism or about telling a story through gameplay, it’s about giving the player room to make that world their own.

Games lost something for me when the characters started talking — at first in little yips and exclamations, then in progressively longer-winded cutscenes. The more they talked, the less room there was for me. When a character speaks through text lines, we’re still part of the process, we’re the reader, the interpreter, parsing the sequential art and the dialogue into a coherent narrative. As technology has progressed, as we’ve been able to add more life and detail to our worlds, we’ve reduced the ability for our players to invest them with a life of their own.

I think part of the reason why people think of Dark Souls as a vaguely retro, old-school game, isn’t because of its punishing difficulty, or its structure, but because it’s willing to shut the fuck up for a moment in the way that those games were pragmatically required to by the limits of technology.

The only part of Dark Souls that never shuts up is the people who love it.

Fuckin’ Dark Souls, man.

EveHeader

Spent all week working on pathfinding stuff. This is, realistically, probably something I shouldn’t be spending this much time on. I’m getting sidetracked. Still, getting sidetracked like this on difficult but interesting problems is good for me, at least in small portions. It helps me keep on learning instead of settle into the same grooves, makes me in general a better artist even if, in specific, a bit worse at producing this specific piece of art. So I don’t begrudge myself the time.

As I understand this problem now, it’s basically split into three parts: First, mapping the terrain. Though the terrain is already in a format easily read and perfectly suitable for simple interactions, understanding the layout of a whole bunch of undifferentiated tiles is something that’s difficult to teach a computer to do. This is mostly what I’ve been spending the last week on, putting together the best map of the terrain I can, as detailed as necessary without any false or extraneous information. This is what it looks like now for a simple level:

Pathfinding02

The lines show where each node is looking for possible connections for where to move next. Note that the nodes underneath the platform don’t try to connect directly to it, since it would be impossible to reach there with the solid platform in the way. Unfortunately, for a more complex level this map takes about a second to generate, which is too long to do in real-time every time a level is loaded. Thus, I’m probably going to have to make these nav maps get saved alongside the map tile data, and just get generated whenever the level is modified or loaded.

So that’s the first part. The second part is finding a path through that map, getting from the start tile to the goal tile. This is what I’m working on now. To start with it’s simple enough, just chain through the connected nodes and find the closest to the start and the goal, and continue until you either reach the goal or fail to do so. That’s the part I have done. The tricky part is that in between each connection I need to make sure that the path isn’t blocked, which means projecting the character movement as they walk or jump from one block to the next, make sure their jump is powerful enough to bridge any gaps, make sure that when attempting to jump across they won’t be blocked by the terrain. That parts a bit complex, and is what I’ll be tackling tomorrow.

The third part I haven’t tackled at all yet, and that’s converting the path through the level into a set of instructions for the entity to move through, and making sure it executes them perfectly enough that it doesn’t, say, miss a jump and fall into a completely different part of the level and generally muck things up. I don’t think that part will be too hard, but I’ve certainly been surprised by that sort of thing before.

I’m hoping that within the next few days I can have a simple case of this running, a basic enemy that just follows the character around using this pathfinding algorithm, before I built it out into something a bit more nuanced. Either way, once I have this, if I do it right it’s something I should be able to use for years to come, for basically any game built on this same kind of 2d platformer movement system. Implementing enemies in general will become much easier in the future, since I can just pass all level navigation tasks down to this algorithm.

I ran out of time and the work I had wasn’t coming together so no post today. Here’s another compensatory music that I made last month.

EveHeader

Progress has been going slow, but it’s progressing. I’ve been slowly building up the behavior code for this enemy type, but I realized a couple of days ago that I’m probably going to need a robust pathfinding solution rather than something kind of half-assed, so the last few days have mostly been research into how pathfinding works, specifically within the context of a 2d platformer.

I’ve got a pretty good idea of the kind of approach I want to use now. This is taking a long time and it’s been a week or two since I’ve made visible progress in the game. which is frustrating: But, the good news is that whatever I come up with here should be highly generalized and reusable for pretty much any 2d platformer I make in the future.

Here’s the algorithm I’m currently planning on using, (copied largely from the daily devblog, where I came up with this approach yesterday):

Step 1: When each level is loaded, generate a navmesh. This is basically just a fancy name for a grid with every ground tile marked, a ground tile being defined as any tile with a slope of 1 or less that doesn’t have a solid tile of some sort directly above it.

Step 2: Run the A* algorithm as described in this video with the start value of the ground tile beneath the entity and the goal of the ground tile beneath the player. Non-ground nodes are disregarded for parenting purposes, so ground surfaces are parented to whatever the last ground surface was navigated from to reach them rather than the closest non-ground tile.

Step 3: When a path is completed to the player, perform the following tests to make sure that it’s valid:

  1. Above each ground tile, ensure that there’s enough clearance above to allow the entity through. I realized today that I can speed this up by storing the available clearance above each tile in the navmesh generation phase.
  2. At each gap between ground tiles, ensure that the entity’s jump is powerful enough to reach the other side of the gap
  3. Ensure that, if jumping, the minimum-possible jump will not be obstructed. It doesn’t matter if the maximum jump is obstructed: If the minimum is obstructed and the obstacle is possible to jump over, it should have its own ground surface nodes that can be navigated by jumping and get caught in subsequent passes. This assumes that all ground surfaces are navigable.

Step 4: If any of those tests are failed, revert the path to its earliest failure point, mark that node connection as intraversible, and try an alternate path.

It’s entirely likely that I’ve overlooked something with this algorithm, but it’s a good solid plan to get started with.

FallingDown

America has a relationship with violence that is, let’s say, a little too friendly. That’s not to say that the American mindset is violent necessarily, that we are predisposed to do violence, but that so much of our outlook is defined in terms of violence. The distinction isn’t obvious, but here’s where games provide a useful demonstration: Most games are about shooting things, of course, and that’s partially habit and fashion at work, but when we make games about choices those choices are themselves framed in violence. To kill or not to kill, that is the question that so many games boil down to, even when they tout their freedom.

It’s not just games. We construct this dichotomy everywhere. Either suppress the riot with brutal force or do nothing. Either invade a country or do nothing. These are the nails for our hammer. Other solutions are not even dismissed, so much as never even considered. We have constructed a vocabulary of violence, of do or die, and forgotten that any words exist beyond it. Questioning the decision to use violence is similarly always contextualized as an argument to do nothing, “So you’d rather let the terrorists do whatever they want?” Ignoring the wide realm of options in between doing nothing and violent enforcement.

We question the necessity of violence, but rarely its utility. We have violence defined as The Thing That Works in our minds: If you can’t pick the lock you kick the door down, if the vending machine doesn’t work you knock it over, if the ants get in your house you poison them. For simple problems, sometimes it does work. But simple problems aren’t really problems, and by saving violence as a last resort we are frequently reserving our least effective option for our most desperate moments. This is most egregiously apparent when it comes to the many justifications our government has recently, shamefully, deployed in service of its ongoing torture and interrogation programs, violent acts which are of little demonstrable security benefit. People who defend these programs do so by balancing the lives of these torture victims against hypothetical lives saved, neatly eliding the questions of whether those lives are actually saved by these acts, whether there would be any more effective way to save those same lives, or whether more other lives are lost because of consequences of systemic state-implemented torture.

We American’s love justified war. Every narrative centers around it. He killed my family, so I can kill him now. He’s going to blow up a building, so I can kill him now. This is every fucking movie and every fucking game, the story of how the bad guy did a bad enough thing that it’s okay to kill him now, and the journey of how he and everyone who works for him gets killed by the main character, and maybe there’s some kind of prize at the end for doing such a good job with the killing. If it’s a kid’s show then instead of killing them he just beats them up and they do it once a week, each week a different justification for the inevitable ass-kicking. What’s the first thing everyone talks about doing with a time machine? Assassinating Hitler. Trying to prevent the greatest massacre in history by murdering someone. Not only is it unlikely to work, since Hitler was the product of his environment and someone would likely have filled his role if he weren’t there, but it’s also just one of many ways to approach the problem. Why not just sit him down and explain the tragedy that will occur if he follows his current course? Why not provide him another path in life? Why not get him into art school? Of course, it’s a bit galling to do favors for Hitler, but at the point where you would presumably contact him using your time machine he would not yet be Hitler, just one Adolf among many. More likely, a serious attempt to prevent the tragedies of the second world war wouldn’t involve Hitler at all, but trying to sow the seeds that unravel the national socialist movement before it gained its murderous momentum.

We so desperately want to kill Hitler, though. We so desperately want to be the unequivocal good guy kicking the shit out of the definitely bad guy, we will do whatever we can to construct those bad guys and turn ourselves into good guys. We want to win world war 2, over and over again, more than we want to prevent that war from ever happening.

This maybe sounds like some ‘won’t someone think of the children’ Jack Thompson horse shit, but this isn’t about the violence itself being damaging or immoral: It’s about the narrative we construct to say that our violence is justified — and I’m not even saying that it isn’t, that violence isn’t ever justified or anything like that, merely that boiling every conversation about the usage of violence to whether it is or isn’t morally okay in this circumstance is completely myopic and misguided. Sometimes the relevant question isn’t whether it’s okay to put a sledgehammer through your wall, but whether it’s useful for your goals.

People in power all over the world tend to have a child’s understanding of violence. Like gangsters, they want to ‘make a problem go away’, and by their lauded power and influence they believe that because they can make that ethical compromise that they should, because that’s the kind of big weighty decision that big weighty men make. Add to that a national desire to be the cowboy who wears the white hat, who everyone knows is right because he’s on the side of justice and has a shiny badge, and you have an explosive mixture. It’s just now starting to really mature, and the explosions are only going to get bigger.