Thursday, September 8, 2011

Operation HackMaster Crit Tables, episode 1

This post is about a project I recently did for fun.  Although the project itself has extremely limited application, it inspired me to do something I've been meaning to do for a long time, namely upgrade the web server for my apollowebworks.com domain to something which supports Java applications with Tomcat.  (I chose a company called Arvixe based on scanning the features they offer and reading a bunch of reviews.  Shout out to my boyz at Arvixe!)

Because I'll be touching on a wide range of topics, I'll split them up into multiple posts, and that should keep me from neglecting this blog for a little while.  So, partly to tell you what's coming and partly just so I can keep track for myself, here's a road map of the topics I plan to hit with this discussion.

  • General geekery about using programming to automate complex tasks.
  • Building a project from the ground up, starting by visualizing the data structures instead of just diving in blindly.
  • How separating interface from implementation makes it easier to translate your program to multiple platforms.
  • Good riddance to the bad old days: How the web has made program content delivery easier.
  • A primer for noobs on what web servers do, and why I bought another one.

First let me explain the problem.  My fiancee, Lynnea, has gotten into paper-and-pencil roleplaying games.  She has been running a light Dungeons & Dragons campaign occasionally for me and my son Ben over the last few months. She also plays with a group of friends one night a week.  For my part, I've played RPGs a few times before but never been a strong part of that scene, so I just listen to the stories of her sessions.  Currently they're playing with a rules system called "HackMaster."

As I understand it from skimming a few chapters of the rulebook, HackMaster was written by someone who hates doing things the easy way.  When D&D was first published in 1974, it was at first an ever-expanding set of complicated rules involving tons of die-rolling for all kinds of special situations.  Or as a German exchange student my family hosted in high school put it, "D&D isn't a role-playing game, it's a roll-playing game."  Har.  Har.  Very droll, those gamers.  (Oh hey, how are things going, Max? ;)

Still, as the years went by, D&D started to reverse the trend and become more streamlined, or so I've heard.  The latest release, fourth edition rules, was clearly heavily influenced by World of Warcraft, and reduces a lot of the unnecessary choices in favor of more interesting combinations of focused options.

The HackMaster author just hates that.  Not that I would recognize the difference, but I have the impression that if anything, he's aggressively chosen to make every little action even more complicated than it would have been under old-school D&D, to the point where a party can spend thirty minutes meticulously checking a single room for traps before seeing any combat.  And the critical hit tables are an utter monstrosity.

Critical hits (or "crits") for you non-gamers, means that for every attack there is a chance (1 in 20 under D&D rules) that it will be a super-strong attack which does extra damage.  In WoW, this is handled automatically by the game; you can build up gear that will increase your crit chance, but usually there's a flat formula that says "If you crit, your strike does twice as much damage."  Rules in 4th edition D&D are pretty close to the same.

Not HackMaster.

In HackMaster, you roll a number between 1 and 10,000 for the body part where your blow lands, and there are all kinds of "realistic" outcomes that result if you land a powerful blow on that body part.  Furthermore, rolling a 20 is just your cue to pull out a ginormous, six page tables full of teeny little numbers and two accompanying rules pages.  You then roll another number that might range from 1-24 to see just how badly your crit hurt the monster (or the monster's crit hurt you).

For instance, if you get hit on the top of the head, the crit damage can range from "8 extra damage" to "twice normal damage AND you lose some hit accuracy AND you lose some dexterity AND you fall down and drop everything you're carrying"... to "brain goo."  Do not pass go.

Each one of those individual clauses, by the way, is represented in the table by a little symbol like "dX" which you have to look up on a smaller table of effects.  I think you have to look at a sample to see what I'm talking about.

(Click for a larger image.)

Not to put too fine a point on it, this sounds like a game that I would personally hate playing.  But no accounting for taste, you know?  Even so, problems of managing huge sets of data are piles of fun to solve with a computer.  NO, that's NOT sarcasm, you non-programmers, that's fun.  Shut up.

So when the DM tentatively asked if it would be possible to write a program that could handle the die rolls and just spit out some nice, clean output, I said "Piece of cake!"  I wouldn't even accept his offer to pay for it.  Just like when I wrote a Sudoku solver, sometimes figuring out how to automate gameplay is more fun than actually playing.  (Disclaimer: I used to claim that Sudoku is a fun math problem and a crappy game.  Now I like playing it.  It's my Android Evo's fault, damn it... it's the perfect game for a handheld, and it has built in strategy advice.  Once I started improving at harder puzzles, there was no escape.)

And so it began.

To be continued...

Tuesday, August 23, 2011

Recruitment spam

A new category of spam has been getting worse and worse. It's recruiters. They are tapping me with impersonal job requests (i.e. "Dear Technology Professional..."). Some of them are even a bit close to my skill set, but the jobs are nothing I would ever accept. Most recent was a six month contract in Kentucky. Honestly, even if I did have any desire to move to Kentucky, I wouldn't pick up my life and move for a six month contract..

This kind of spam is particularly insidious, because I can't just label it as spam and then let the GMail filter handle it... because it kind of resembles message that I would actually like to read in the event that I need to find work again. Honestly though, it's despicably lazy of the recruiters. They're just blasting everyone they can find, probably using a spider to automatically scan resumes and send out the messages without regard for location or a very good match. Argh.

Monday, August 1, 2011

On learning to love your users, who are idiots

In the process of discussing error checking in the comments section of a recent post, I flippantly remarked that "all users are idiots." This is a sentiment that I expect all veteran programmers will have encountered or stated themselves on some occasion.

From a new programmer struggling with this problem, I hear this: "This would be a heck of a lot easier if users just weren't idiots." And of course, that is something we all wish. But then again, if we didn't have to assume user idiocy, we wouldn't be writing programs.

There's a fundamental difference between constructing a program and writing a novel or painting a picture. For static forms of media, you only have to create one thing from beginning to end. Once you've finished writing your book, it's over. For better or for worse, your characters have finished interacting with each other. They've said what they have to say. People will either like it or not like it; they may debate endlessly about what your words or images "really mean," but they can't affect its behavior.

Unfortunately, programs aren't like that. Once your release your program into the wild, users get to do whatever they want with it. And if they do something utterly crazy and your program breaks, they'll blame you.

Murphy's Law ("Whatever can go wrong, will") was written by an engineer in the 19th century, but it is used most by software engineers. It's not that everything possible will go wrong every single time your program is run. It's just that if you have millions of users (which you will if you are successful) then even a very small chance that one person will do something unexpected, must necessarily magnify into a virtual certainty that somebody, somewhere will find a way to blow up your program.

With that in mind, writing a program is just as much about covering every possible angle of what some idiot user might do to you, as it is about creating a pleasing presentation when the program is Used As Intended.

As a gamer, I have heard several interviews with voice actors who are veterans of film or television, but new to performing voices for video games. The universal sentiment seems to be "This is the craziest thing I've ever had to do. You have to perform a dozen different lines for every single scene, and they're not just different takes for the editor to select from. They're ALL USED in the game. I'll have to perform a scene featuring my dramatic death, and in the very next scene I'm alive again. I'll have to answer the same question five different ways, just in case the player decides to harass me by asking my character over and over again." And so on.

So, because we must cover every possible use of the program, we create elaborate error scenarios and use all kinds of tricks to keep the user on track. One way to handle user error is to simply give the user very strict instructions, like this: "You MUST TYPE A NUMBER from 1-100, and if you do ANYTHING ELSE, then the program WILL CRASH and that is YOUR RESPONSIBILITY." That's not very satisfying, though. People make mistakes, even people who are not idiots. It's much nicer to recover gracefully from an error. At every step, you're asking yourself: "What can go wrong here?" And then you add a clause to your program: "If bad thing xyz occurs, say something polite to guide the user back on track, and try it again."

Often, an even better solution is to tie the user's hands so he can't actually make the mistake in the first place. For example, slider bars and drop boxes exist exactly so that the user can pick an integer from 1-100 without the capability to do something stupid.

Obviously, it takes a lot of work to write a bulletproof program, and the more thoroughly you prepare for bad user behavior, the harder the work is going to be. Often you have to strike a happy medium. The smaller your audience is, the less effort you have to put into mistrusting your users. If you are just writing a program for yourself, it's probably less work to try and give good input than to write error handling routines.

Also, the more general the application, the more you have to just let the errors happen, and your only responsibility becomes to make sure the errors don't cause a crash. For instance, if you're writing a calculator program, you can't just stop all operations that divide by zero. The user might just DECIDE to divide a number by zero. You just have to tell him he made an illegal operation, and move on to the next step.

When you write a program, you're not designing a static thing for people to look at. You're designing a universe of possibilities to cover all uses. The more time you spend thinking about what an idiot might do, the better you can guarantee that you will make it a pleasant experience for those who are not idiots.

Thursday, July 14, 2011

Programming puzzle: Testing probability

I've been using the comments section of the previous post as a sort of impromptu classroom for my friend James to work out simple programming problems. Since I've got nothing else in particular going on with this blog right now, I might as well keep it up and post a more interesting (novice level) problem. So here it is.

One of my favorite puzzle books, "Aha! Gotcha" by Martin Gardner, used the game of "Chuck a Luck" to illustrate some basic probability concepts. You can read the rules and history here.

In a nutshell, the player picks a number from one to six and then places a $1 bet and rolls three dice. If your number doesn't come up, you lose the dollar. If it does come up, you keep your dollar and win $1 for each die that shows your number.

A program which implemented these rules might look like this:

What number do you bet on? 3
You rolled: 4 6 2
You lose $1!

What number do you bet on? 2
You rolled: 2 1 5
You win $1!

What number do you bet on? 1
You rolled: 1 3 1
You win $2!


Gardner concocted a rationalization for a gambler who believed that the game favors the player, and then challenged the reader to show why the argument is faulty. But if you actually write such a program, you could show empirically the the game is stacked against you.


I suggest that you do this in four phases.

Phase one: Implement a program that has output similar to the above.

Phase two: Keep track of how much total money the player has won or lost.

Phase three: Ask the player how many games he wants to play automatically. Like this:

What number do you bet on? 1
How many games do you want to play? 10
[optional: display the outcome of each game]
...You lost a total of $3!


Phase four: Have your program play a very large number of games, and calculate the average amount you lost per game.

Let me know how it goes.

Thursday, July 7, 2011

Adventures in junior programming, episode 3

Haven't been posting on this blog much lately. Since I last posted I got a new full time job at a high tech marketing firm, and also taught myself the fundamentals of both Android and iPhone programming. Interesting stuff, probably good fodder for a future post. But for now, I'd like to go over recent efforts to teach my son more programming.

We let it slip during the school year but we've picked it up again over the summer. We're doing about an hour of work several nights a week. It seems like teaching a nine year old to program irregularly is like pushing the stone of Sisyphus, since every time we take it up again, I have to re-teach concepts that seemed to stick the last time but didn't. Nevertheless, my feeling about programming has always been that you have to learn to "think like a programmer" first, and once you have burned this style into your memory, it becomes much easier to pick up any language or platform in existence.

So what is the core of thinking like a programmer? As far as I can sum up for a kid, it boils down to a few key elements which need to be practiced over and over under a variety of conditions:

  1. Output
  2. Tinkering with variables
  3. Input
  4. Loops
  5. Conditionals
  6. Logical operators
  7. Functions and classes, which fall broadly under the category of "splitting up the work into manageable smaller chunks."

I've fallen into sort of a systematic bootstrapping pattern of teaching, which goes something like this. I have milestones in mind for things Ben should know how to do well, and they should be second nature. The current milestone is: "Write a Python program that counts to ten." Once he can do this without hesitation and without complaining that he needs more hints, we'll bump it up and move on to another milestone.

Each session, I ask him to hit the milestone. If he can't do it well enough, I'll point out what he's missing and go over how it works again. After we get through this, if it's appropriate, I'll introduce a new concept, which we'll drill in the future until that becomes the new milestone.

I've also been making him follow the program logic step by step. It's not as intuitive as you might think. For instance, I ask him to explain HOW the computer goes through the stages of counting to ten, and this is the kind of response I'm looking for:

"First I set the counter to one. One is less than ten, so I enter the loop. I print the counter value. Then I add one to the counter, making it two. Now I return to the beginning of the loop. Two is less than ten, so I enter the loop..."

The kind of response I get takes frequent shortcuts, like "I keep doing that until it's ten." That may be technically correct, but it doesn't capture the essence of thinking through every step, which is critical to catching bugs. If you wind up writing a program that only counts to nine, or goes into an infinite loop, you can keep modifying lines until you get lucky, but if you can see what it's doing at every step, then you're less likely to make mistakes in the first place.

I don't even see the code. All I see is blonde, brunette, red-head...


Programming can seem tedious and repetitive, but at its best you get those "light bulb" moments when it's suddenly crystal clear what you want your program to be doing and how. And sometimes it's even more fun to write the code that solves a puzzle than to grind out the solution on your own.

Monday, February 28, 2011

My very late entry to mobile computing

I'm starting this post writing on my new Android phone, though I may not have the patience to finish it on this tiny virtual keyboard. (For the record, I'm using Swype to type.)

So I admit, I'm a latecomer to Smart Phone technology, having ignored the iPhone almost completely when it was in the $500 to $600 range (apart from playing with a friend's every so often). I don't much regret waiting. Although I am a geek to the core, and love my techno toys as much as the next 21st century man, I am also a cheapskate at heart and don't like to overpay for the privilege of early adoption. My problem with the phones has been not just the initial cost, but the ongoing charge on the phone bill. In this case though, after developing a healthy case of envy from seeing my dad's Android, as well as plenty of coworkers playing with their phones, I have succumbed. The price has dropped substantially, and some of the early technical problems that were apparent in the iPhone (one unreliable phone carrier, shortage of third party apps, and various other issues that you'd expect with a brand new technology) have ceased to be a concern.

The highest tech handheld device I had before a couple of weeks ago was an iPod Nano that was a few years old, and the main interface was the five button scroll wheel. Many years ago I had a somewhat Palm Pilot with a miniature keyboard and a wifi connection, but it broke too many times and I couldn't justify dumping so much money into it. When my regular phone company offered me a deal on trading in my old (cracked) phone, I realized I could replace both phone and iPod in one shot, for less than an iPod Touch costs, and also get a fully featured GPS system. So I was sold.

So. Welcome, belatedly, to the 21st century. The internet now exists more or less everywhere. This is actually pretty close to the way things were going anyway, with free wifi connections being available in every household and classroom, and more and more public buildings and restaurants. The difference is that if I get lost on the freeway now, or want to look for things in my immediate area, all I have to do is park. I have a full suite of tools and it doesn't require me to go home or carry a laptop in order to access them.

I've been using personal computers since I was eight years old, and developing software for nearly as long (BASIC, then Pascal and C in high school). At that time, everything was pretty much self-contained. Last year I reposted Tim O'Reilly's talk on the "Internet Operating System." Part of what Tim was talking about was the fact that programs now tap into a massive infrastructure of other programs that already do stuff, and that makes it easier to just hook it up into new applications without rewriting everything.

For instance, Google did not have to write a new map program just to get navigation to work on the Android. Due to the success of Google Maps and Google Earth, they've been harvesting information for years already, from satellite photos to detailed street maps to (as I am now seeing) data mined patterns indicating exactly where and when traffic is heaviest on each day of the week. So the Android Navigation program mainly represents a new interface on an existing product.

It is, of course, neat that my Android has lots of local space. Eight gigabytes of memory totally dwarfs the computers we had in the early 80's. Our first computer had no hard drive, and had to read everything off of floppy disks with a capacity of 140 KB. Our first hard drive had, I think somewhere around 10MB of space, which seemed like a huge amount of storage at the time. My Android could host that hard drive's contents 800 times, while fitting comfortably in my pocket, and doesn't make all that noise.

But as cool as that is, it's important not to underestimate the power of having your programs tap into information that's just floating around in the air. The accumulated map and satellite data from Google obviously would not come close to fitting in a phone. But I only need a small amount of local data at any given time to support the navigation system. Everything else is handled by services hosted on web servers that are "out there" somewhere, and supply just as much data as I need to find my way around at the immediate moment.

This technology, which seemed so cutting edge and exotic to me a couple of years ago is now, apparently, a commonplace app. I already downloaded it. You hold a bar code up to the phone, and it scans it, and then in a few moments you can pull up Amazon reviews and comparison shop. This actually makes physical bookstores more interesting again, as one of the main reasons I liked shopping online was the ability to jump to all the associated data that was available.

Anyway, I'm pretty enthusiastic to see the sort of horizons that have opened up now that I've got mobile computing, and I'm already experimenting with the Android SDK to see if I can, for starters, port some of the little Java games I already wrote to a new platform. Hate to sound even more geeky than usual, but it's an exciting time we live in.



(Final note: I did stop Swyping this post about halfway into the second paragraph.)

Monday, November 29, 2010

Retrospective on my first do-it-yourself computer experience

I've always considered myself a software geek, and in the past I've had no desire to fool around with hardware beyond the occasional RAM upgrade or extra hard drive. However, so many friends have reported positive experiences with building their own computers, that I decided I really needed to try it.

I was pushed to hurry along this path when my old desktop's hard disk got corrupted and I could no longer run Windows. I was planning to pull the data off and reinstall, but I still recognized that it was time to replace the old eight year old system. Since I got a new laptop a year ago, my old computer was mostly sitting dormant, used occasionally to recover documents and sync my iPod with music that I've recorded and rated from my CD collection over the last several years.

A Facebook friend gave me some words of wisdom: You will not save money by building your own computer. Not because the parts won't be cheaper -- they will! But when you buy them individually, it's impossible to resist the siren call of "100 more watts of power couldn't hurt!" or "Gosh, this terrabyte hard drive is not nearly twice as expensive as the 500GB, how can I pass that up?" or "I'm saving money! A little more muscle in the graphics card? Why not?"

So you'll spend just as much as you would for a prefab desktop, but you will get more than you would have for your money. And then there's the "priceless" category, which is pride in creation, as well as a better understanding of what's going on under the hood of all future computers you may work with.

Another friend who used to build and test hardware for Dell pointed out that I was working at a severe disadvantage as a first timer. An experienced or professional builder will have lots of spare parts lying around to swap out and help test the machine. Nothing's on the screen, is the graphics card okay? Put in a different card and find out. Etc. I had to debug all my problems with just one set of parts, as my other PC was much too old to have any compatible bits.

Phase 1: Shopping spree

The first thing I did right was, instead of buying a motherboard, case and power supply online, I went down to the local Fry's and chatted up an extremely knowledgeable clerk. With all the dire warnings I'd heard about messing up compatibility requirements, I just didn't want to take the chance of guesswork. Before I went, I bought a short trade magazine about building a computer by PC Gamer. I read it thoroughly. They of course recommended a ridiculously overpowered and overpriced system, but later in the book they had some recommendations for working on a budget. They came up with something for under $600, but this estimate is a bit deceptive because it doesn't include an OS or any peripherals like a monitor.

Anyway, I read this thoroughly and dog-eared the page full of cheap stuff, figuring this to be a minimum benchmark for what I can buy. Then I brought the list to the Fry's guy, and I said "I am prepared to spend several hundred dollars today. Pay attention to me!" Basically I went through each item on the "cheap" list, and asked the following questions:
  1. Do you have this particular part?
  2. If not, what do you have that's comparable in price and performance?
  3. What would I get by spending more on a better part?
  4. How likely is it that I will need that extra power?
  5. (In some cases) That's more expensive than the guide implies. Can I get it cheaper on New Egg?

Your mileage may vary, but this guy was extremely helpful, and didn't try argue too hard to get me to buy only at Fry's or to buy stuff that was more powerful than I needed. In fact I only wound up buying a motherboard and case that day, and I left armed with a list of precise specs that would be compatible with the mobo, and deals to look for on New Egg. (For example: "That CPU you're looking for is absolutely the best thing in that price range," he said. "In fact it's so popular that it's been out of stock for weeks. Go look for that exact thing on New Egg and see if you can find it at the price you want." And I did.) I was so happy with the experience that I made a point of coming back when I needed some odds and ends, like a keyboard and a replacement hard drive.

It happens to be the holiday season, so it seems like New Egg had even more combo details and discounts than usual, or so they told me via email every single day. You just have to know approximately what you're looking for, and then keep an eye out for discounts with other parts you're looking for. Hard disk may be paired with Windows 7. Graphics card may come along extra RAM. Stuff like that. $10-$20 savings here and there adds up, or as I warned, encourages you to buy slightly more power. :)

Phase 2: Construction

In addition to getting friendly with a retail guy, it's always a good idea to identify a friend or coworker who has done this before and can guide you through it. If your workplace makes this likely, talk to everyone about your intent and see what kind of feedback they get. A guy who works in QA here is my new best friend. :)

Building the computer was both less complicated and more nerve wracking than I expected. I was frankly terrified of making mistakes, and I did make mistakes. I was curious about the CPU connections, and brushed it with my finger before remembering that you NEVER EVER TOUCH THE PINS. Similarly, I couldn't find a tube of thermal grease that my magazine claimed would come with either the CPU or motherboard. It wasn't until I poked the underside of the CPU cooler and came away with sticky fingers that I realized the stuff was pre-applied, and now I was afraid I'd contaminated and ruined it somehow. I forgot to put on my static wrist strap several times. I dropped the graphics card a little too hard as I was pulling it in and out so often. Luckily, the computer parts are considerably less fragile than I had feared. Not that they aren't fragile, but they can take a few knocks. (Except hard drives. The drive I bought from NewEgg made clicking noises and didn't get detected, which is why I wound up returning it and buying a replacement.)

Figuring out how many parts need power was also a challenge. I initially thought my power supply was busted because nothing happened when I simply plugged it in -- no fan action or anything. Turns out it needs to be hooked into the computer's power button or else it doesn't get an "on" signal. Also, count the number of fans and make sure they are ALL running. My case has two built in, with space to install another one. The CPU has its own fan; the graphics card has its own fan; and the power supply has an intake fan. At first I had plugged the fan into the power supply, but my QA friend pointed out that you are supposed to plug them into the motherboard so it can sense the temperature and regulate the fan speed.

The CPU needs power, and the mobo needs two cables plugged in SNUGLY (loose cables were also a hallmark of the experience). Then there are all the little things like LEDs and USB power supplies, which seem intimidating at first (lots of cables!) but the motherboard's manual is very specific about what goes where. It's not so bad. Just don't forget to find the loose parts you need, like a tiny speaker.

Miscellaneous stuff I learned

  • If you haven't upgraded your system for a while you may be surprised to learn what is built in standard to motherboards these days. You used to need to plug in a sound card and a network card; now you don't. I bought a sound card, and I'm installing it because it's a cheap part that is not much worth returning. But the built in sound works fine for the most part.
  • The BIOS may take a long time to appear on screen the first time you start it up. Give it a couple of minutes.
  • If your graphics card has two ports, they are not necessarily interchangeable. One is for the primary monitor, and the other is for a dual setup. Make sure your monitor is plugged into the right one.
  • The first sign that you are doing something right is if it beeps. Make sure the little internal speaker is set up. Don't put in RAM right away, because when it's out you will hear beeps indicating an error. At that point, you know your motherboard is probably okay.
  • All you have to do with the new system is drop in a CD for the operating system of your choice and watch it go. There is no other initial prep work (I thought i would have to screw around in the BIOS more).
  • Don't talk too much about your issues on Facebook, because an army of annoying drones will tell you to switch to Mac. They can STFU if they're not planning to play grown-up games or develop software. :)

Specs

Case: Cooler Master HAF 912
Motherboard: MSI 870-G45
CPU: AMD Phenom II X2 555 Black Edition Callisto 3.2GHz Socket AM3 80W Dual-Core
Power supply: COOLER MASTER Silent Pro M700 RS-700-AMBA-D3 700W
Hard drive: Seagate Barracuda 7200.12 ST31000528AS 1TB (actually that's the one that died and got replaced; the new one is Toshiba or something)
Mouse: RAZER Lachesis Banshee Blue 9 Buttons 1 x Wheel USB Wired Laser Gaming Mouse
RAM: G.SKILL Ripjaws Series 4GB (2 x 2GB) 240-Pin DDR3 SDRAM DDR3 1600 (PC3 12800)
DVD: SAMSUNG CD/DVD Burner Black SATA Model
OS: Windows 7 64 bit Home Premium
Graphics: SAPPHIRE 100284L Radeon HD 5750 1GB 128-bit GDDR5 PCI Express 2.0 x16

The Gaming Experience

Sure, I've installed Eclipse and JBoss on the new box, and I'm enjoying the fact that I won't be coming close to filling up the hard drive for a long time. Compiling programs is nice when it's fast, but don't let me lie to you; the real benefit of a new system is the games.

For a moderate priced system it runs great. I've been playing World of Warcraft at "Ultra" graphics settings with hardly any drop in the full 60 FPS. Of course, WoW is not such a graphics intensive game, but with the new changes in place for Cataclysm, it looks pretty nice: the water has good distortion effects, you can see stuff in the landscape that is a good half a zone away; and the spell effects really sparkle.

With Starcraft II it's hard for people who don't play to notice the difference, since the view is set such a long distance from the action. When playing though, you can see enormous detail in the units, and the glowing effect of workers carrying minerals and gas is a nice bonus. Also, the Machinima in-game cutscenes are noticeably worse than the pre-rendered movies on a slower machine. With higher settings, they are still different but still pretty impressive.

Left 4 Dead 2 looks great and benefits enormously from running quickly.

I'm a pretty satisfied customer of the experience, and again, it's not so much the newness of the machine as the pride of ownership.