05 December 2007

Physics R Phun

These nifty little physics-based puzzle games have shown up on various lists at work:

Launchball lets you place tiles with different properties to get a ball to the goal. Some of the tiles provide power, some use power and some push the ball in different ways.

Crayon Physics is another ball-to-goal game but you draw shapes to apply force to the ball or guide it along its path.

The guy(s?) at Kloonigames are working on a Deluxe version of the Crayon Physics games that lets you use shapes and constructs other than boxes:

Both are a lot of fun and very addictive.

04 December 2007

Head the other Direction

You won't catch me taking my kids to see The Golden Compass. It's based on Philip Pullman's series of books subtly training children to reject God and deplore religion. Philip Pullman is probably the closest to an antithesis of C.S. Lewis that you can find and has been called The Most Dangerous Author in Britain.

I'll stick with C.S. Lewis' great classics which have entertained children and adults alike for over half a century. Speaking of which, Prince Caspian is in post-production for a release in May of next year. I'll see that instead.

25 November 2007

A Decade of Ultima Online, Part 2

Since I have UO on the brain now, I think I'll list off some of my best memories both as a player and as a developer.

Player
  • My first character: a smithy/miner. This was back near launch in Oct 1997. Mining was tough because of player killers (PKs) and you always had more ore than you could carry, so you would have to set it on the ground and move it a tile at a time. Pack animals didn't exist yet so your precious ore was always in danger. Players actually paid me to fix their armor.
  • The first time I (successfully) went from a city to another city. When the game was very new the only map you had was a little mini-map in the game and the cloth map that came with it. Tools like UO Auto-Map didn't exist yet, so getting lost was the nature of exploring.
  • Dying to forest creatures. Rabbits and deer were merciless to new characters.
  • Sailing around the world. When I came back after a few years away, the first thing I did was buy a boat and sail all over. It provided hours of enjoyment exploring the world, with nothing to show except to be able to say I had been there.
  • Joining a guild. While I was wandering in the dangerous non-consentual-PVP world of Felucca, I met a nice guy named Alydar. We chatted for hours while killing creatures and discovered that we were both programmers. I had started writing some tools for UO and he was interested in learning the same things that I was discovering. He invited me to join his guild, the Defenders of Virtue. He became my mentor and later sent me on a quest to discover the Virtues in order to become a Knight within the guild.
  • Animal Taming. I tamed white wolves for hours to get my Animal Taming skill up, but it was all worth it the first time I tamed a dragon. Stealing the not-so-original name Trogdor, my dragon and I could solo Ancient Wyrms and Balrons.
  • Age of Shadows. With the help of my pal Alydar, I was able to obtain a house plot inside the brand new city of Luna in the new continent of Malas. I still own that house to this day and use it as a vendor location, allowing other players to set up vendors at my house. This expansion also launched with a critical bandwidth usage problem that eventually got me a job working on UO.
Developer
  • Fixing the bandwidth problem mentioned above in less than two weeks on the job. It was actually a very simple problem. The Age of Shadows expansion introduced real item tooltips to UO for the first time. Tooltips were always the same for everyone and had a global 'version'. Whenever something would change the tooltip was invalidated and the new version number would be sent out to everyone in range. This would cause all of the clients to request the new version. However, the problem was that tooltips were being invalidated whenever anyone new would come into range of the item. Instead of sending the current version to just the new in-range player, it would spam everyone in range when someone new came close. In busy areas the net traffic got ridiculous.
  • The Day the Servers (almost) Died. UO's player backup format is very prone to bloating the backup file with empty space. Someone made a change to the way player characters were stored that broke the compression utility that removed said empty space. Right before Christmas. Everyone was gone right before Christmas break started, and player backups on production servers were quickly approaching their 4GB limit, above which Bad ThingsTM happen. I had to make a very timely change to the compression utility and get the fix out to all the servers without dropping them by myself after having been on the job for about a month.
  • Fixing the 'insurance bug'. Targeting in UO is request/response. The server tells the client that it needs a target. The client then changes the cursor to a targeting cursor and sends a response back to the server when the player picks something. The server then fires a callback on the item that requested the target. The problem was that the item was determined from information in the target response, so the server was stupidly trusting the client in this respect. In most cases, the scripts that controlled targeting had their own "security" but it was up to the developer to script it in every case. In the case of insurance, the 'item' the callback fired on was the player requesting to insure/uninsure something and there was no security. Now the security of all request/response formats is ensured by the server at a global level.
  • Character Transfer system. I was pulled in to the character transfer team to wrap it up with my good friends Deathwish, AviStetto and MrTact. It was the last major feature that we did before Origin was dismantled and it was a lot of fun.
  • Moving to Redwood City. Although I miss Origin, moving to CA with EA has been one of the best things to happen to me, even though I really didn't enjoy working at EA nearly as much as Origin.
  • Fixing the 'chunk egg crash'. Each 8x8 tile section ("chunk") of the UO world has an invisible item called a 'chunk egg'. These are immovable (even by GMs) items that store all of the resources for the chunk (wood, metal, etc) that can be harvested by players. However, periodically these chunk eggs could end up inexplicably inside a moving crate in someone's house. The server would crash when the players would try to re-organize their house. The workaround was for a developer to go and remove everything from the moving crate, lock it down in their house and then delete the moving crate. Oddly and seemingly unrelated, people were also complaining about items disappearing from their houses. It turns out that the two problems were related. Object IDs in UO are 32-bit numbers that can be reused and the reference to the moving crate wasn't cleared when a player cleaned it out. This would leave a 'dangling reference' which was normally invalid. Sometimes the ID referenced would be reused to be a container in someone else's house or a chunk egg. Summoning the moving crate would pull that container from someone else's house or crash the server due to attempting to summon a chunk egg.
  • Samurai Empire expansion. I did most of the coding for getting in the new wearables. I also did the a lot of the scripting side of the new Bushido and Ninjitsu skills. I did a proof-of-concept for the roof tile system which was later turned over to an intern. I also did a proof-of-concept for a Unreal Tournament-style PvP battlefield system that was rejected (and continues to be a bit of sore spot with the point of view of management).
  • Unannounced game revamp. This isn't a 'great memory' so I don't know why I'm mentioning it. Yes, we were working on UO2 for the third time. We had a 3D client and were doing awesome things with breaking the skills into specialization and quest-based learning. The server technology was mostly staying the same, but we had finer-granularity movement actually working that allowed you to move within a tile. The scope of the project grew huge and we didn't have time to finish it nor wherewithal to cut part of it. Everything was scrapped and the idea eventually became Kingdom Reborn.
  • Mondain's Legacy expansion. Mostly support work here. I supported the rest of the engineering team and picked up a lot of the "smaller" tasks like the world collections (museum, zoo, etc) and parrots. I also worked on an asset replacement system that was supposed to help our artists be able to test out new content in the game engine faster. I also helped MrTact and EvilMantis design the guts of the Quest system. I left EA before this expansion went live.
  • Wombat. For some reason, I had great love for this proprietary scripting language. I took it under my wing and made some major improvements to it:
    • An integrated debugger that allowed breakpoints, stepping and printing out variables.
    • The ability to do negative numbers. Yeah. Really.
    • Floating point support.
    • Compiled binary support. Greatly reduced server start up times.
    • A simple optimizer.
    • Support for array and dictionary container types. Previously the only type was linked-list.
    • Global variable support (saved on memory usage)
    • Reference-counted containers. Saved time when large amounts of data were thrown around. Previously everything was copied. A lot.
Good times!

24 November 2007

A Decade of Ultima Online

Recently, Ultima Online celebrated its Tenth Anniversary. UO will always hold a special place in my heart because it was my first MMO, both as a player and as a developer.

As part of the celebration, IGN has an article and speedman (my dev name on UO) got a mention.

I can't explain why, but I always look at my memories in UO through rose-colored glasses. I remember playing back in 1997 and getting PK'd all the time as I mined ore (which was always gone due to the now-defunct resource bank system). I took some time off for a few years but eventually found my way back. A lot had changed in my time away, but I found a good group of friends to help me through the transition.

UO was a sandbox in many ways. Origin Systems provided the world but the players were the content. There were no predefined quests, no raid encounters and no leveling. There were only a handful of skills and spells and a wide-open world. When I wanted to gain a higher rank in the guild (which wasn't defined in the game mechanics), my mentor sent me on a quest (again, not defined in the game mechanics) which I had to document. It was the most unique experience I've ever had in an MMO and I passed it down to other guildmates when I became their mentors. As a developer, I also had the opportunity to chronicle it for the players. The story of my guild quest is now available as two in-game books written by Autenil.

UO was also my break into the game industry. I was a bit of a hacker at the time and wrote a few utilities for UO. I never distributed them to anyone but my closest friends; it was mostly a learning experience. The crown of my collection was a DLL that would attach itself to the UO client and re-write part of the software to pass network messages to my applications after the client had decrypted them. All of my tools were centered around this hook DLL. I had message loggers, information sniffers, and a few useful tools. Yes, I even had tools that would make it easier to gain skills by automating some tedious tasks (my animal taming tool would keep retrying until something was tamed, rename it so that you wouldn't tame it again, and release it).

Anyways, the company I worked for at the time sent me on a business trip to Austin, TX which also just happened to be the city of Origin Systems, the very headquarters of UO. Turns out they were looking for a server programmer and I had passed the tech test with flying colors. Since I was going to be in Austin anyway, I arranged a meeting with the UO dev team. Over three hours at Cheesecake Factory they grilled me about programming and MMOs (some of my old friends might remember that night). They were having some bandwidth problems with their latest expansion and I (due to my tools) knew what the main problem was. I told them that I would fix the bandwidth problem within two weeks if hired. They hired me and I fixed the problem within the first few days. Within two weeks, it was live and players were rejoicing.

The development environment that UO required was challenging. The servers would only build and run on Linux and we used GDB for our debugging. All programmers and designers had and maintained their own Linux boxes. Getting a server up and running required a spider web of filesystem links and a delicate matrix of configuration files and scripts (of several different formats). Still, I loved the proprietary script language known as Wombat and the badly-written C++ code.

I don't work on or really even play UO anymore, and I don't always (ever?) agree with what Electronic Arts/Mythic does with the game, but I still think about the game (and the friends I made working on it and playing it) often.

Congratulations, UO. Here's to another decade. At least.

19 November 2007

Kunark Rising

I've really been enjoying the new expansion. As a developer, playing it while under development really isn't "fun": you're looking for bugs, only a few people are in the zones, you're trying to take notes and not really enjoying the content. That all changes after the expansion launches.

Some things that I'm really loving:
  • Zone Art - I'm only level 69, so I've been hanging out in Kylong Plains. The art here is amazing. The spires at Teren's Grasp are amazing and ridiculously tall and the transition from the warmer lowlands to the frigid area is great. Plus, I can see my character's breath in the snow. The new environmental system that we put in is really making a great debut in the intra-zone transitions as well as POIs like Karnor's Castle.
  • Increased Quest XP - I love quests more than level grinding. The new quests are fantastic and have great rewards. The Quest Designers are using the relatively new item-association system that I put in and it's helping in some very subtle but effective ways. Also, this is a great time for me to brag about my Quest Sharing system. I've been adventuring with some pick-up groups and sharing quests has REALLY helped out.
  • Smooth Launch - I talked about this a bit in my previous post, but this launch had to have been one of the smoothest EQ2 launches we've had. The team was in great form and we really cranked on getting the last few issues wrapped up before launch.

Some programming-related things that I (and others on the team) have noticed and we're looking into:
  • Memory Usage - Those big zones aren't cheap memory wise. I'm currently looking into new ways to save memory.
  • Quest Sorting - If you're in one of the additional instances of the big zones your quest journal isn't showing quests for the current zone at the top.
  • DB Issues - Some of our larger servers have been under additional stress from the popularity of Kunark. The team is working hard to resolve these issues.


Happy Kunarking

13 November 2007

This! Is! Kunark!

We on the EQ2 team are launching our Rise of Kunark expansion today. I'll periodically edit this post with updates. If all goes well, this should be a very boring read. :)

8am - Gah, too early. They brought in breakfast which is greatly appreciated. We also just received our Rise of Kunark boxes and I registered my RoK keys for the live servers. Servers are receiving the RoK publish package and everyone is trying to patch.

10:30am - I finally got patched up. Servers are still locked (and will be for a while while QA continues to get patched up and runs tests). Besides some slowness with patching, there's no problems to report yet. Back to work trying to get the client to use less memory!

Noon - The community people have come by to take my picture a couple times. Maybe I'll be famous! Or not. They'll probably post a picture on eq2players.com or something. Due to overloaded patchers, we had to extend the downtime to 2 pm.

1:30pm - It's getting close. A quick check of the IRC channels show that the unlock is imminent. QA appears to have signed off and the operations group is preparing to let the players in. Now the real fun starts. We'll watch the performance and hope that all of our hard work payed off.

2:15pm - Everything is going well. Servers have been live and unlocked for 45 minutes now and everything looks great. I'm on-call for any emergencies that might crop up, but everything looks great for now!

Turns out they wanted pics for an interview. In French.

12 November 2007

'Twas the Night before Kunark...

Most days I feel incredibly blessed to be in the job that I'm in. Programming, working on (and playing) games, all while makin' bucks has just been a lot of fun. SOE is a great company to work for, especially with how family-friendly they've been.

We're launching Rise of Kunark tomorrow and it's bound to be an interesting day. I'm part of the launch support team, so I'll be in there bright and early at 8am tomorrow morning. Hopefully tomorrow I'll post a play-by-play of how an EQ2 expansion launch looks through my eyes. In the meantime, here's some pics of where I'll be spending at least 8 hours tomorrow:



27 October 2007

Let's Rock!

I was pleasantly surprised to find that Redoctane shipped my Guitar Hero 3 bundle yesterday and it was delivered today! Not bad for a game that is supposed to be released this coming Sunday.

As you can imagine, I tore into it almost as soon as I could.

Quick Review:
The actually like the new UI. The wireless Les Paul guitar is awesome (after losing the wireless when going from PS2 -> XBOX360, it's great to have it back) and feels more solid, plus the strum bar is quieter. Better still, it works great with Guitar Hero II. I thought that battle mode was going to suck, but it's actually a lot of fun. The online play is great. I played (and won) some random Pro Face-Off matches and then hooked up with a friend to play Pro Face-Off and Battle Mode matches. For better or worse, the achievements are much harder to get, and there are a lot that involve co-op career mode (yeah, it's a new feature too).

All in all, I'd say Activision did very well with the latest installment. It'll keep me entertained for quite a while!

24 October 2007

My xbox has a Voice

"Shall we play a game?" - Joshua in WarGames

Ok, maybe it's not quite like that, but my xbox 360 has learned how to keep a blog. Sure, it just picks randomly from a list of phrases, but it's kind of cute. It really appeals to my geek nature i guess.

Anyways, my xbox live gamertag is 'autenil' (the same as my EQ2 developer name).

Now, off to try out the Guitar Hero III demo!!

Back at home

Just an update. Even though the I-5 was closed this morning, we decided to head back down to San Diego from Bakersfield. The drive went great with no delays and we passed the Horno fire burning near Camp Pendleton, getting some pics (hopefully I can post later).

Upon reaching home, everything was much better than when we left early Monday morning. Most of the smoke had cleared and you could actually tell that the sky was blue. There was some small debris blown into our yard and the front sidewalk is caked with dirt, but everything is just peachy.

Thanks to everyone who IM'd or emailed to check up on us!

23 October 2007

California Land: Smokin' Hot!

San Diego really is a beautiful place to live, but it gets kind of hot while it's ON FIRE.

We noticed the fires a little after noon on Sunday. I noticed that my car was no longer parked at my house and called the police to find that it had been towed (stupid homeowners' association rules) and we all piled into the car to get it back. $314 later (zomg!) we were driving home and noticed the haze in the sky. We turned on the radio and heard about the Witch Fire burning near Ramona, CA. We were amazed that this smoke was from a fire 30 mi away.

We went home and closed up the house and turned on the TV. With the fire due east and heading west at a remarkable rate, we definitely wanted to keep an eye on it through the night. Sarah woke up at around 5 am Monday morning and turned on the TV. The Poway High School that was being used as an evacuation center for Ramona citizens was cleared out and the evacuees were moved to Mira Mesa High School, just down the street for us. The Witch Fire was encroaching on Poway. The air quality was horrible. Even with the house closed up and the AC running, there was a thick wood-fire smell in the house.

We reserved some plane tickets to get Sarah and the kids out of town, but weren't able to get to the airport fast enough. Work was obviously canceled, so we decided to beat the crowds out of town and turn the fire into an impromptu family vacation. We packed up all the important stuff in the car in case the fire does reach the house and took off heading north at about 9 am. I-15 was closed due to the fire, but it was very easy to head out north toward LA on I-5 (the I-5 was later deadlocked by people trying to leave, so early was definitely the way to go here). Parts of LA were burning too, but we were able to avoid those areas pretty easily. We were going to stay in Stevenson Ranch, but there were some nearby fires so we decided to keep driving north. It's a good thing too, because another large fire broke out there.

We kept driving north and decided to stop in Bakersfield. It's a nice little town (and has Sonic restaurants!), but best of all, there's no fire.

We're just hanging out here enjoying the local sites and breathing clean air. We might head back home tomorrow depending on how the fires do through the night.

10 October 2007

Whew! My fingers are sore!

After 24.5 hours of building spread out over 11 days, I've finished building the 5200-piece LEGO Millennium Falcon kit.

Here's a time-lapse video for your enjoyment:

02 October 2007

3 Steps to Wealth!

Someone wrote this up on my whiteboard in my office:

1. Time Machine
2. ?
3. Money Hats!!

28 September 2007

It finally came!

Back in March I placed an order for a certain LEGO set. Even though it wasn't supposed to ship until 10/01, it went ahead and showed up on my doorstep yesterday.

I haven't started building it yet, but based on how long the Death Star took, I'm guessing it'll be around the 20 hour mark before it's finished.

Here's some pics that I snapped:
DSC00100 DSC00101 DSC00102
DSC00104 DSC00105

19 September 2007

Avast, ye lubbers!

Arrr, so today be International Talk Like a Pirate day. If I be tellin' ye the truth, enjoy this day I did. Ne'er before have I participated in the festivities, but this year thar be rum a-plenty and a good dose of piratitude among me hearties.

If ye's were unaware or disinclined to take part in Talk Like a Pirate Day, forget it not next year, or ye'll be walkin' th' plank at the tip o' me cutlass! So, grab yer bonnie lass and yer grog and Talk Like a Pirate, lest ye be keelhauled! Arrr!


If ye can't wait to fill ye holds with swag, th' whisper on the wind says that somethin' is a'comin'. Roll out th' cannons and prepare for battle!

11 September 2007

Apparently, I'm a "Blood Snob"

A friend told me this, and truth be told, I like the title.

One of the things I like to do for the community is donate blood. I'm a universal donor with a blood type of O- so several agencies call me every 8 weeks trying to get me to come in. However, I'm fairly particular about which agency I donate blood with. Generally, it's the San Diego Blood Bank. They have several perks specifically designed to attract the <snobbery>blood donating elite such as myself</snobbery>:
  • Points awarded for each donation that can be spent in their online store (or donated back)
  • Online stat tracking (blood pressure, pulse, cholesterol, etc)
  • Levels of preference based on how often you donate
  • Awards (such as sports tickets)
  • Gallon tracker
  • etc.
Maybe it's an ego thing, but it's nice to whip out my Life Level 4 card and hear the trumpet fanfare and be raised on a pedestal in the spotlight... Ok, maybe all that doesn't happen, but there is some manner of recognition and the nurses are glad to have you there. The San Diego Blood Bank is doing it right and I'll be glad to see them again in another 8 weeks. Those other agencies should take notes.

19 August 2007

New MP3 Players!

A while back I expressed my personal experience and hatred of the iPod. I mentioned that I wouldn't be getting another iPod and today I confirmed that.

My wife's ipod mini is to the point where it won't even hold enough of a charge to turn on when plugged in. My 3rd gen ipod has been dropped too many times and the last time (not by me) broke the connector to the point where it doesn't detect that it's connected to a charger or the computer.

A few days back my sister-in-law purchased a Creative Zen V Plus 4GB and then decided that she didn't want it. My wife loved the thing and took it as her own. Goodbye, ipod mini. Hello, tiny Zen. It holds the same 4GB that her ipod mini did, but adds a color screen, can show pictures and play video (albeit tiny), has a built-in FM tuner, and a mic for recording anything. Quite a steal for only about $110.

I'm a little more geeky and require something higher than 4GB. My 3rd generation ipod held 10GB. I was looking heavily at the 30GB Creative Zen Vision:M, but after reading some reviews and great user feedback of the 30GB Microsoft Zune, I decided to pick one up. Both the 30GB Zune and Vision:M run the same price as the 30GB video ipod: $250.

The Zune has the immensely desired FM tuner as well as a much bigger [wide]screen. It also has a wireless device so that you can share music with other Zunes. On the downside, it's a little bulkier than even my old 3rd generation ipod, and doesn't look as sexy. The buttons are simple and clicky (which I prefer over the touch activated ipod), but I'll probably miss the ipod's thumbwheel. I also lament the lack of FireWire support for the Zune.

I'm currently trying to get all my music organized and put on the Zune. The software that comes with it is a breeze to install, but finds every picture, music file and video on your computer and adds them to the library. I have a ton of games installed and don't necessarily want all of the games' MP3s on my Zune. I still have to burn and rip all of my iTunes purchases (only about 85) so that I can put them on the Zune.

I'll probably be posting more about this subject in the future...

29 July 2007

cya at fan faire

SOE's annual Fan Faire starts this Thursday.

We'll be showing off some cool stuff about our in-progress EverQuest II expansion, Rise of Kunark and attendees who pick EQ2 as their game of choice will be given a ROK-themed cloak only available at Fan Faire.

I'll be on a panel or two, including the Mechanically Speaking panel.

Our Comic Con Block Party also went quite well. I had fun showing of the new Sarnak race in ROK and talking to fans for a few hours.

If you can make it to Las Vegas for Fan Faire, it'll be great to see you there!

Pickling - it's not just cucumbers anymore

We programmers on the EverQuest II team discovered a neat little utility the other day.

We have so much data and source code in Perforce for EverQuest II that our administrator frowns at creating branches. We only have three branches aptly named "main", "test" and "live" and we do all of our development out of "main" including expansion features and live game updates (there are other challenges to overcome with this configuration, but I'll just go into one).

Occasionally, I'll be working on a feature and will have a significant amount of critical files checked out and modified. At this very moment something comes up: a live game crash, a higher priority, etc.

Enter Code Pickle. This nifty little utility allows you to suspend an entire changelist. All your current changes are safely stored freeing you up to handle the immediate priority. After handling the emergency, you can then resume your changelist just as if you were never interrupted. If the files in the suspended changelist have other changes, Code Pickle helps you integrate them. And at $600 for a 10 user license, it's well worth it.

Code Pickle supports multiple source control packages, but I've only tried it with Perforce. Try out the demo!

20 July 2007

/resurrect PSP

A few weeks ago I sat down on a plane looking forward to returning home from vacation. I pulled out the PSP to watch a few episodes of The Office on the ride. Lo and behold, I'm greeted with a PSP owner's worst nightmare: a cracked screen.
DSC00593

I wasn't ready to write off the $200 that I paid for it though, and Google was more than willing to help me out. Amazon even listed some screens for sale for a very decent price. I ordered a new screen (with backlight, not because mine was bad but I'd rather pay $5 than having the hassle of trying to swap backlights without getting any dust in there) from The Gaming Shop on the 13th and it arrived today (7 days for North LA -> San Diego? That's sad.) I don't really recommend getting the screen from them because this is how it came:
DSC00591
Loose, in bubble wrap, not even in a cardboard box.

Like a kid on Christmas morning, it's time to work on my PSP! I used The Llama's excellent PSP screen replacement guide. I'll let the photos do the talking:
DSC00594 DSC00595 DSC00596 DSC00597 DSC00598 DSC00599 DSC00601 DSC00602

Then, the moment of Truth:
DSC00603

Woot! The brand-new screen fires up beautifully with no dead pixels! Just a few more screws and we're done:
DSC00604

I managed to replace my PSP's screen for about $50 (and a fun 45 minutes or so) rather than buying a new one at $169. Looks like I'll be investing in a hard-shell case soon too!

05 July 2007

Independence Day: Parades, Fireworks... Bike Rides?

In what has apparently become family tradition, I did the Scripps Ranch Old Pros Bike Ride yesterday. Since moving to San Diego we've done the 12-mile "Family Fun" ride. Two years ago, my wife rode with us and my son was in a seat on the back of my bike. Last year, my wife was pregnant and it was just me and the kid. This year however, my son has gotten too big for his bike-mounted seat and I didn't have anything sufficient for him to tag along with. So I did the 28-mile ride solo.

It was definitely more hilly that I'm used to. My semi-daily ride to work is about 6 miles, so this was quite the step up. I did it in two hours flat and it was just about perfect for my cycling strength. My 2005 Trek 1500 was pretty decent for the ride. I definitely have to work on my hill climbing. I managed to hit 42.1 MPH during one of the downhill portions when I was still fresh and trying to catch up with some other riders. That's freakin' fast when there's nothing between you and the pavement but two thin tires.

The water and oranges at the finish line tasted better than a meal fit for a king.

Unfortunately, the ride didn't go well for everyone. (There's actually a few errors in that story: It's the 56 highway, not the 76. The 10K was the run portion; he was on the 28-mile ride.)

I'm looking forward to next year, but I won't be doing the Tour de France anytime soon.

12 June 2007

The Scam that is LA Fitness

How hard should it be to cancel your gym membership? Just a few years ago, I walked into 24-Hour Fitness, said "I want to cancel" and they said ok. Done deal.

Fast forward to a week ago. My wife wasn't using her membership and my kids didn't like their Kids Klub play area. "I'll just cancel the account!" I thought. So I call up LA Fitness. "You can do it online. We can't do it here in the gym."

So I create an account online and go to the cancel option. Here's what I'm greeted by:


I have to mail in a crappy form for each person in order for them to cancel the account.

Fine. Gyms make most of their money from people who don't cancel and don't attend. This just seems like it's a little bit harder than it should be.

So I mail in the forms. A little over a week later I check back at the gym to see if the accounts have been canceled. Nope! Why not? They have no idea, because that's all handled by corporate and they don't even have a phone number to give me (I later found out that they seem to 'lose' an awful lot of mail that isn't sent CERTIFIED). The most they can offer is to have someone from corporate call me.

And call me they did (though not when they said they would). To be honest, I was actually surprised. But the guy had the audacity to require a reason for canceling. Here's your reason: I don't want to give you any more money. It's a good thing my credit card has better customer service than they do. What's more is you have to give them 30 days notice (basically one more time they can charge you) BEFORE they start counting on that "last month" that you paid for when you start up.

Case in point: If you sign up at LA Fitness, be aware that it's going to take World War 3 in order to end the membership. Save your money and your sanity and go ANYWHERE else.

Update 5/6/2008:
In the comments below, Duane pointed us to the BBB page for LA Fitness and called out Aylin Medina (phone (949) 255-7330) as the person to call to cancel your account with zero hassles. I recently called her to cancel my last remaining LA Fitness account. She was very nice and I had my account canceled inside of two minutes. If you call her, make sure you have your LA Fitness barcode handy. Thanks Duane!

Update 1/20/2010:
Apparently there has been a Class-Action Lawsuit against LA Fitness. It looks like you might be able to file claims for post-cancellation charges. More information at www.gymsettlement.com.

10 June 2007

Video Card Woes

For a while now, I've been rather loathe to play any 3D games due to subtacular performance. Even my own game (EverQuest II) had become unfun and choppy. My home rig isn't that shabby: AMD x64 4000+, 2GB RAM, ATI X800 XT Platinum video card. So why the bad performance?

At first, I thought it was a problem with EQ2. I have all of the source code, but since I don't run Intel at home, VTune was out of the question. So I wrote my own simple sampling profiler (which works pretty well I might add) that basically lets me know where the main thread was spending all of its time. On a healthy system, this is typically in the CPU-bound vertex transformations for animations (side note: don't ask me why this isn't in a shader).

However, that's not what I was seeing. I was seeing the most time spent handing geometry to the card. After doing a little research, I discovered that this might be because the card is overheating and the drivers were decelerating the VPU. I downloaded the ATITool to have a look-see.

Sure enough, my VPU was reaching temps of up to 110 C (zomg!) playing EQ2 in full-screen mode. It was slightly better windowed, but still hotter than hades. The fan was visually observed to be spinning at 100%. I figured I might as well try out Mike Vande Ven Jr's solution before I go drop $500 or more on a new card.

I ripped the card out and used a generous amount of canned air to get all the caked-on dust off the card. There was plenty for a 3-year-old card. Then the heatsink had to come off. This was actually pretty easy: just pop out 3 phillips screws. The old thermal grease was definitely pretty nasty. It appeared to be more solid than it should be:
DSC00391

I used a plastic card to scrape away all of the old grease. Then I used Arctic Silver ArctiClean to remove the rest of the old stuff. It was amazing how much it cleaned up the heatsink and VPU. Unfortunately, I was too excited to take a picture, but here's an idea from a 9800. After I could see myself staring back from the VPU, it was time to apply the new thermal grease. I chose Arctic Silver 5 because it's what all the overclockers use. The instructions say .5-.75 of the size of a grain of rice, and then spread it around with the plastic card:
DSC00394

I threw the heatsink back on, careful to evenly tighten the screws that put the pressure on the VPU. Initial tests are already showing idle temps to be around 15 C lower, with load tests not even breaking 50 C (the idle point prior to the grease change). I'm having issues with a hard drive now, so I'll confirm results later when actually running a game.

Update: I ran around in EQ2 for a while and hit a max temp of 72 C with the fan only spinning at 67%. And this in full screen! Previously it would overheat the card to the point of shutdown. I'd say it worked!

11 May 2007

Rocking Out

Yes, I love Guitar Hero. I love Guitar Hero 2 even more. Here's my first ever Guitar Hero video playing "More than a Feeling" by Boston. Not perfect, but not too shabby either.

10 May 2007

Rise of Kunark

We just announced our latest expansion for EverQuest II: Rise of Kunark.

Allakhazam has some exclusive interviews with Scott Hartsman.
Even EQ2Flames has a positive thread on the subject.
Tons of threads on the Official Forums.

Of course, players figured out some of this from an accidental leak a few days ago.

Needless to say, we're very excited about the next expansion!

09 May 2007

Burninating the Countryside

There was a brush fire scarily close (~1500 ft) to my house. What's more is they think it's arson. What is with people?! Anyways, with the wind blowing the fire toward us we didn't hang around long. We strapped the kids into the car and headed off to a friend's house to watch from a distance. Praise God that the San Diego Firemen are good at their jobs. My son had fun decorating a card for the Fire Department and delivering it to them. Might be time to take that standard-San-Diego-issue evacuation checklist seriously.

Click for more images

04 May 2007

Wii got one!

Last Sunday, Target stores nationwide had several Wii units available. Since I'm too lazy to get up (either that or my two kids tend to keep me busy), my dad offered to go stand in line. Between him, my sister and my mom, they walked away with 2 Wii units.

There's also a cool story there: my sister selflessly gave her place in line to a sweet little girl who had been saving for months to get a Wii. Way to go sis!

Setting it up now and loving it.

Thanks dad!

P.S. My Wii number is 0018 1966 1556 9253

25 April 2007

Compile-Time use of assert

Why do at runtime what you can do at compile time? A lot of times, code depends on the values of certain enums not changing, or if they do, the code must be updated. If not handled properly, this can become a maintenance nightmare.

Use of the assert keyword comes in handy here. You can assert in debug builds that the value is what you expect it to be and whoever is maintaining your code will know what they need to do to make their new value work (because, let's face it, you comment your code great).

There's one little problem though. The assert line only happens if it's executed, therefore it might not catch all situations of misuse (at least not right away).

Here's a neat little trick:
#define compiletime_assert(argument) \
{ int unused[ argument ? 1 : -1 ]; }

compiletime_assert(MY_SPECIAL_VALUE == 4);
This gets evaluated at compile time. If anyone changes MY_SPECIAL_VAL to a value other than 4, the compiler will stop there with an error. The only downside is that the error is pretty cryptic, but good commenting will help out there. Obviously this will only work for things the compiler is able to evaluate at compile time, but that includes some very useful things like sizeof and value checking.

Software bugs, but not what you think

I'm posting this because of the people who didn't believe me. You know who you are.

According to an article that happened to find its way into my email, scientists have found and modified a particular bug protein so as to use it for data storage. Apparently, a LOT of storage.

The article estimates commercially available USB drives available a year from when it was written, but it's been almost a year and doesn't seem to be mainstream yet.

I'll keep my fingers crossed.

16 April 2007

Gun Control and the VA Tech Shootings

So it didn't take any time at all for the Gun Control lobby to come out and preach about the necessities of Gun Control.

First and foremost, my condolences and prayers are with the parents, family and friends of the victims of this tragedy. I'm sorry for your loss.

Now, Gun Control is not the answer. Why? Bad people have always been able to do Bad Things, and they don't obey the laws, so why would Gun Control apply to them anyways? The only thing Gun Control would do is cause law-abiding citizens to not be able to get guns that the Second Amendment to the Constitution affords them:
A well regulated militia being necessary to the security of a free State, the right of the People to keep and bear arms shall not be infringed.

Virginia has a concealed carry law, but the VA Tech campus doesn't allow concealed carry and furthermore an official praised the defeat of the concealed carry law on campus! With concealed carry, you don't know who around you has a gun, but if someone does, they've gone through extensive background checks and training. This is almost like a type of militia.

School shootings have really increased dramatically. In the 70's they were almost non-existent, and now there are multiple every year. Kids these days have loose morals, but that wasn't always the case. In the 50's you could find a school parking lot with rifles in trucks, but almost no school shootings. There was another thing present in schools in those days, and that was God. Since God was removed from the public schools in 1962, every major social problem has been on the rise: violent crime, divorce, teenage pregnancy, sexually transmitted disease, etc. Take away children's moral base and tell them that they are the product of nothing other than time, chance and random processes and what do you think will happen? Honestly, where is the outrage?

It's time for America to turn back to the moral base it had. There's nothing progressive about this society.

14 April 2007

Placement new is your friend

It doesn't happen often in game programming when you want to be specific about how (or where) an object is constructed, but it does come up. Consider a simple block allocator:

struct FreeBlock {
FreeBlock* pNext;
FreeBlock( FreeBlock* pNextFree = 0 ) :
pNext( pNextFree ) {}
};

T* BlockAlloc<T>::alloc() {
if ( m_freeList ) {
FreeBlock* pBlock = m_freeList;
m_freeList = pBlock->pNext;
pBlock->~FreeBlock(); // Destruct FreeBlock
// Use placement new to construct T
return new ( pBlock ) T();
} else {
// Get raw memory and set up free list
...
}
}

void BlockAlloc<T>::free( T* pt ) {
if ( pt ) {
pt->~T(); // Destruct T
m_freeList = new ( pt ) FreeBlock( m_freeList );
}
}


This is a very simple example, used only for illustration. The use of placement new allows us to construct only the T objects that are currently in use, but allows us to allocate enough memory for a large number of them.

Calling the FreeBlock destructor is seemingly unnecessary since FreeBlock only has an implicit destructor. However, it's maintainable to do so. What if someone later adds a destructor to FreeBlock to, say, decrement a count of FreeBlock objects?

This is a simple example; placement new is great for many things: containers, singleton objects that you don't want on the heap (but want to control when they are constructed), memory management structures, game resource management and so on.

09 April 2007

Five things you [probably] don't know about me

... or care to.

Anyways, this was going around for a while. Even though no one tagged me I'm going to go ahead and dump this on you. Here goes:
  • I'm a Christian
  • At a young age I turned my life over to Christ. Christian apologetics are very interesting to me. Most people don't understand that it's possible to be an intellectual Christian, but there is amazing historical evidence of Christ, his life, death and resurrection. Christianity has given me pure joy and I attribute any success I have in life to Christ.

  • I'm a Creationist
  • This plays into the first point. Again, it's possible to be an intellectual Creationist. No matter what view of origins you hold, it's not observable, measurable or repeatable. It's a matter of faith. None the less, there are plenty of books and videos that support my point of view on the topic.

  • I've been lost
  • When I was in High School, a friend and I went hiking in the Gila Wilderness. After losing the trail due to snow melt and becoming hopelessly lost, we figured our position on the map as best we could and headed for the Gila River, ignoring those close topographical lines. We had to climb down huge cliffs and eventually had to abandon our equipment. My friend lost one of his boots as he was swept away in the Gila River. When we finally made it to a highway, we hitchhiked the 14 miles back to my car, which had a flat tire. This also plays into the first point as it strengthened my faith.

  • I prefer Country
  • Why? 'Cause it's songs about me. It's music I can listen to in the car with my kids around. It's old-fashioned values and unselfish people still helping each other. Now, if only Guitar Hero would actually come in a country version...

  • I have better-than-perfect vision
  • I have permission from my optometrist to brag on this. He was dismayed at not being able to sell me any glasses or contacts with my 20/15 vision in both eyes. This is amazing to me since my dad has always worn glasses, my younger brother is starting to wear them, and my mom has been wearing them for a few years now.

02 April 2007

Maintainable code [for the win]

Books can (and have) been written on this topic, but I'd like to share one of my favorite little constructs. Often times I'll need to change a variable just for the scope of my function (a locking bool or a depth count for instance). It is ALWAYS better to use a temporary class on the stack to do this.

If I set bRecursionLock = true then I have to remember to always set bRecursionLock = false before I return from the function. What if someone other than me (or even me in a few months) has to change that code? What if someone adds a new return and forgets to set bRecursionLock = false? You get a hard-to-track-down bug. Why bother? The simplist C++ construct can take care of this:

class TempLock
{
    bool& m_lock;
public:
    TempLock( bool& lock ) : m_lock( lock ) { m_lock = true; }
    ~TempLock() { m_lock = false; }
};
TempLock lock( bRecursionLock );


We actually had this situation last week. A function needed a temporary class to change a variable on a class instance just in the scope of a function, so I used this construct even though there were no return statements. At the same time, an intern refactored the same function to return all over the place. When both of our changes were merged, the code worked perfectly.

24 March 2007

Deconstructing the XBox security system

This is a great video that talks about the original XBox, its security shortcomings, and how hackers eventually got it to run Linux. Over an hour, but very entertaining for geeks like myself.

23 March 2007

Getting Handsy

Grandma and Grandpa are in town, so somehow, crazy videos with my son turn up. Here's the latest:

21 March 2007

Humanized Software

A friend showed me an interesting piece of software today over at Humanized. It's called Enso, and has been described by some as "The Command Line Comeback".

It's a very intriguing idea. Highlight a block of text that says "132/4", hold down Caps Lock and type "calculator". Presto-changeo, the highlighted text gets replaced with 33. There are several other commands to open programs, browse the Internet, or control windows. Head on over there and check out the demo!

The install was seamless. Click a web control and it's as easy as installing the Google Toolbar. Unfortunately, as a technogeek, I didn't want it installed where it automatically ended up (and I didn't see any custom install options). Obviously a very minor note.

The other problem that I had with it is that it's overly resource-hungry. This might be due to the fact that it's almost entirely written in Python, but for as simple as it seems, I don't think it needs 30MB of memory and 17 threads.

The possibilities for this piece of software are abundant. You can 'teach' it new commands and future versions are supposed to be extensible with Python. As a programmer, I'd love to have things like conversions between hex/decimal/binary or even a calculator that does bitwise operations.

This is definitely something I'll be keeping my eye on.

13 March 2007

Don't buy an iPod

For a while now I've been having a consistent problem with my 3rd generation iPod: the last 15-20% of some songs get cut off. Unfortunately, there seems to be nothing that Apple is doing to address the problem (or even acknowledge what it is). Several people have reported this problem in various forms. Now, I only use iTunes to import my songs, and as others mention, they play fine in iTunes. And the kicker: this is even happening with songs that I purchased from the iTunes store!

It's definitely a problem with the iPod: the progress bar gets within 15-20% of the end of the song, and all of a sudden, the iPod switches to the next song. If I manually set the progress bar into the part that gets cut off, it immediately skips to the next song without playing anything. It's not every song, but it's always the same songs. It seems like every so often a new song starts exhibiting this problem.

If Apple would address the problem, that would be great. Any hope of getting that to happen? Probably not.

My wife's 1st generation iPod mini also has a problem: In less than 3 years (it's newer than my 3rd generation iPod) the battery won't hold a charge for even 30 minutes. Is it in warranty? Not anymore! Is the battery user-serviceable? Never! Last time I checked, Apple wants $100 to swap out the battery.

By now you should know what I'm going to say: my next MP3 player selection will NOT be of the Apple variety.

Update, August 2007: I decided to go with a Zune; read the whole post

10 March 2007

Hackalicious

The more I beta-test/play/develop MMOs, the more I realize that developers still cut corners when it comes to security. If you're working on an MMO, especially before launch, it's very important to take a look at your game through the eyes of a hacker.

I've worked on hardening some games to the hacker types (and let's admit it: I was one myself once), so here's my short primer on MMOs and hacking:
  • Don't ship your game with the .PDB file! Obvious? Maybe, but not to some.
  • Turn off RTTI. Why are you using dynamic_cast anyways? It supports crazy things like casting horizontally in multiple inheritance. Not to mention that it's slow. Hackers love RTTI though, as it causes the executable to include mangled names of pretty much everything. If you need a dynamic typesafe casting solution, search the web or get a book. Or use virtual functions, though it's ugly as sin.
  • Take a look at your client in a hex editor, especially strings. You might be surprised at what you find. Those assert lines can actually contain a ton of useful information, like source file names and line numbers, not to mention C++ code itself. Or you might just find that you're including the class names of every message type in the game. Yes, it's been done.
  • Beware large areas of [un]initialized memory. Hackers love it when they already have space allocated in your program that they are free to write their code into. UO had a bunch of these before I cleaned them up, the largest of which being a 640x480 graphics buffer that was never fully used. Use the heap and make it lazy allocate. If possible, delete it as soon as you're done with it.
  • Change message IDs frequently. If you can do it right (and unpredictably), this can work well to foil those who like to read the network traffic.
  • Log stuff to the server, but don't take action on it right away. You don't want to do anything that lets a hacker know that you're onto them. Check with your legal department to find out what you can report, but it generally shouldn't be bad to do something like CRC the client in memory and send back a pass/fail response to the server. Or report if they're using a debugger, though this can be challenging. Unfortunately, uploading their modifications for review is anathema.
  • Watch your encryption keys. Yes, EQ2 actually held the encryption key in plaintext in a static buffer after negotiating it. It's fixed now, but hackers rejoiced!
  • Verify user data. UO has an immediate request/response targeting system. The server sends a request to the client with an ID which the client returns unmolested to the server. But what happens when a hacker figures out how to make use of changing that ID? You get the insurance bug.
  • Beware of unreleased/undocumented content. Again with UO, there were quite a few "gumps" that were in half-implemented features that still got pushed to live servers. A hacker figured out how to make use of one of these and ended up teleporting half the players on the server to a single X,Y location. Use source control branches or some configuration system to make sure this untested stuff can't be used. Period.
  • Don't make assumptions. You've heard the clichés so i'll spare you. Just because a normal user can't see something (like a UI window or network message format) doesn't mean they can't exploit it.
  • Movement. A notoriously bad topic for MMOs, especially 3D ones, there should really be more seriousness here, at least in the way of logging. Servers can at least sanity check movement without having to run simulations of every client.
  • Buffer overruns/remote code execution. Yes, it can happen to you. Watch how you're using the string functions, especially the varargs ones (sprintf, sscanf, etc) and wide functions. The discussion on this one topic alone could be (and has been) a lecture in itself, so I'll just say: be aware of it.


  • You can never fully stop people from hacking on your game, but you can make it difficult (and you should). Then there's the other side of the coin: banning the people you catch hacking. Usually this is financially advantageous: if a hacker is turning people off of your game, it's probably not just one.

    Unfortunately, maintaining hack resistance and detection can be a full-time job, especially if your game is well established and there are many hack programs out for it. In such cases, it might be better to look at using something like PunkBuster.

    This is definitely an area of MMOs that should be collaborated on, since all MMO developers don't want the hackers :)

    08 March 2007

    07 March 2007

    Remember Showbiz Pizza?

    My old boss on UO, Anthony "SunSword" Castoro was apparently a child actor. Who knew? You can see a quality 80's Showbiz Pizza commercial and read all about it here.

    Anthony has apparently just moved back to Austin to start Heatwave Interactive.

    06 March 2007

    Fun with C++ template specialization

    Today I had some fun with C++ template specialization.

    The EQ2 codebase doesn't use std::vector anymore in an effort to reduce compile and link times. Instead, we have our own templated array type that is, for all intents and purposes, equivalent to std::vector but without some of the template overhead for allocators and such. Call it ArrayType< T >.

    Now, ArrayType relies upon a static traits structure to do certain things for it, such as construct a range of T objects or copy T objects. Template specialization is used, especially for built-in types such as int or float, to perform the necessary operation in the most efficient way. For a built-in type, a copy could typically be implemented as a memcpy() or a memmove(). That wouldn't work very well for most custom classes.

    STL libraries such as STLport use complicated type traits to answer questions like is_POD_type. Ours is much simpler and specialized to remove that template overhead.

    In any case, back to my use of specialization. Consider what happens when you do something like this:

    std::vector< std::vector< int > > vec;
    vec.push_back( std::vector< int >( 1 ) );
    vec.push_back( std::vector< int >( 2 ) );

    vec.insert( vec.begin() + 1, std::vector< int >( 3 ) );


    If you have vectors of vectors, each reallocate of the underlying data structure is going to cause the contained vectors to be copied. That's potentially a LOT of allocations. Likewise, the insert is going to move all of the elements including and after the insert position to make room for the new element. More allocations. Theoretically, there is a way to overcome this. Vectors (and most other STL containers) have a nifty little function called swap which swaps the contents of two same-type containers in O(1). To handle the insert, all you'd need to do is construct a default object (or copy-construct the new object) at the end and swap with previous starting at the end. The default object ends up right where you want your inserted element to go, so you can use the assignment operator to set it to the new element. No deep copies of all of the vectors, just nice-and-tidy memory management.

    The rub is that there doesn't seem to be a tidy, generic way to do this with the STL. If you know how the traits work for STLport, you might be able to extend it to get what you want. That's far from a generic solution. This is where I get to brag about our ArrayType. All I had to do to make this work the way it should was define the swap semantics in a partially specialized ArrayType_traits:

    template< typename U >
    struct ArrayType_traits {
    ...
    static void rev_copy( VeArray<U>* dest, VeArray<U>* src, unsigned n )
    { dest += n, src += n;
    while ( n-- ) { (*--dest).swap( *--src ); } }
    ...
    };


    Neener, neener.

    05 March 2007

    LEGO + MMO = LEGMMO?

    Ah Legos. I never grew up. I still build all the Legos I can find. So, an MMO built with Legos? We'll have to wait and see how this turns out, but i've got my fingers crossed on this one.

    The start of a legacy or just another waste of time?

    Well, after several unsuccessful attempts at starting a blog, hopefully this one will stick. I imagine it will contain thoughts on a variety of topics.

    On the game programming front, my good friend Tim "MrTact" Keating just left Electronic Arts to work for a startup in Austin. As Palpatine said in Episode 1, "We shall be watching your career with great interest."

    On the topic of family, here are a few videos of my 3-month-old daughter, who just discovered that she could laugh. Enjoy!