views:

224

answers:

3

Hi, what would be the best way to implement kind of cheat codes in general? I have WinForms application in mind, where a cheat code would unlock an easter egg, but the implementation details are not relevant.

The best approach that comes to my mind is to keep index for each code - let's consider famous DOOM codes - IDDQD and IDKFA, in a fictional C# app.

string[] CheatCodes = { "IDDQD", "IDKFA"};
int[] CheatIndexes = { 0, 0 };
const int CHEAT_COUNT = 2;
void KeyPress(char c)
{
    for (int i = 0; i < CHEAT_COUNT; i++) //for each cheat code
    {
        if (CheatCodes[i][CheatIndexes[i]] == c)
        { //we have hit the next key in sequence
            if (++CheatIndexes[i] == CheatCodes[i].Length) //are we in the end?
            {
                //Do cheat work
                MessageBox.Show(CheatCodes[i]);
                //reset cheat index so we can enter it next time
                CheatIndexes[i] = 0; 
            }
        }
        else //mistyped, reset cheat index
            CheatIndexes[i] = 0; 
    }
}

Is this the right way to do it?

Edit: Probably the worst thing I should have done was to include the first cheat codes that came from the top of my head as an example. I really did not want to see Doom's source code or their implementation, but general solution to this problem.

+10  A: 

Why not download the DOOM source and see for yourself? =) http://www.doomworld.com/idgames/?id=14576

MHarrison
basically it's about the same, albeit more structured and elaborate. But what else can one expect from ID soft :)
Axarydax
Their code is indeed giving me a whole new respect for that game.
MHarrison
Haha. I always love when a smart-ass answer like this is really the best solution to the problem +1
Billy ONeal
+5  A: 

I think this one's a bit easier to understand, though your original will probably perform better than this one:

using System.Collections.Generic;

void KeyPress(char c)
{
    string[] cheatCodes = { "IDDQD", "IDKFA"};
    static Queue<char> buffer; //Contains the longest number of characters needed
    buffer.Enqueue(c);
    if (buffer.Count() > 5) //Replace 5 with whatever your longest cheat code is
        buffer.Dequeue();
    bufferString = new System.String(buffer.ToArray());
    foreach(string code in cheatCodes) {
        if (bufferString.EndsWith(code)) {
            //Do cheat work
        }
    }
}
Billy ONeal
but your code won't probably work with variable length codes, would it?
Axarydax
@Axarydax: Sure it works. Check again :)
Billy ONeal
my bad. I didn't see the "EndsWith" part ;)
Axarydax
@Axarydax: That was a joke lol -- I edited the endswith part in later. See the edit history for the original.
Billy ONeal
you're lucky that I read your comment after the edit was done :)
Axarydax
+1  A: 

here is the DOOM cheat implementation from the doom source:

#define SCRAMBLE(a) \
((((a)&1)<<7) + (((a)&2)<<5) + ((a)&4) + (((a)&8)<<1) \
 + (((a)&16)>>1) + ((a)&32) + (((a)&64)>>5) + (((a)&128)>>7))

int cht_CheckCheat ( cheatseq_t* cht, char key )
{
    int i;
    int rc = 0;

    if (firsttime)
    {
        firsttime = 0;
        for (i=0;i<256;i++) cheat_xlate_table[i] = SCRAMBLE(i);
    }

    if (!cht->p)
        cht->p = cht->sequence; // initialize if first time

    if (*cht->p == 0)
        *(cht->p++) = key;
    else if
        (cheat_xlate_table[(unsigned char)key] == *cht->p) cht->p++;
    else
        cht->p = cht->sequence;

    if (*cht->p == 1)
        cht->p++;
    else if (*cht->p == 0xff) // end of sequence character
    {
        cht->p = cht->sequence;
        rc = 1;
    }

    return rc;
}
mkoryak
Nice...........
zaf