I appreciate all the compliments, everyone!
Since I posted the code over at the adafruit forum, I'll post it here as well. I'm not normally a programmer, so this is the result of what I've learned around here. Comments are welcome, but be gentle. 
/*
This is a sketch for a robot costume for a little kid.
Jerry Adlersfluegel
10/2009
Using Arduino 17, on an Arduino Diecimila with ATmega328
Costume features:
Chaser LEDs surrounding the Aruino. People will want to know how it all works,
so we want to show off the fact that there's a computer in there. Will be
mounted on the back of the costume, so this will also be a visibility safety
feature.
Candy input slot / Analog gauge. There is an electric eye in the input slot
(with a .75 sec debounce/guard time), and the gauge indicates that candy has been
received, climbing higher with each piece inserted, until the desired amount of
candy has been exceeded, at which point the giver will be rewarded with the
gauge going crazy! (That is, the needle will swing back and forth wildly.) Then,
after an amount of time, the gauge will reset, so the needle is back to 0 at the
next house. This time is enough to get a laugh without showing the giver that it
resets, but not so long that the next house sees the needle still going crazy.
Sound effects via Adafruit Wave Shield. There's an idle loop playing robot
beeps, which gets interrupted by candy input. When the candy count increases,
there is a synthesized speech recording that will be played, a different one for
each quantity. When playback of one of those files completes, the idle loop
starts again.
[Still need to document the circuits.]
*/
// scheduler library http://www.arduino.cc/playground/Code/Scheduler
#include <Scheduler.h>
// LED library http://www.arduino.cc/playground/Code/LED
#include <LED.h>
// Button library http://www.arduino.cc/playground/Code/Button
#include <Button.h>
// library for doing things periodically http://www.arduino.cc/playground/Code/TimedAction
#include <TimedAction.h>
// libraries and includes for wave shield
#include <AF_Wave.h>
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"
// stuff for wave shield
AF_Wave card;
File f;
Wavefile wave; // only one!
// stuff for the analog gauge
const int GaugePin = 6; // pwm pin for driving analog gauge ** found out you can't use pin 9 for pwm w/wave shield!!
// create an LED object for the gauge, since we're using it like an LED, kinda sorta
LED Gauge = LED(GaugePin); // also, this object removes the need to put anything for it in the setup()
TimedAction GaugeReward = TimedAction(250,CandyOverloadIndication); // to set interval for toggling the gauge
// stuff for the candy input sensor
const int CandyInputPin = 7; // pin for the input of the IR sensor - SEN-00241 from sparkfun
// create a button object for this input.
Button CandyInput = Button(CandyInputPin, PULLDOWN); // again, no setup() required
int CandyCount = 0;
boolean CandyInputBlocked = false; // used to prevent one piece from being overcounted, sort of a debounce
const int CandyGoal = 3; // how much candy to beg for at each house; number of steps on the gauge
boolean CandyIsOverloaded = false; // used in indicating if extra candy was collected
// scheduler object used to reset the candy counter after an amount of time, so it's zeroed at the next house
Scheduler CandyCountResetTime = Scheduler();
Scheduler CandyInputDebounce = Scheduler();
// stuff for the LED chasers
const byte NumberOfChasers = 6;
const byte ChaserInterval = 1000;
LED Chaser[NumberOfChasers] = {
LED(14), LED(15), LED(16), LED(17), LED(18), LED(19) }; // using the analog inputs as digital outs
byte CurrentChaserLED = 0; // keep track of which chaser LED is current
TimedAction ChaserAction = TimedAction(ChaserInterval, ChaserUpdate); // create protothread for running the chaser
void setup()
{
Serial.begin(9600);
// wave shield pins
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
if (!card.init_card()) {
putstring_nl("Card init. failed!");
return;
}
if (!card.open_partition()) {
putstring_nl("No partition!");
return;
}
if (!card.open_filesys()) {
putstring_nl("Couldn't open filesys");
return;
}
if (!card.open_rootdir()) {
putstring_nl("Couldn't open dir");
return;
}
//
// putstring_nl("Files found:");
// ls();
// initalize the chaser LEDs. We want all on except the first one
//
// turn each Chaser LED
for(int i=0; i < NumberOfChasers; i++)
{
Chaser[i].on();
}
// and then flip the first one
Chaser[CurrentChaserLED].toggle();
playfile("0IDLE.WAV");
}
void loop()
{
// Serial.println(CandyCount);
ReadSensors();
UpdateGauge();
GaugeReward.check();
ChaserAction.check();
CandyCountResetTime.update();
if(!wave.isplaying)
{
card.close_file(f);
playfile("0IDLE.WAV");
}
}
// Read the values of all sensors, and set variables that reflect their states.
void ReadSensors()
{
// check if the candy sensor sees candy now, and didn't last time. If so, increment the candy count
if (CandyInput.isPressed() && CandyInput.stateChanged())
{
CandyInputDebounce.update();
if (!CandyInputBlocked) // during the debounce period, don't do anything with this input
{
CandyCount++;
// also, schedule a time to reset CandyCount to 0, after clearing the schedule queue
CandyCountResetTime.clear(); // clear the Scheduler queue
CandyCountResetTime.schedule(ResetCandyCount, 20000); // 20 sec in milliseconds
CandyInputBlocked = true; // to prevent input from being read
CandyInputDebounce.schedule(ResetCandyInputDebounce, 750); // schedule a .75 second debounce of candy input
// and finally, play a sound associated with this qunatity of candy
switch (CandyCount)
{
case 1:
playfile("1CANDY.WAV");
break;
case 2:
playfile("2YUM.WAV");
break;
case 3:
playfile("3THANKS.WAV");
break;
case 4:
playfile("4OVER.WAV");
break;
default:
break;
}
}
}
}
void playfile(char *name)
{
if (wave.isplaying) {// already playing something, so stop it!
wave.stop(); // stop it
card.close_file(f);
}
f = card.open_file(name);
if (!f) {
putstring("Couldn't open file ");
Serial.print(name);
return;
}
if (!wave.create(f)) {
putstring_nl("Not a valid WAV");
return;
}
// ok time to play!
wave.play();
}
// set the value the gauge displays
void UpdateGauge()
{
if (CandyCount <= CandyGoal)
{
// set the gauge to the progress towards the candy goal. map() that to the PWM range 0-255
Gauge.setValue(map(CandyCount, 0, CandyGoal, 0, 255));
CandyIsOverloaded = false;
}
else
{
CandyIsOverloaded = true;
}
}
void CandyOverloadIndication()
{
if (CandyIsOverloaded)
{
Gauge.toggle();
}
}
// fuction to reset the candy input counter
void ResetCandyCount()
{
CandyCount = 0;
CandyIsOverloaded = false;
}
// function to flip the current chaser, increment the current value, then flip the next LED
void ChaserUpdate()
{
Chaser[CurrentChaserLED].toggle();
CurrentChaserLED == NumberOfChasers - 1 ? CurrentChaserLED = 0 : CurrentChaserLED++;
Chaser[CurrentChaserLED].toggle();
}
// function to clear the candy input blocked flag
void ResetCandyInputDebounce()
{
CandyInputBlocked = false;
}