Tag Archives: opponent creator

Streamlining

                I made a fair bit of progress on the boxing game today and implemented a major change that should make for a better built program. In short: I switched opponent behavior from a threaded timer-based system over too one which uses the WX Timer object. In long:

                When I first started designing the game, I built a system which queued up all of a round’s behaviors at one time. Each of the punches, taunts, and unblocks basically received their own alarm, and when that alarm went off, the event attached to it was triggered. While the program ran smoothly  enough, it always gave me a huge number of trace backs—or errors—every time I prematurely shut it down. Each of the separate alarms was known as a thread, and when the program was closed, any threads that hadn’t yet been executed were cut, resulting in an error message for each one. I’m not certain if this really did anything bad, but it sure looked disconcerting when it happened.

                Partially because of this, I switched the program over to a new system today. Using a module called WX, I built in support for a single recurring timer that will handle all of my event management rather than placing the responsibility on dozens—sometimes hundreds—of separate timers. This single timer runs every tenth of a second, and when it runs it makes various checks to determine whether it should throw a punch, taunt the player, adjust fatigue and health, end the round, and a whole host of other functions.

                The second benefit to this new system is that it allows for on-the-fly changes to be made, including the aforementioned behavior system that people asked for. Because all behaviors aren’t laid out at the beginning of the round, they can be changed as needed.

                In order to really test things, though, I need to go back to the opponent creator and start building in support for the new system. In fact, I think I’ll start that now.

Rewriting the Future

                One of the biggest stumbling blocks I tripped over when the boxing game came to a screeching halt was the opponent creator. I know people are really excited about that feature; I am too. When I tried to conceptualize a system, though, I found that it kept getting progressively bigger and uglier, and after a while I didn’t even want to deal with it.

                The problem, I think, lay in the design of the program. When I conceptualized the opponent creator, I had a continuous timeline in mind. Users would jump into the timeline, place their events, tweak everything so that it was just the way they wanted, save the character, and share it with whomever they chose. I quickly found, though, that people didn’t like this approach. They wanted to be able to create their own combos, build in AI, and perform lots of other functions that I had never even considered. Many of these ideas were good ones, and I thought it would be fun to implement them. In trying to do so atop my existing code, however, I created a Frankenstein mess that quickly became untenable. I had built the system for single events, not combos or AI or anything of the sort, so the system couldn’t easily handle the new suggestions.

                So I’ve decided to do a bit of a rewrite, and it’s going to require messing with some of the existing engine. Here’s what I’m changing and what you can expect.

                The current setup provides for two opponent conditions: blocking and not blocking. (Eloquent, I know.) When the opponent is blocking, you can’t hit him; when he’s not, you can. Sounds complicated, right? Well … kind of, yeah. One of the things people asked for was the ability to create different opponent behaviors depending on how well or poorly the opponent is doing. If the opponent is winning, perhaps he’d like to go in for the knockout. If he’s losing, he might put up his guard, and therein lies the problem. If the opponent blocking means he can’t be hit, then when the opponent goes on the defense, he is nearly invincible. Using the current system, the only way to avoid this problem would be to have the opponent come out from behind his guard to throw punches from time to time, a behavior that would be at odds with his defensive nature.

                In the current system there are three ways to land a punch on an opponent:

  1. Hit him while he’s swinging at you.
  2. Hit him after you dodge one of his punches.
  3. Wait for him to drop his block, then sneak in a few punches. (more on this later)

All of the above factors conspire to create a game where the player is completely dependent on the opponent for his or her openings, which ostensibly makes this game a rich, detailed Bop It. Not cool!

                The other issue that currently exists is one of stamina. Like the original Punch-Out! from which this game draws much of its inspiration, I had programmed the player so that he would lose fatigue for punching at a blocking opponent, but he would not lose any fatigue for landing a successful hit. Why? When I look back on this setup, it doesn’t really make sense. You can get just as tired hammering nails as you can from swinging a hammer at nothing, so why do you not lose stamina for successfully landing a punch? If I wanted to fix blocking, I realized, I needed to fix this too.

                After banging my head against these issues for a while, I finally decided that the root of the problem lay in the opponents’ ability to become instantly invincible. If the opponent couldn’t block every single punch thrown at him, I reasoned, he could start adapting to different emotional situations without the unfair advantage of becoming a walking tank. With this in mind, and drawing inspiration from many of the mainstream games of today, I’ve started working on high and low blocks as an alternative. If an opponent is blocking high, he can still be hit low. The reverse is true if the opponent is blocking low. This will enable players and opponents alike to adjust play styles depending on how aggressive or defensive they are at any given moment.

                But then comes the issue of stamina. Since it’s now possible to land many more punches, there needs to be a check in place that will keep the player from simply unleashing a torrent of key presses and battering the opponent into the ground. Thus, the new system will subtract stamina for both successful and unsuccessful hits, meaning that it won’t be advantageous to just slug away …

                Or will it?

                That’s all going to depend on the third major facet currently in the planning stages, statistics. Perhaps you’d like to be a bruiser with a take no prisoners attitude. Or maybe you’d rather be a calculating, careful fighter, using your mind and your reflexes to solve the sweet science. Perhaps you’re just a glutton for punishment and can’t avoid getting punched in the face to save your life—or at least your career. With customizable stats in place, all of these should be possible.

                My current plan is to have four trainable stats: strength, speed, stamina, and vitality. The player will have the ability to train a few stats at the start of the game, and will gain additional points for participating in fights. This means that if you find yourself getting too tired during fights, you can use your training to improve your stamina in order to stay on your feet longer. If you know the next opponent is going to dish out some serious damage, you might consider dropping a few points into your vitality as a precautionary measure.

                Finally, there’s the opponent creator I mentioned at the top of the post. People want combos, and they want the ability to create situation-based events. I want to give them these things, so here’s what I have in mind.

                Instead of having a timeline to cover the entirety of the match, complete with too much scripting, opponents’ behavior will be based solely on combos. The game will choose from a set list of combos depending on the current situation—offensive, defensive, normal, etc.—and one will be chosen and executed. The nice part of this system is that it can create as much or as little complexity as the creator chooses. If you want to create a completely predictable opponent, only design a few combos for each situation. If you want someone harder to predict, you can design dozens—even hundreds—of combos, and the game will just choose from a larger set. Combine this with the already-existing ability to create punches of random height and side, and you have an extremely flexible system.

                Many of these features are still in the design phase, but I firmly believe that, once implemented, they will combine to create a much richer, more satisfying game with greater replay value. By giving people a more detailed fighting system and a thorough opponent creation utility, I hope I can create something that many of you will be excited to play.

                Before I can make any of this happen, though, I need to look through the old code, find out what needs to be kept and what needs to be scrapped, and make the necessary changes to the underlying infrastructure. It’s going to take a lot of refactoring, a lot of proofreading, and a lot of coding. I know. I’m excited too!

Changing the Rules

                Years ago I used to run around the neighborhood with the local kids and play some variant of “guns:” cowboys and Indians (we weren’t racially sensitive), cops and robbers, spacemen versus other spacemen. Even though most of us were on board, there was always that one kid who just had to bend the rules a bit.

                “Hey,” you’d yell, blowing imaginary smoke off the barrel of your plastic revolver. “I shot you!”

                “Nuh-uh,” he would always return. “I was wearing a bullet proof vest.”

                I understand now, after a hasty Wikipedia search, that bulletproof armor did in fact exist during the 19th century—at least as far as Wikipedia claims. According to the article, it existed some 300 years before the Civil War. But as kids, we and the bulletproof wannabe thought of ballistic vests in the more widely recognized, modern sense. As far as we were concerned, he was cheating, arbitrarily changing the rules when the game was already in progress.

                I always look back on my body armor memories and smirk when something completely new and unexpected comes along to shake things up. (By the way, My Body Armor Memories would make a great band name. Feel free to use it.) In the case of programming that game-changer was decimal numbers, referred to in computer parlance as floating point numbers. As far as your computer is concerned, writing floating point numbers is hard. The mechanics of why this is the case are a bit obnoxious, but suffice it to say that when you see 0.1 on your computer screen, the computer isn’t thinking of the same number. If I assign the number 0.1 to the letter x, then tell Python to print x, I’ll get a nice, pretty 0.1. If I tell it to print 0.1 to 25 decimal places, though, I get 0.1000000000000000055511151. This difference of numbers can cause major trouble in coding if you’re not aware of it, and just like my cheating neighbor, it caught me completely off guard.

                In trying to program the opponent creator, I designed a system that checks the time an event is scheduled to occur against the user’s current time. If the two numbers match, a sound is played, and the user can edit events. When I tried to move a tenth of a second at a time, however, I found that my comparisons weren’t matching up. I tried to debug the code with print statements, and things looked like they should have worked.

position 2.8
position 2.9
position 3.0
position 3.1
Event placed!

Even when I pressed the right arrow, then pressed the left arrow to return to 3.1, things looked like they were working.

position 3.2
position 3.1

                But at 3.1, I should have received a message that said “sound method called.” I didn’t, and the reason, as I discovered after 8 days of struggling with the code and obtaining tips from experienced programmers, was those blasted floating point numbers. A simple print-out of the three punches I had entered shows why.

{3.1000000000000014: {‘punch’: {‘strength’: 0, ‘height’: ‘head’, ‘can_stun’: False, ‘can_break’: False, ‘speed’: 1, ‘side’: ‘left’}},
2.1000000000000005: {‘punch’: {‘strength’: 0, ‘height’: ‘head’, ‘can_stun’: False, ‘can_break’: False, ‘speed’: 1, ‘side’: ‘left’}},
1.0999999999999999: {‘punch’: {‘strength’: 0, ‘height ‘: ‘head’, ‘can_stun’: False, ‘can_break’: False, ‘speed’: 1, ‘side’: ‘left’}}}

                When I enter a check between the time of an event and the user’s current time, they will never match up, because in no world is 3.1 equal to 3.1000000000000014. But completely unaware of this oddity in computer programming, I scanned through my code perhaps a dozen times, grew incredibly frustrated, and even considered a complete re-write. As Christopher Toth later told me, “This is the kind of thing that makes perfectly sane programmers gibber in fear.” How right he is.

                The code is working properly now. I found I could overcome the problem by rounding the floating point numbers I encounter, but the solution was a long time in coming. I never realized when I started out that some of the hurdles I would face in learning to program would require a grappling hook and a spotter to overcome. (This situation also shows why I do not give release dates or accept pre-orders.) Even so, the trial is passed, and I have some talented programmers to thank for it.

Tangling with Inertia

                I didn’t know it could happen, but it appears it has: I am at a point in my code where I cannot independently think of any way to fix what is wrong with the creator. No matter how often I look through the code, no matter how much tweaking and debugging I do, I am absolutely stuck. I am waiting to hear back from people with much greater experience in Python than I, but in the meantime, I cannot go forward.

                Strictly from a personal standpoint, this doesn’t bother me. I understand that this is just one more hurdle to overcome in the grand scheme of learning to program. But from a development angle, it means I’m not working while I wait for feedback, and since I’m not working, it comes as no surprise that no progress is being made.

                I have pondered the idea of working on secondary projects as many developers do, but I’m not sure if this is a wise idea in my situation. Many of the developers I know design and code for several hours a week, whereas I do this in my spare time after a full day of work. That’s not to prop either practice, but it does mean that if I split the two hours a day I have to code amongst many different projects, the little time I do have will be spread rather thin. Perhaps that’s a good thing, as it will keep me from getting bored or frustrated with a single undertaking. On the other hand, though, it waters down my focus in a time when I have too little focus to give in the first place.

                What would you all do? Would you work on more than one project at once or would you bang your efforts against a particular obstacle until you manage to break through? All opinions welcome!

Much ado about … What?

                Randi mentioned in passing yesterday that it has been a lot of time since I wrote my last blog post. When I look over the progress I’ve made—or haven’t made—in the past 9 days, though, I can see why. Still, it has been an interesting thing to ponder.

                The beauty of Twitter and microblogging is the ability to make insignificant things sound more important. You might not write a whole blog post on what you had for breakfast, but you could fill 140 characters with that information. (Note: doing so, in my opinion, is really silly. People generally don’t care what you had for breakfast unless it was a plate of duck embryos.) Twitter is handy for those smaller thoughts one has; in my case it’s handy for the smaller updates. If I get a particular facet of something working, that’s worthy of a twitter update. If I finish a whole system, though, I’ll write it both places, and the blogged version will be fleshed out and thorough.

                I can see the other side of it too, though. Before Twitter, when places like Miriani and Star Conquest had online change logs, I would read them religiously. I would log on to them day after day in the hope that something new and exciting would be posted. When there wasn’t something new that day I would be disappointed. Now that I’m posting my own version of change logs, though, I understand why new content wasn’t forthcoming on a daily basis. I managed to get the timeline view of the opponent creator working on Sunday. I started writing a few dialog boxes. I don’t know that I could stretch that into 300 or 400 words worthy of a blog post, though.

                All this is to say that even when this blog isn’t updated, I am still working on the game. If you want more frequent thoughts and updates, GMPUpdates on Twitter is the place to check. If you don’t mind waiting between thoughts and developments, you can check this site as often as you like. I promise I won’t go dormant on anyone.

                In the meantime, though, I have an opponent creator to finish.

Update on the Opponent Creator

                I’ve been hard at work on the opponent creator, and while I’ve made progress on it, it’s nothing that really lends itself to a lengthy blog post. So instead, I’ll give you all a run-down of what you can expect from the program to whet your appetite.

Why design an opponent creator?

                An opponent’s punch has a number of factors: time of occurrence, speed, strength, height (head or body), side (left or right), whether it can be interrupted, and whether a player can stun the opponent if he manages to dodge the punch. That’s 7 arguments just for the punch. Then there’s the unblock method which determines how long the opponent drops his arms and whether punching him during this time will yield up an ultra punch. When you think about the fact that between punching, taunting, and unblocking, I have to design over 100 events per round with all their associated parameters, you start to see how big an undertaking this is. In fact, hand-coding the first round of the test opponent took well over an hour.

                Part of the reason I want to build an opponent creator is for my own sanity. If I can design something that will enable me to cut down on production time, so much the better. Beyond that, though, I want members of the community to have a crack at designing their own opponents and contributing them to the project. Everyone loves expansion packs.

How it Works

                I envision the opponent creator as having two distinct phases: a timeline that creators can navigate to place punches and taunts, and an input window where said data can be entered. Players will use the timeline to jump from tenths of seconds to whole minutes either forward or backward, and it is here that they will press different keys to launch the input window. The timeline will also have a playback feature that will allow designers to hear the opponent’s half of the fight in real-time.

The input window will be a simple form with boxes for speed, strength, height, side, and so on. When the designer clicks the “OK” button, the behavior will be inserted directly into the timeline.

 When the opponent is complete, its creator will save the timelines for the 3 rounds as a file which they can distribute to friends, integrate into their own game, or send to me for possible inclusion into expansion packs. My hope is to make the design and distribution process simple enough that anyone will be able to use it.