static inline void pcb_draw(image_t *img, pcb_t *p); static pcb_t *load_str(char *fn); static inline int pcb_num_strokes(pcb_t *p); static void pcb_dump_str(FILE *f, pcb_t *p); pcb_t *default_new = NULL; long *black; long black_len; double stroke_penalty; /* Random value between from and to, inclusive */ static inline int myrand(int from, int to) { return from + rand() % (to - from + 1); } static inline void pcb_clear(image_t *img) { int n; pixel_t *p = img->pixmap; for(n = 0; n < img->sx * img->sy; n++,p++) { *p = pixel_white; } } static inline long int pcb_diff(const image_t *img1, const image_t *img2) { long int diff = 0; int n; const pixel_t *p1 = img1->pixmap; const pixel_t *p2 = img2->pixmap; for(n = 0; n < img1->sx * img1->sy; n++,p1++,p2++) { if ((p1->r != p2->r) || (p1->g != p2->g) || (p1->b != p2->b)) diff++; } return diff; } static inline void pcb_shadow(image_t *dst, const image_t *src) { int n; pixel_t *d = dst->pixmap; const pixel_t *s = src->pixmap; for(n = 0; n < dst->sx * dst->sy; n++,d++,s++) { if ((s->r != 255) && (s->g != 255) && (s->b != 255)) { d->r = 200; d->g = 240; d->b = 240; } else *d = pixel_white; } } static inline long pcb_list_black(const image_t *src, long *bl) { long n, cnt = 0; const pixel_t *s = src->pixmap; for(n = 0; n < src->sx * src->sy; n++,s++) { if ((s->r != 255) && (s->g != 255) && (s->b != 255)) { if (bl != NULL) bl[cnt] = n; cnt++; } } return cnt; } #define clamp(v, min, max) ((v) < (min) ? (min) : ((v) > (max) ? (max) : (v))) double pcb_score(void *data) { double scr; pcb_clear(canvas); pcb_draw(canvas, data); scr = pcb_diff(canvas, ref); return scr + (pcb_num_strokes(data)+1) * stroke_penalty; } #define tune(dst, min, max, delta) \ if ((dst + delta >= min) && (dst + delta <= max)) dst += delta; void pcb_clone(void *dst, void *src) { memcpy(dst, src, sizeof(pcb_t)); } const char *pcb_dump(void *data, int population_id, int individual_id) { image_t *img = canvas; static char s[256]; FILE *f; snprintf(s, sizeof(s), DUMPDIR "s_%08d_%02d.str", population_id, individual_id); f = fopen(s, "w"); pcb_dump_str(f, data); fclose(f); pcb_shadow(img, ref); pcb_draw(img, data); snprintf(s, sizeof(s), DUMPDIR "s_%08d_%02d.pnm", population_id, individual_id); pnm_save(img, s); return s; } static inline void common_init(int argc, char *argv[]) { char *ref_fn = "l.pnm"; if (argv[1] != NULL) ref_fn = argv[1]; if (argv[2] != NULL) default_new = load_str(argv[2]); srand(time(NULL)); ref = pnm_load(ref_fn); black_len = pcb_list_black(ref, NULL); black = malloc(sizeof(long) * black_len); black_len = pcb_list_black(ref, black); stroke_penalty = ref->sx * ref->sy / STROKE_PENALTY; canvas = image_new(ref->sx, ref->sy); }