/// puzzlebox.c: Inputs are read from a file on the command line. The /// inputs are modified in various ways to checked to match specific /// patterns associated with "phases". Each set of correct inputs /// "passes" a phase and scores points. /// /// USING THE DEBUGGER is almost essential to understand what is /// happening in the source code. Compile with debug flags and run in /// the gdb debugger as in /// /// > gcc -g -o puzzlebox puzzlebox.c /// > gdb -tui ./puzzlebox /// /// is a good policy. /// /// Original DebugMe.java version and rhymes by Mark Snyder /// C Port/Adaptation by Chris Kauffman #include #include #include #include #include #include #define BUFSIZE 128 #define NSTAGES 10 int points[NSTAGES+1] = { 0, 8, 8, 8, 8, 5, 5, 4, 4, 5, 5, }; int score = 0; int max_score = 50; char *userID = NULL; int hash = 0; void setup(); void end_now(); void phase01(); void phase02(); void phase03(); void phase04(); void phase05(); void phase06(); void phase07(); void phase08(); void phase09(); void phase10(); int main(int argc, char *argv[]){ printf("========================================\n"); printf("PROBLEM 2: Puzzlebox\n"); if(sizeof(int)!=4 || sizeof(long)!=8){ printf("Unexpected byte sizes of int or long\n"); printf(" %5s %5s\n","EXPECT","ACTUAL"); printf(" int: %5d %5lu\n",4,sizeof(int)); printf("long: %5d %5lu\n",8,sizeof(long)); printf("\n"); printf("puzzlebox must be run on a 64-bit architecture. Bailing out\n"); return 1; } if(argc < 2){ printf("usage: %s \n",argv[0]); printf(" Provide a text file to read from on the command line\n"); printf(" The first token in the input file is your Internet ID like kauf0095\n"); printf(" Bailing out.\n"); return 1; } setup(argv[1]); printf("PHASE 1: A puzzle you say? Challenge accepted!\n"); phase01(); score += points[1]; printf("PHASE 2: That was cake by the ocean! Wait: the cake is a lie!\n"); phase02(); score+=points[2]; printf("PHASE 3: Warm-up is over. This $#!^ just go real.\n"); phase03(); score+=points[3]; printf("PHASE 4: Tired yet? Nope? There's more in phase four.\n"); phase04(); score+=points[4]; printf("PHASE 5: You're doing well. But can you break through this secret technique of darkness?\n"); phase05(); score+=points[5]; printf("PHASE 6: Watch out, here comes a wall of bricks! It's time for you to solve phase six.\n"); phase06(); score+=points[6]; printf("PHASE 7: Next it's phase eleven! oops, seven. (off-by-4 errors don't lose credit, right?)\n"); phase07(); score+=points[7]; printf("PHASE 8: You're doing great, now try phase 1000!\n"); phase08(); score+=points[8]; printf("PHASE 9: Finally, the finish line; Can you solve phase nine?\n"); phase09(); score+=points[9]; printf("PHASE 10: Rule #1: The doctor lies. Next time a message mentions 'finish line,' check the source code.\n"); phase10(); score+=points[10]; printf("***Achievement Unlocked***\n"); printf("gdb? Yeah you know me!\n"); end_now(); return 0; } void setup_signal_handlers(); void failure(char *msg); void end_now(); void setup_input(char *fname); void close_input(); char *next_input(); void setup(char *infile_name){ setup_signal_handlers(); setup_input(infile_name); userID = next_input(); int len = strlen(userID); if(len != 8){ printf("'%s' is a userID and must be 8 characters\n", userID); exit(1); } for(int i=0; ic && a1){ if(n & 1){ n = (n<<2) - n + 1; } else { n = n >> 1; } if(s == t && m == t){ return; } s++; } failure("Seems you forgatz the essence of Collatz"); } void phase06(){ int a = atoi(next_input()); int b = atoi(next_input()); int c = atoi(next_input()); int d = atoi(next_input()); char expect[BUFSIZE] = "There are 10 kinds of people in the world: those who understand binary and those who don't"; char actual[BUFSIZE] = {}; strcpy(actual,expect); int slen = strlen(expect); int ilen = slen / sizeof(int) - 1; int location1 = (hash % 211) % ilen; int location2 = (hash % 311) % ilen; ((int *)actual)[location1] = 0x58585858; ((int *)actual)[location2] = 0x59595959; *(((int *)actual) + a) = b; *(((int *)actual) + c) = d; if(strncmp(expect,actual,BUFSIZE) == 0){ return; } failure("Here are hints:\n- use two ints with 4 bytes to make the message right\n- beware of endian ordering angst\n"); } void phase07(){ float a = atof(next_input()); union { char c[9]; float f; } flar; strcpy(flar.c, userID); if( fabs(a-flar.f) < 1e-8 ){ return; } char *msg = "Ugly cousin to the struct: if you don't know unions, then on this phase you're ...\n" "stuck.\n" "What did you think was going to rhyme with 'struct'? A curseword?\n" "Keep it PG: there are little bits 'n bytes with ears around here.\n" ; failure(msg); } void phase08() { int n = atoi(next_input()); int m = atoi(next_input()); int t = (hash % 83) + 21; int s = 0; char *msg = "Do you like spaghetti? Try some spaghetti! It's good, right?\n" "What, you prefer structured loops? How mundane.\n"; goto LTOP; LEND: failure(msg); LOM1: n = (n<<2) - n + 1; LCHK: if(s == t && m == t){ goto LAFT; } s++; goto LTOP; LOC1: if(n & 1){ goto LOM1; } goto LEM1; LTOP: if(!(n>1)){ goto LEND; } goto LOC1; LEM1: n = n >> 1; goto LCHK; LAFT: return; } unsigned long state = 1; unsigned int pb_rand() { state = state * 1103515245 + 12345; return (unsigned int)(state/65536) % 32768; } void pb_srand(unsigned long seed){ state = seed; } void scramble(char *str, int rounds){ int len = strlen(str); for(int i=0; i= len){ char *msg = "\"My, what big ints you have, Granny!\" " "\"All the better to overflow your buffers my dear\"\n"; failure(msg); } } long seed = (((long) hash) << 32) + ~hash; pb_srand(seed); scramble(letters, 100); char buf[BUFSIZE] = {}; for(int i=0; i<5; i++){ buf[i] = letters[idxs[i]]; } union{ long l; char s[8]; } chong; chong.l = 478426194263; if(strcmp(buf,chong.s)==0){ return; } char *msg = "Where's that stripey hipster with the lame hat and cane?\n" "He's all spread around in there. Find him."; failure(msg); } void phase10(){ long a = atol(next_input()); char ans[] = " "; for(int i=0; i<8; i++){ ans[i] = (char) ((a >> (6*i) & 0x3F) + 48); } if(strcmp(ans,userID)==0){ printf("OMG %s, the answers were inside you the the whole time!\n",userID); return; } char msg[BUFSIZE] = {}; snprintf(msg, BUFSIZE, "'%s' it is not. Look within, you must.\n", ans); failure(msg); }