/** * Generator for text printing Malbolge programs. * 2012, 2015 Matthias Ernst. * Please visit * * To the extent possible under law, the author has dedicated all copyright * and related and neighboring rights to this software to the public domain * worldwide. This software is distributed without any warranty. * * See . */ #include #include #include #define MB_OUT 5 #define MB_ROT 39 #define MB_OPR 62 #define MB_NOP 68 #define MB_HALT 81 const char* translation = "5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72FhOA1CB6v^=I_0/8|jsb9m<.TVac`uY*MK'X~xDl}REokN:#?G\"i@"; int memory[59050]; // program int memory_runtime[59050]; // memory at runtime: with encrypted commands int last_A_val = 0; // last value of A register /** * Searches and generates Malbolge instructions that generate goal's value in the A register. * Malbolge command sequence starts at position C. * Returns the length of the instruction set. * Returns -1 on failure. */ int generate_character(int C, char goal); void create_malbolge_command(int command, int position) { command = (command-(position)%94+94)%94; if (command<33) { command+=94; } memory[position] = command; if (position >= 98) { memory_runtime[position] = translation[memory[position]-33]; } else { memory_runtime[position] = memory[position]; } } int opr(int a, int d){ int crz[] = {1,0,0,1,0,2,2,2,1}; int position = 0; int output = 0; while (position < 10){ int i = a%3; int j = d%3; int out = crz[i+3*j]; int multiple = 1; int k; for (k=0;k 1){ int total_length = 0; // total length of command line arguments int pos = 0; for (i=1;i0) pos--; out_s[pos]=0; }else{ // If no command line arguments are given, read from STDIN. // Read 59.000 characters at most. int pos = 0; int result = 0; out_s = (char*)malloc(59001*sizeof(char)); if (stdin == 0){ printf("Cannot access STDIN.\n"); return -1; } while (!feof(stdin) && pos < 59000){ result = fread(out_s+pos,1,1,stdin); if (result<0){ printf("Error while reading from STDIN.\n"); return -1; } if (result==0) break; pos++; } out_s[pos]=0; } // first character: b -> cause a jump to address 98 which will be encrypted first memory_runtime[0] = memory[0] = 'b'; // fill skipped memory cells with NOPs for (i=1;i<99;i++){ create_malbolge_command(MB_NOP, i); } // Malbolge program execution continues with data pointer at 1 and program counter at 99 C = 99; // The data pointer is always D = C-98, so we needn't store its value. while (*out_s != 0){ int command_length = 0; // load character to A register do { command_length = generate_character(C, *out_s); out_s++; } while(command_length < 0 && *out_s!=0); if (command_length == -1) break; C += command_length; if (C > 59047){ C=59047; break; }else{ // print A register create_malbolge_command(MB_OUT, C); C++; } } if (C > 59047){ C=59047; } // halt create_malbolge_command(MB_HALT, C); C++; for (i=0;i= 154 && (unsigned char)goal <= 208)) { // These characters cannot be generated by our method. Return -1 (no success). return -1; } if ((char)last_A_val == goal){ // goal's value is in the A register already. return 0; } // search for instructions of format // NOP* ROT? NOP* OPR? NOP* OPR // or // NOP* ROT // that generate goal's value in the A register // within the search window. while(window_size <= 700 && window_size + C < 59049){ int rotPos = -1; do{ int inner_opr_pos = rotPos+1; do{ int cur_A_val = last_A_val; for (i=C;i= 0){ create_malbolge_command(MB_ROT, C+rotPos); cur_A_val = rotateR(memory_runtime[C+rotPos-98]); } for (i=C+rotPos+1;i