#define light SENSOR_1 #define touch1 SENSOR_2 #define touch2 SENSOR_3 int HighScore[4]; int NewDisp, OldDisp; int Key; int KeyTimeOut; int Level; // Play level int EasyDir; int OldRnd=0, ValRnd; int UserDisplay; int Dark; int Bright; task main () { int RndSeed; int LostGame=false; int Sequence; int i; int TimeOut; int FlagHiScore = false; SetSensor (light, SENSOR_LIGHT); SetSensor (touch1, SENSOR_TOUCH); SetSensor (touch2, SENSOR_TOUCH); SetUserDisplay (UserDisplay, 2); // initializes light sensor thresholds i = light; Dark = light + 4; // Between black and gray Bright = light + 14; // Between gray and yellow // Waits for level choice. // Blue key selects level 1 (easy) // Red key selects level 2 // Yellow key selects level 3 // Green key selects level 4 (hard) KeyTimeOut = 200; start ShiftDisplay; GetKey(); stop ShiftDisplay; if (Key == -1) { PlaySound (SOUND_DOWN); // No key pressed, StopAllTasks (); // Halts program } Level = Key + 1; UserDisplay = Level*1111; PlaySound (SOUND_FAST_UP); PlaySound (SOUND_FAST_UP); Wait(100); OldDisp = 5; RndSeed = FastTimer(2); SetRandomSeed(RndSeed); EasyDir = 2 * Random(1) - 1; Sequence = 1; switch (Level) { case 1: TimeOut = 200; // response time = 20s break; case 2: TimeOut = 20; // response time = 2s break; case 3: TimeOut = 10; // response time = 1s break; case 4: TimeOut = 4; // response time = 0.4s break; } do { SetRandomSeed(RndSeed); OldRnd=0; // display score.HighScore UserDisplay = 100*Sequence + HighScore [Level-1]; for(i=0; i HighScore[Level-1]) && (FlagHiScore == false) && (LostGame==false)) { FlagHiScore = true; // Got a high score... PlaySound (SOUND_FAST_UP); // play tune PlaySound (SOUND_FAST_UP); PlaySound (SOUND_FAST_UP); Wait(150); // wait for sound } Sequence += 1; } while (LostGame == false); // Game lost... Sequence -= 2; // Remove last increment AND lost level if(FlagHiScore) HighScore[Level-1] = Sequence; UserDisplay = 100*Sequence + HighScore [Level-1]; if(Key==-1) PlaySound (SOUND_LOW_BEEP); Wait(20); PlaySound (SOUND_DOWN); Wait(200); StopAllTasks (); // Halts program } //----------------------------------------- // Animates RCX display while waiting for // Level choice task ShiftDisplay () { while (true) { UserDisplay = 1234; Wait(50); UserDisplay = 2341; Wait(50); UserDisplay = 3412; Wait(50); UserDisplay = 4123; Wait(50); } } //----------------------------------------- // Returns a random value in ValRnd. // if level=1 (easy), the generator tends to produce // sequences of successive numbers // if level=1 or 2, successive values are different. sub NextRnd () { switch (Level) { case 1: if (Random(3) > 1) ValRnd = (OldRnd + EasyDir) & 3; else do ValRnd = Random(3); while (ValRnd == OldRnd); break; case 2: do ValRnd = Random(3); while (ValRnd == OldRnd); break; default: ValRnd = Random(3); } OldRnd = ValRnd; } //----------------------------------------- // Reads keyboard value, returned in "Key" // Response time is limited by the value // in KeyTimeOut * 0.1s. // returns -1 if timeout. #define NoteTime 30 sub GetKey () { Key = -1; ClearTimer (1); while ((Key == -1) && (Timer (1) < KeyTimeOut)) { if(touch1 == 0) { Key = 0; PlayTone(262,NoteTime); } else if(touch2 == 0) { Key = 3; PlayTone(494,NoteTime); } else if(light > Dark) { Wait(10); if (light > Bright) { Key = 1; PlayTone(330,NoteTime); } else if (light > Dark) { Key = 2; PlayTone(392,NoteTime); } } } // wait for key release while ((touch1 == 0) || (touch2 == 0) || (light > Dark)); } //----------------------------------------- // Displays the present value. // If value is the same as previous, moves // slightly the hand and comes back #define DispH OUT_C #define DispL OUT_A #define DispTime 30 // The motors are used at a very low power setting // to avoid breaking things #define DriveLevel 1 #define HoldLevel 0 sub Display () { if(NewDisp == OldDisp) { SetPower (DispL,DriveLevel); SetPower (DispH,HoldLevel); Toggle(DispL); On (DispL + DispH); Wait(DispTime/3); Toggle(DispL); Wait(2*DispTime/3); Off (DispL + DispH); } else { if((NewDisp & 1) == (OldDisp & 1)) SetPower (DispL,HoldLevel); else SetPower (DispL,DriveLevel); if((NewDisp & 2) == (OldDisp & 2)) SetPower (DispH,HoldLevel); else SetPower (DispH,DriveLevel); if((NewDisp & 1) == 1) Rev (DispL); else Fwd (DispL); if((NewDisp & 2) == 2) Fwd (DispH); else Rev (DispH); On (DispL + DispH); Wait(DispTime); Off (DispL + DispH); } OldDisp = NewDisp; switch (NewDisp) { case 0: PlayTone(262,NoteTime); break; case 1: PlayTone(330,NoteTime); break; case 2: PlayTone(392,NoteTime); break; case 3: PlayTone(494,NoteTime); break; } Wait(NoteTime+20); }