DRUID Development Docs: codegen.c

Gadget Sourcecode: codegen.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define PUZZLE_CODES_NEEDED     30
#define PUZZLE_CODE_LEN         6

#define LOCATION_CODE_LEN       6
#define LOCATION_CODES_NEEDED   30

#define MIN_UNIQUE              2
#define MIN_FAR                 1
#define MIN_SHIFTED_UNIQUE      1
#define MIN_SHIFTED_FAR         0

#define MAX_PARM_VAL    30
#define MAX_PARM1_VAL   30
#define MAX_PARM2_VAL   30
#define MAX_CODE_LEN    10
#define NUM_CHARS       36

typedef unsigned long long icode;

int do_print = 0;

icode p1_mul[MAX_CODE_LEN];
icode p2_mul[MAX_CODE_LEN];
icode code_max[MAX_CODE_LEN];

int hist[MAX_CODE_LEN+1];
int hist2[MAX_CODE_LEN+1];
int hist3[MAX_CODE_LEN+1];
int hist4[MAX_CODE_LEN+1];

typedef enum CodeMode_e {
    CM_PUZZLE,
    CM_SPECIAL,
    CM_LOCATION,
    CM_EXTRA,

    CM_END
} CodeMode;

typedef struct CodeInfo_s {
    char        *code;
    char        *func;
    char        *parm0;
    int          id;
    int          parm1_max;
    int          parm2_max;
    CodeMode     mode;
    struct CodeInfo_s   *next;
    
} CodeInfo;

typedef struct CodeList_s {
    CodeInfo    **list[MAX_CODE_LEN];
    int           cnt[MAX_CODE_LEN];
    int           max[MAX_CODE_LEN];
    int           puzzle_cnt;
    int           location_cnt;

    CodeInfo    *puzzle_head;
    CodeInfo    **puzzle_tail;
    CodeInfo    *location_head;
    CodeInfo    **location_tail;
    CodeInfo    *special_head;
    CodeInfo    **special_tail;

    CodeInfo    *puzzles[PUZZLE_CODES_NEEDED];
    CodeInfo    *locations[LOCATION_CODES_NEEDED];

} CodeList;

int code_max_cnt = 0;

//int ocode_cnt = 0;
//int pcode_cnt = 0;
//int code_len;

CodeList code_list1;
CodeList *code_list = &code_list1;

#define ASSERT(cond)    if (!(cond)) { assert_err( #cond ); }

void assert_err(char *str)
{
    fprintf(stderr,"ASSERT FAILED: %s\n",str);
    exit(1);
}

int find_mul = 0;

void init_codes(CodeList *list)
{
    int i;
    int cnt = (MAX_PARM1_VAL+1)*(MAX_PARM2_VAL+1) * (LOCATION_CODES_NEEDED+1) + PUZZLE_CODES_NEEDED + 100;
    int size = cnt * sizeof(CodeInfo*);
    memset(list, 0, sizeof(*list));
    for (i=0; i<MAX_CODE_LEN; i++) {
        list->list[i] = (CodeInfo**)malloc(size);
        memset(list->list[i],0,size);
        list->cnt[i] = 0;
        list->max[i] = cnt;
        list->puzzle_cnt = 0;
        list->location_cnt = 0;
    }

    list->puzzle_tail = &list->puzzle_head;
    list->location_tail = &list->location_head;
    list->special_tail = &list->special_head;
}

void set_puzzle_code(CodeList *list, CodeInfo *ci, int val)
{
    if (val < 0) {
        for (val = 0; val < PUZZLE_CODES_NEEDED; val++) {
            if (list->puzzles[val] == 0) break;
        }
        ASSERT(val < PUZZLE_CODES_NEEDED);
    }

    if (list->puzzles[val] != 0) {
        fprintf(stderr,"ERROR: puzzle %d is already assigned to '%s' - cannot be reassigned to '%s'!\n",
            val,list->puzzles[val]->code,ci->code);
        return;
    }
    
    ci->id = val;
    list->puzzles[val] = ci;
}

CodeInfo *set_location_code(CodeList *list, CodeInfo *ci, int val)
{
    if (val < 0) {
        for (val = 0; val < LOCATION_CODES_NEEDED; val++) {
            if (list->locations[val] == 0) break;
        }
        ASSERT(val < LOCATION_CODES_NEEDED);
    }

    if (list->locations[val] != 0) {
        fprintf(stderr,"ERROR: locations %d is already assigned to '%s' - cannot be reassigned to '%s'!\n",
            val,list->locations[val]->code,ci->code);
        return;
    }
    
    ci->id = val;
    list->locations[val] = ci;
}

void delete_code(CodeInfo *ci)
{
    ASSERT(ci->mode == CM_EXTRA);
    ASSERT(ci->id == -1);
    if (ci->code) free(ci->code);
    if (ci->func) free(ci->func);
    if (ci->parm0) free(ci->parm0);
    free(ci);
}

void remove_code(CodeList *list, char *code)
{
    int i;
    int len = strlen(code);
    for (i=0; i<list->cnt[len]; i++) {
        CodeInfo *ci = list->list[len][i];
        if (!strcmp(ci->code, code)) {
            delete_code(ci);
            list->cnt[len]--;
            list->list[len][i] = list->list[len][list->cnt[len]];
            list->list[len][list->cnt[len]] = 0;
        }
    }
}

CodeInfo *add_code(CodeList *list, char *code, char *func, char *parm0, int parm1_max, int parm2_max)
{
    int idx;
    int len = strlen(code);
    CodeInfo *ci = (CodeInfo*)malloc(sizeof(CodeInfo) + len + 1);

    remove_code(list, code);

    ASSERT(len >0 && len <= MAX_CODE_LEN);
    ci->code = strdup(code);
    ci->func = 0;
    ci->parm0 = (parm0&&parm0[0])?strdup(parm0):0;
    ci->parm1_max = parm1_max;
    ci->parm2_max = parm2_max;
    ci->mode = CM_EXTRA;
    ci->next = 0;
    ci->id = -1;

    if (func) {
        if (!strncmp(func,"func_fn_",8)) {
            ci->func = strdup(func);
            if (!strncmp(func+8,"puzcode_",8)) {
                ci->mode = CM_PUZZLE;
                list->puzzle_cnt++;
            } else if (!strncmp(func+8,"loccode_",8)) {
                ci->mode = CM_LOCATION;
                list->location_cnt++;
            } else {
                ci->mode = CM_SPECIAL;
            }
        } else if (!strcmp(func,"PUZZLE")) {
            ci->mode = CM_PUZZLE;
            list->puzzle_cnt++;
        } else if (!strcmp(func,"LOCATION")) {
            ci->mode = CM_LOCATION;
            list->location_cnt++;
        } else {
            fprintf(stderr,"Bad function name: '%s'\n",func);
        }
    }

    switch(ci->mode) {
        case CM_PUZZLE:
            list->puzzle_cnt++;
            *list->puzzle_tail = ci;
            list->puzzle_tail  = &ci->next;
            if (ci->parm0 && !strncmp(ci->parm0, "puz", 3)) {
                char *e;
                long val = strtol(ci->parm0+3,&e,10);
                if (e && *e == 0 && e == ci->parm0+3) {
                    set_puzzle_code(list, ci, val);
                } else {
                    fprintf(stderr,"WARNING: Could not determine puzzle number for code '%s'\n",
                        ci->code);
                }
            }
            break;
        case CM_LOCATION:
            list->location_cnt++;
            *list->location_tail = ci;
            list->location_tail  = &ci->next;
            if (ci->parm0 && !strncmp(ci->parm0, "loc", 3)) {
                char *e;
                long val = strtol(ci->parm0+3,&e,10);
                if (e && *e == 0 && e == ci->parm0+3) {
                    set_location_code(list, ci, val);
                } else {
                    fprintf(stderr,"WARNING: Could not determine location number for code '%s'\n",
                        ci->code);
                }
            }
            break;
        case CM_SPECIAL:
            *list->special_tail = ci;
            list->special_tail  = &ci->next;
            break;
        default:
            break;
    }

    ASSERT(list->cnt[len] < list->max[len]);
    idx = list->cnt[len]++;
    if (list->list[len][idx]) {
        free(list->list[len][idx]);
    }
    list->list[len][idx] = ci;
    
    return ci;
}

CodeList *bookmark_create(CodeList *list)
{
    CodeList *bookmark = (CodeList *)malloc(sizeof(CodeList));
    memcpy(bookmark, list, sizeof(CodeList));
    return bookmark;
}

void bookmark_delete(CodeList *bookmark)
{
    free(bookmark);
}

void bookmark_restore(CodeList *list, CodeList *bookmark)
{
    memcpy(list, bookmark, sizeof(CodeList));
    bookmark_delete(bookmark);
}


void read_codes(CodeList *list, char *filename)
{
    FILE *fp = fopen(filename,"rt");
    int c;
    int state = 1;
    int linenum = 1;
    char code[100];
    char func[100];
    char parm0[100];
    int parm1_max;
    int parm2_max;

    if (!fp) {
        fprintf(stderr,"ERROR: Could not read file '%s'\n",filename);
        return;
    }   

    c = getc(fp);
    while(state != 1000) {
        while (state < 7) {
            switch(c) {
                case 'C': if (state==1) state++; break;
                case 'O': if (state==2) state++; break;
                case 'D': if (state==3) state++; break;
                case 'E': if (state==4) state++; break;
                case ' ': if (state==5) state = 7; break;
                case '\t': if (state==5) state = 7; break;
                case EOF: state = 1000; break;
                case '\n': state = 1; linenum++; break;
                default:    state = 6; break;
            }
            c = getc(fp);
        }

        #define PARSE_ASSERT(cond)                                          \
                if (!(cond)) {                                              \
                    fprintf(stderr,"PARSE ERROR: %s:%d: ASSERT(%s)\n",      \
                        filename,linenum,#cond);                            \
                    continue;                                               \
                }

        if (state == 7) {
            int cnt;
            state = 6;

            //
            // read code string
            //
            while(isspace(c) && c!= '\n') c = getc(fp);
            PARSE_ASSERT(c=='"');
            c = getc(fp);
            cnt=0;
            while(c!='"' && c!='\n' && c!=EOF) {
                PARSE_ASSERT(cnt<100);
                code[cnt++] = tolower(c);
                c = getc(fp);
            }
            PARSE_ASSERT(c=='"');
            c = getc(fp);
            code[cnt++] = 0;

            //
            // read func name
            //
            while(isspace(c) && c!= '\n') c = getc(fp);
            PARSE_ASSERT(c=='f');
            cnt = 0;
            while(!isspace(c) && c!=EOF && c!= '#') {
                PARSE_ASSERT(cnt<100);
                func[cnt++] = c;
                c = getc(fp);
            }
            func[cnt++] = 0;
            
            //
            // read parm0 (optional)
            //
            while(isspace(c) && c!= '\n') c = getc(fp);
            cnt = 0;
            while(!isspace(c) && c!=EOF && c!= '#') {
                PARSE_ASSERT(cnt<100);
                parm0[cnt++] = c;
                c = getc(fp);
            }
            parm0[cnt++] = 0;
            
            //
            // read parm1_max (optional)
            //
            while(isspace(c) && c!= '\n') c = getc(fp);
            parm1_max = 0;
            while(!isspace(c) && c!=EOF && c!= '#') {
                PARSE_ASSERT(isdigit(c));
                parm1_max *= 10;
                parm1_max += c - '0';
                c = getc(fp);
            }
            
            //
            // read parm2_max (optional)
            //
            while(isspace(c) && c!= '\n') c = getc(fp);
            parm2_max = 0;
            while(!isspace(c) && c!=EOF && c!= '#') {
                PARSE_ASSERT(isdigit(c));
                parm2_max *= 10;
                parm2_max += c - '0';
                c = getc(fp);
            }

            //
            // read rest of line
            //
            while(isspace(c) && c!= '\n') c = getc(fp);
            PARSE_ASSERT(c == '\n' || c==EOF || c=='#');
            
            //
            // add code
            //
            if (check_perms(code, parm1_max, parm2_max, 0)) {
                fprintf(stderr,"Input code '%s' conflicts!!\n",code);
            }
            add_code(list, code, func, parm0, parm1_max, parm2_max);

        }
    }
    #undef PARSE_ASSERT

    fclose(fp);
}

void setup(void)
{
#if 0
    static int p1_sc[MAX_CODE_LEN] = 
        {1,0,2,0,3,0,4,0,5,0};
    static int p2_sc[MAX_CODE_LEN] = 
        {0,1,0,2,0,3,0,4,0,5};
#else
    static int p1_sc[MAX_CODE_LEN] = 
        {3,1,4,0,3,2,4,3,1,3};
    static int p2_sc[MAX_CODE_LEN] = 
        {2,0,1,3,2,4,2,0,2,1};
#endif

    int i;
    icode digit;

    time_t t;
    time(&t);
    srandom(t);

    while(1) {
        CodeList *save_cnt = bookmark_create(code_list);
        digit = 1;
        p1_mul[0] = p2_mul[0] = p1_mul[1] = p2_mul[1] = 0;
        for (i=2; i<MAX_CODE_LEN; i++) {
            if (find_mul) {
                p1_sc[i-1] = random() % 5;
                do {
                    p2_sc[i-1] = random() % 5;
                } while (p2_sc[i-1] == p1_sc[i-1]);
            }
            p1_mul[i] = p1_mul[i-1] + digit * p1_sc[i-1];
            p2_mul[i] = p2_mul[i-1] + digit * p2_sc[i-1];
            digit *= NUM_CHARS;
            code_max[i-1] = digit;
            fprintf(stderr,"len=%2d  p1_sc=%d p2_sc=%d code_max=%-16Ld p1_mul=%-16Ld p2_mul=%-16Ld\n",
                i+1,p1_sc[i],p2_sc[i],code_max[i],p1_mul[i],p2_mul[i]);
        }

        for (i=0; i<MAX_CODE_LEN+1; i++) {
            hist3[i] = 0;
            hist4[i] = 0;
        }
        check_perms("aaaaaa", MAX_PARM1_VAL, MAX_PARM2_VAL, 0);
        for (i=0; i<MAX_CODE_LEN+1; i++) {
            fprintf(stderr,"[%2d]%-10d ",i,hist3[i]);
        }
        fprintf(stderr,"\n");
        for (i=0; i<MAX_CODE_LEN+1; i++) {
            fprintf(stderr,"[%2d]%-10d ",i,hist4[i]);
        }
        fprintf(stderr,"\n");

        bookmark_restore(code_list,save_cnt);

        if (!find_mul) break;

        if (hist3[6]==1 &&
            hist4[6]==1 &&
            hist3[5]==0 &&
            hist4[5]==0 &&
            hist3[4]==0 /*&&
            hist4[4]==0 /*&&
            hist3[3]==0 /*&&
            (hist4[3]==0 || hist3[2]==0)*/) {
            break;
        }
    }
}

int char2int(int c)
{
    if (c>='a' && c<='z') return c-'a';
    if (c>='A' && c<='Z') return c-'A';
    if (c>='0' && c<='9') return c-'0'+26;
    fprintf(stderr,"BAD CODE CHARACTER: %d = 0x%02x = '%c'\n",
        c,c,isprint(c)?c:'?');
    exit(1);
    return -1;
}

int int2char(int i)
{
    if (i>=0 && i<=25) return i+'a';
    if (i>=26 && i<=35) return i+'0'-26;
    fprintf(stderr,"BAD CODE DIGIT: %d = 0x%02x = '%c'\n",
        i,i,isprint(i)?i:'?');
    exit(1);
    return -1;
}

icode code2int(char *code)
{
    int len = strlen(code);
    icode num = 0;
    int i;
    for (i=0; i<len; i++) {
        num *= NUM_CHARS;
        num += char2int(code[i]);
    }
    return num;
}

char *int2code(icode num, int len)
{
    char *code;
    int i=1;
    icode digit = 1;
    ASSERT(digit > 0);
    while(i<len || num >= digit * NUM_CHARS) {
        i++;
        digit *= NUM_CHARS;
        ASSERT(digit > 0);
    }

    len = i;
    code = (char*)malloc(len + 1);
    code[len] = 0;
    
    for (i=0; i<len; i++) {
        int val = num/digit;
        num = num - (digit * val);
        code[i] = int2char(val);
        digit /= NUM_CHARS;
    }
    return code;
}

char *gen_perm(char *code, int parm1, int parm2)
{
    int len = strlen(code);
    icode num = code2int(code);
    icode num0=num;
    char *code2;

    ASSERT(len <= MAX_CODE_LEN);

    num +=  (icode)parm1 * p1_mul[len-1] +
            (icode)parm2 * p2_mul[len-1];

    code2 = int2code(num, len);

#if 0
    fprintf(stderr,"gen_perm(%s,%d,%d) = %s  num=%20Ld  %10Ld\n",
        code,parm1,parm2,code2,num0,num);
#endif
    return code2;
}

int check_similar(int c1, int c2)
{
    if (c1 == c2) return 1;
    if (c1 == c2+1) return 1;
    if (c1 == c2-1) return 1;
    if (c1 == '0' && tolower(c2)=='z') return 1;
    if (c1 == '9' && tolower(c2)=='a') return 1;
    if (c2 == '0' && tolower(c1)=='z') return 1;
    if (c2 == '9' && tolower(c1)=='a') return 1;
    return 0;
}

char *check_code(char *code, int len, int add)
{
    static char err_str[100];
    int i,j,k,len2;
    int max_same = 0;
    int max_similar = 0;
    int z_cnt = 0;
    int n_cnt = 0;
    if (strlen(code) != len) {
        return "code-length";
    }

    for (j=0; j<len; j++) {
        int cc = tolower(code[j]);
        if (cc == 'a') {
            z_cnt++;
            n_cnt++;
        } else if (cc == 'b' || cc == '9') {
            n_cnt++;
        }
    }
    hist3[z_cnt]++;
    hist4[n_cnt]++;

    for (len2 = len-1; len2<=len+1; len2++) {
        for (i=0; i<code_list->cnt[len2]; i++) {
            char *codea, *codeb;
            int   lena, lenb;
            if (len2 > len) {
                codea = code_list->list[len2][i]->code;
                lena  = len2;
                codeb = code;
                lenb  = len;
            } else {
                codeb = code_list->list[len2][i]->code;
                lenb  = len2;
                codea = code;
                lena  = len;
            }
            for (j=0; j<lena; j++) {
                int same_cnt = 0;
                int similar_cnt = 0;
                for (k=0; k<lenb; k++) {
                    if (check_similar(codeb[k], codea[(lena+j-k)%lena])) {
                        similar_cnt++;
                        if (codeb[k] == codea[(j+k)%lena]) {
                            same_cnt++;
                        }
                    }
                }
                if (same_cnt > max_same) max_same = same_cnt;
                if (similar_cnt > max_similar) max_similar = similar_cnt;
                if (j != 0) {
                    same_cnt = 0;
                    similar_cnt = 0;
                    for (k=0; k<lenb; k++) {
                        if (check_similar(codeb[k], codea[(j+k)%lena])) {
                            similar_cnt++;
                            if (codeb[k] == codea[(j+k)%lena]) {
                                same_cnt++;
                            }
                        }
                    }
                    if (same_cnt > max_same) max_same = same_cnt;
                    if (similar_cnt > max_similar) max_similar = similar_cnt;
                }
            }
        }
    }
    if (len - max_same < MIN_SHIFTED_UNIQUE) {
        sprintf(err_str, "%d shifted chars same",max_same);
        return err_str;
    }
    if (len - max_similar < MIN_SHIFTED_FAR) {
        sprintf(err_str, "%d shifted chars similar",max_similar);
        return err_str;
    }

    for (i=0; i<code_list->cnt[len]; i++) {
        int same_cnt = 0;
        int similar_cnt = 0;
        for (j=0; j<len; j++) {
            if (code[j] == code_list->list[len][i]->code[j]) {
                same_cnt++;
                similar_cnt++;
            } else if (check_similar(code[j],code_list->list[len][i]->code[j])) {
                similar_cnt++;
            }
        }
        hist[same_cnt]++;
        hist2[similar_cnt]++;
        if (same_cnt > max_same) max_same = same_cnt;
        if (similar_cnt > max_similar) max_similar = similar_cnt;
    }
    if (len - max_same < MIN_UNIQUE) {
        sprintf(err_str, "%d chars same",max_same);
        return err_str;
    }
    if (len - max_similar < MIN_FAR) {
        sprintf(err_str, "%d chars similar",max_similar);
        return err_str;
    }
    if (add && max_same != len) {
        add_code(code_list, code, 0, 0, 0, 0);
    }
    return 0;
}

int check_perms(char *code, int max_p1, int max_p2, int do_rej)
{
    int i,j;
    int cnt = 0;
    int len = strlen(code);

    for (i=0; i<=max_p1; i++) {
        for (j=0; j<=max_p2; j++) {
            char *code2 = gen_perm(code,i,j);
            char *rej;
            rej = check_code(code2,len,do_rej);
            if (do_rej && rej) {
                fprintf(stderr,"REJECT code %s(%2d,%2d) = %s  (%s)\n",
                        code,i,j,code2, rej);
                return 1;
            }
            if (do_print) {
                fprintf(stderr,"code(%2d,%2d) = %s\n",
                    i,j,code2);
            }
            free(code2);
            if ((cnt%100) == 0) {
                //fprintf(stderr,".");
            }
            cnt++;
        }
    }
    //fprintf(stderr,"\n");
    if (do_print) {
        fprintf(stderr,"\n");
        for (i=0; i<=max_p1; i++) {
            char *code2 = gen_perm(code,i,0);
            fprintf(stderr,"code(%2d,%2d) = %s\n",i,0,code2);
            free(code2);
        }
        fprintf(stderr,"\n");
        for (i=0; i<=max_p1; i++) {
            char *code2 = gen_perm(code,0,i);
            fprintf(stderr,"code(%2d,%2d) = %s\n",0,i,code2);
            free(code2);
        }
        fprintf(stderr,"\n");
    }
    return 0;
}

char *add_rand_code(int len, int max_p1, int max_p2, char *func)
{
    char code[MAX_CODE_LEN+1];
    int i;
    CodeList *save_cnt = bookmark_create(code_list);

    ASSERT(len <= MAX_CODE_LEN);
    
    code[len] = 0;
    hist[len] = 0;
    hist2[len] = 0;
    for (i=0; i<len; i++) {
        hist[i] = 0;
        hist2[i] = 0;
        code[i] = int2char(random() % NUM_CHARS);
    }

    fprintf(stderr,"try(%d,%d)(%d) %s\n",max_p1,max_p2,code_list->cnt[len],code);

    if (check_perms(code, max_p1, max_p2, 1)) {
        bookmark_restore(code_list, save_cnt);
        return 0;
    }
    bookmark_delete(save_cnt);

    fprintf(stderr,"SUCCESS:  ");
    for (i=0; i<len+1; i++) {
        fprintf(stderr,"[%d]%-10d ",i,hist[i]);
    }
    fprintf(stderr,"\n          ");
    for (i=0; i<len+1; i++) {
        fprintf(stderr,"[%d]%-10d ",i,hist2[i]);
    }
    fprintf(stderr,"\n");

    add_code(code_list, code, func, 0, max_p1, max_p2);
    return strdup(code);
}

void output_code(FILE *out, char *code, char *func, char *parm0, int parm1_max, int parm2_max)
{
    fprintf(out,"CODE \"%s\" %s",
        code,
        func?func:"func_fn_unknown");

    if (parm0 || parm1_max || parm2_max) {
        fprintf(out," %s",parm0?parm0:"parmval_0");

        if (parm1_max || parm2_max) {
            ASSERT(parm1_max >= 0 && parm1_max <= MAX_PARM_VAL);
            fprintf(out," parmval_%d",parm1_max);
            if (parm2_max) {
                ASSERT(parm2_max >= 0 && parm2_max <= MAX_PARM_VAL);
                fprintf(out," parmval_%d",parm2_max);
            }
        }
    }
    fprintf(out,"\n");
}

void output(FILE *out, CodeList *list)
{
    CodeInfo *ci;
    int i;

    fprintf(out,"; Justice Unlimited Gadget Microcode\n");
    fprintf(out,"; (C) 2004 Nathan (Acorn) Pooley\n");
    fprintf(out,";\n");
    fprintf(out,"; gcodes.sstr\n");
    fprintf(out,";\n");
    fprintf(out,";@DOC@ Codes\n");
    fprintf(out,";\n");
    fprintf(out,"\n");
    fprintf(out,"; WARNING: DO NOT EDIT THIS FILE BY HAND\n");
    fprintf(out,"; This file is autogenerated by codegen.c.\n");


    fprintf(out,"\n\n");
    for (i=0; i<MAX_CODE_LEN; i++) {
        fprintf(out,"#define CODE_MUL1_%d\t\t0x%x\n",
            i, p1_mul[i]);
        fprintf(out,"#define CODE_MUL2_%d\t\t0x%x\n",
            i, p2_mul[i]);
    }
    fprintf(out,"\n\n");

    for (i=0; i<MAX_PARM_VAL; i++) {
        fprintf(out,"#define parmval_%d     %d\n",i,i);
    }
    fprintf(out,"\n\n");

    ci = list->special_head;
    while(ci) {
        output_code(out, ci->code, ci->func, ci->parm0, ci->parm1_max, ci->parm2_max);
        ci = ci->next;
    }
    fprintf(out,"\n\n");

    ci = list->puzzle_head;
    while(ci) {
        if (ci->id < 0) {
            set_puzzle_code(list, ci, -1);
        }
        ci = ci->next;
    }

    ci = list->location_head;
    while(ci) {
        if (ci->id < 0) {
            set_location_code(list, ci, -1);
        }
        ci = ci->next;
    }

    for (i=0; i<PUZZLE_CODES_NEEDED; i++) {
        char *func;
        char *parm0p;
        char parm0[100];
        ci = list->puzzles[i];
        ASSERT(ci);
        func = ci->func ? ci->func : "func_fn_puzcode";
        sprintf(parm0,"puz%d",i);
        parm0p = (ci->parm0 && ci->parm0[0]) ? ci->parm0 : parm0;
        
        output_code(out, ci->code, func, parm0p, ci->parm1_max, ci->parm2_max);
    }
    fprintf(out,"\n\n");

    for (i=0; i<LOCATION_CODES_NEEDED; i++) {
        char *func;
        char *parm0p;
        char parm0[100];
        ci = list->locations[i];
        ASSERT(ci);
        func = ci->func ? ci->func : "func_fn_loccode";
        sprintf(parm0,"loc%d",i);
        parm0p = (ci->parm0 && ci->parm0[0]) ? ci->parm0 : parm0;

        output_code(out, ci->code, func, parm0p, ci->parm1_max, ci->parm2_max);
    }
    fprintf(out,"\n\n");
}


int main(int argc, char *argv[])
{
    int i;
    int o_cnt;

    ASSERT(sizeof(icode) >= 8);

    init_codes(code_list);
    setup();

    //
    // get pre-assigned codes
    //
    read_codes(code_list,"gadget_codes.sstr");
    
    //
    // get location codes
    //
    while(code_list->location_cnt < LOCATION_CODES_NEEDED) {
        add_rand_code(LOCATION_CODE_LEN, MAX_PARM1_VAL, MAX_PARM2_VAL, "LOCATION");
    }

    //
    // get puzzle codes
    //
    while(code_list->puzzle_cnt < PUZZLE_CODES_NEEDED) {
        add_rand_code(LOCATION_CODE_LEN, 0, 0, "PUZZLE");
    }


#if 0
    fprintf(stderr,"\n\n");
    for (i=0; i<CODES_NEEDED; i++) {
        int j;
        fprintf(stderr,"code %2d:  %s  ",i,codes[i]);
        for (j=0; j<code_len+1; j++) {
            hist[j] = 0;
            hist2[j] = 0;
        }
        check_perms(codes[i], MAX_PARM1_VAL, MAX_PARM2_VAL, 0);
        for (j=0; j<code_len+1; j++) {
            fprintf(stderr,"[%d]%-10d ",j,hist[j]);
        }
        fprintf(stderr,"\n          %*s  ",code_len,"");
        for (j=0; j<code_len+1; j++) {
            fprintf(stderr,"[%d]%-10d ",j,hist2[j]);
        }
        fprintf(stderr,"\n");
    }
    fprintf(stderr,"%d unique codes\n",code_cnt);
#endif


#if 0
    printf("\n\n");
    for (i=0; i<MAX_CODE_LEN; i++) {
        printf("#define CODE_MUL1_%d\t\t0x%x\n",
            i, p1_mul[i]);
        printf("#define CODE_MUL2_%d\t\t0x%x\n",
            i, p2_mul[i]);
    }

    printf("\n\n");
    for (i=0; i<CODES_NEEDED; i++) {
        printf("CODE \"%s\" func_fn_loccode loc%02d\n",
            codes[i],
            i);
    }

    printf("\n\n");
    o_cnt = sizeof(other_codes)/sizeof(other_codes[0]);
    for (i=0; i<o_cnt; i++) {
        printf("CODE \"%s\" func_fn_other\n",
            other_codes[i]);
    }

    printf("\n\n");
    for (i=ocode_cnt; i<pcode_cnt; i++) {
        printf("CODE \"%s\" func_fn_puzcode puz%d\n",
            code_list[i],
            i-ocode_cnt);
    }
#endif

    output(stdout, code_list);


    return 0;
}

This file Copyright (C) 2004 by Nathan (Acorn) Pooley
Go to DRUID Development page
Go to DRUID page
Go to JU Gadgets page
Go to Justice Unlimited homepage
Go to Acorn's personal webpage
Contact Acorn
See comments from others
Post your own comments
File created by do_doc at Wed Aug 4 18:05:22 2004