Soul Calimeter

There's a lot of info here, but if you just want cool stuff, you can scroll down to the Web Site and Commentaries section at the bottom.

After playing Soul Calibur just about every day for over three years, my coworkers and I grew tired of wondering what our stats were in the game.  We needed a system that could track our stats but that wouldn't be annoying to use.  We tossed around a couple ideas but decided to try out a system based on video capture to see if it would be able to analyze the video feed from the GameCube and look for certain key events to occur -- character selection per controller, fight start, end game events (KO, Perfect, Ring Out, etc), health changes, and win changes.  Well it turns out that it worked, and with those pieces of data captured off of the video combined with a game manager that is in charge of the circuit rules (maximum allowable time for play, maximum number of fights, etc) and the rotation (winner stays, loser stays, etc), the computer is able to track player stats in realtime.  Toss in a database for saving the stats, a web front-end for analyzing stats and starting circuits, voice synthesis using AT&T Natural Voices for commentaries, and some cool API's, and you've got yourself a tracking Soul Calibur with live computer-generated commentaries responding in realtime to events happening in the fight.  That's Soul Calimeter.

The System
The key feature of Soul Calimeter is its ability to take the live gameplay video and look for important events.  The system tracks events such as character selections on the character selection screen, fights beginning, health increasing and decreasing, wins increasing, and end game events.  Each of these events is useful in determining various statistics both for comparison of player performance as well as fodder for the computer commentators (Bob and Nancy) to talk about.

The Video Capture system was built on the cheapest piece of crap capture card that I could find -- which turns out to be a $25 WaveWatcher card with a Bt878 chipset.  The most important part was getting a reasonably clean video feed -- the SVideo input on the card proved to be pretty important (roughly 3x more reliable detection of video events as compared to composite input).  The app was originally implemented on Windows using the Java Media Framework's standard VFW-based video capture API's.  The VFW implementation proved too unreliable, so a JMF wrapper was written around Microsoft's DirectShow API's to provide for more dependable capture as well as to allow us to programmatically change the video source on the card (which JMF/VFW doesn't support).

The soul calimeter box is a 1Ghz Athlon with 512M of RAM running Tomcat as the webserver.  The stats database originally was MySQL, but MySQL's current stable releases did not support the complexity of query capabilities needed to run the stats analysis.  It has since been run on Mckoi (a pure Java database that kicks ass) for development and Oracle 9i in "production".

Speech synthensis for commentaries is built with the Java Speech API on top of CloudGarden's TalkingJava SDK.  The voices are AT&T Natural Voices, which sound awesome, but aren't very expensive.

The Stats
The stats was really the main thing we wanted out of Soul Calimeter.  We wanted to know who's kicking who's ass, how badly, and with which characters.  Once we got the basic system, we realized the amount of analysis is pretty endless.  We can currently run the following stats in realtime:

Duration By Person - show the number of minutes that each person has played

Fights By Person - shows the number of fights each person has played

Fights By Character - shows the number of fights each SC character has played (turns out the Random option really isn't so random)

Win Percentages by Person - shows the win/loss percentages for each person

Win Percentages by Character - shows the win/loss percentages for each SC character

Win Percentages By Person Matchup - shows the win/loss percentages given two people player eachother

Win Percentages By Character Matchup - shows the win/loss percentages given two characters against eachother

The cool part is that we track down to each health change, so there's tons more anaylsis to be done and we are building up a huge database of tracking data, so we can add new stats at any time that can run on the historical data.

Circuits and Rotations
Currently, the computer can't identify which people are playing and which controllers they have (this is being worked on), so the computer has to be in charge of handing out the controllers to the appropriate people after each game.  The computer has several different sets of circuits -- a timed circuit, a race-to circuit (like "race to 5"), never-ending circuit, and a circuit that implements some custom rules we play by.  In addition, the computer has a rotation that determines who gets the controller after each game.  The rotation implements rules like Winner Stays, Loser Stays, etc.

The Web Interface
This is where things start to get cool.  Here are some screenshots from the Soul Calimeter web interface:

The Main Screen - This is the front screen from Soul Calimeter that has a couple high level stats on it.

Circuit Setup - When you want to create a new circuit of games, this is the screen you use.  This allows you to pick the people that will be playing during the circuit and the ruleset you want to use for the games.

Most Recent Game - This shows the most recently played game, or if there is a current game, this shows realtime data from the game as you reload.  These screenshots are from my local version, so the data shown is from one of my testcases rather than real data, but you get the point. Oh yeah -- "controler" is spelled that way because it sounded better when the voice says that spelling.

Stats - And of course, where the rubber meets the road.  These are the stats.  There's more data analysis to be done than time in a day.  We actually have more stats implemented than are shown here, but they're currently only used by the commentators and haven't been hooked up to the stats page.

Random? - And when you choose "Random", if you've ever felt like it's not really random then you're probably right.  Here's the data we've collected on it.  You can see it's pretty terribly distributed.  We'll just have to see if it levels out over time.

Commentaries
OK -- I think the commentaries are the coolest thing, so I've kept them till last.  The API for Soul Calimeter was designed so that it would be really easy to add in new commentaries.  Currently we only have two AT&T Natural Voices (Mike and Crystal, which we have dubbed Bob and Nancy), so we only have the witty banter of the two of them, but it's designed to support an arbitrary number of "commentators".  The commentators can respond to any of the trackable events -- fights starting, games ending, KO's, Perfects, health changing, etc.  In addition, several commentaries are time-based, or triggered by an impending scenario.  A commentary can queue up a single comment by a particular commentator, or it can queue up a discussion between the two commentators.  An example commentary that occurs when one player is getting his ass kicked is "1: {fight.winner.person} just beat {fight.loser.person}'s ass.; 2: Just like I did to your mom last night {commentator1}.".  The {..} are variables that are replaced at runtime.  The 1:/2: specifies which commentator should speak (they can be randomly chosen to mix up the voices).

Some of the commentaries we've implemented include a choke alarm (if a player starts losing a huge lead), "finish him" (when a player has a tiny amount of health left), demanding a perfect (if one player has all his/her health and the other player is very low, the commentators can request a perfect and will respond pleasantly or with disappointment depending on the fight outcome), and stats commentaries -- these can be queued up to run at random times so that the commentators can point out that "Schrag with Ivy has never beaten Adam with Kilik", or that "Adam wins 53% of his fights", etc.

Lastly, commentaries can be generated off of JSGF grammars, which can be built up to generate incredibly complex commentary scenarios.  The grammars can include variable replacement like the example above.

Here are some sample recordings of commentaries.  These particular recordings are from my test cases as well, so they have some debug speaking at the front of the clips setting up the scenario.

Ass Kicking - This is a commentary that is triggered by someone getting his ass kicked

Choke Alarm - This is a commentary that is triggered by someone losing a huge lead (60% lead to a 10% loss)

Block Fest - This is a commentary that is triggered by at least 10 seconds without a hit on either side.  This one is kind of cool because the test case sets up an entire fight, so you hear a random stat at the beginning as well as some trash talk -- this is more like what a real fight sounds like (albeit compressed into a very short time period).

What Now?
The system is pretty darn reliable.  We only know of about 10 out of our over 300 fights that have had the wrong character detected (it sometimes detects the character as "Random" if we click really fast through the character selection screen, because it doesn't have time to process the switch from the Random box to the randomly selected character).  As far as in-fight data, we very occasionally (even less than the 3% misdetection of characters) get a missed Fight Start event, so it thinks the second fight is the first fight, but it generally recognizes the win count properly anyway and in the worst case will just clean itself up when it ends up back at the character selection screen.  It tries to throw out game data in that case, since it is suspect.  There are a couple steps that we can take to clean up these last few accuracy problems -- specifically the occasional first start problem.

The biggest thing for us at this point is adding in new rulesets, adding commentaries, and adding new stats to track.  Some of the newer commentaries will actually choose discussions based on stats (for instance, it might make predictions based on the players, etc) rather than to just look at in-fight events or raw stats speaking.  We've also talked about having the commentators choose favorites and talk trash about the other player.  I already tell Bob to fuck off when he tells me that "to be the man, you have to beat the man", so the commentaries are pretty effective.  It's even more infuriating when you know when Bob or Nancy talks shit to you that it's based on hard facts.  So when Bob says you got your ass kicked, you really did get your ass kicked.

As far as releasing the app, we don't know what direction we want to go.  The video detection has only been tested on the card we have and with a GameCube.  Obviously the detection system will need to be made more resilient to deal with changes in color, noise, scale, etc as you move among cards and game consoles, but the basic system is there and we use it everyday, so we know it works.  Part of putting this page up is to see if we get any response at all from people about using this app for their own SC fights.  If there's no interest at all, we'll just happily track our own stats; but if it looks like other people might be interested, we'll take a look at making it more releasable.

For info/questions/comments about Soul Calimeter, contact mschrag@cavtel.net .

Some Updates
Since it got submitted to Slashdot I figure I should go ahead and write up the latest and greatest info.

First I wanted to point out that Soul Calimeter has been a collaborative effort with my coworkers Adam Rabung and Mel Riffe.  Many thousands of fights have gone into perfecting the system :) (for work people -- just append "during lunch" to every sentence on this page)

The DirectShow/JMF interface (binaries and source) is available at java.net for anyone who is interested ( http://jmds.dev.java.net ).  It can be a little finicky if you don't shutdown everything just right, but it has been working really well for us (granted we don't actually shut it down ever).

The stats and commentaries have been expanded since I wrote this up -- there are about 3 or 4 more reports and an additional 3 or 4 commentaries than are listed here.

The last cool technology addition is that we have a much slicker system for identifying players now.  I ordered a set of iButtons for everyone (the ID-only ones) and a USB iButton reader (which has a really nice Java API -- I was shocked -- I fully expected it to suck).  So now whoever is playing can just put their iButton in the reader when they come in the room and it will lookup their ID in the db and add the person to the circuit (or remove the person if you put your iButton in again during an active circuit).  Before, we had to setup who was in the circuit using the web interface, which always sucked if someone had to leave early.  Now people can just logout when they need to leave and they get removed from the circuit on the fly.

The last piece I'd like to bring into the mix is the Zaurus w/ wireless so it's easier to get stats on-demand.  When you're playing, sometimes a discussion arises about a particular stat, and it would be nice to be able to just run the query right there.  Beyond that, I'm starting to run out of ideas :)