/* * Piece editor for plumb * * min * |-------| * | | * | smallr | * | | * |-------| * max * min * |---------------------------------| * | | * ~~~~~~~~ ~~~~~ * | bigr edit screen | * ~~~~ ~~~~~ * |---------------------------------| * max */ #include #include #include #include #include #define SIZE 48 #define MAG 10 #define BORDER 4 #define NVAL 4 struct{ char *name; Image *image; }piece[]={ " 0 N/E", 0, " 1 N/S", 0, " 2 N/W", 0, " 3 E/S", 0, " 4 E/W", 0, " 5 S/W", 0, " 6 N/S+E/W", 0, " 7 N/E one way", 0, " 8 N/S one way", 0, " 9 N/W one way", 0, "10 E/N one way", 0, "11 E/S one way", 0, "12 E/W one way", 0, "13 S/N one way", 0, "14 S/E one way", 0, "15 S/W one way", 0, "16 W/N one way", 0, "17 W/E one way", 0, "18 W/S one way", 0, "19 start N", 0, "20 start E", 0, "21 start S", 0, "22 start W", 0, "23 finish N", 0, "24 finish E", 0, "25 finish S", 0, "26 finish W", 0, "27 N/S reservoir", 0, "28 E/W reservoir", 0, "29 N/S bonus", 0, "30 E/W bonus", 0, "31 obstacle", 0, "32 empty", 0, }; #define NPIECE (sizeof piece/sizeof piece[0]) Image *flat[NVAL]; char pix[SIZE][SIZE]; char curval=3; enum{ Paint, Fill, Relief}mode=Paint; Rectangle bigr, smallr; /* colors for plumb */ Image *darkgreen; Image *palegreen; Image *bgcolor; char pattern[16][16]={ 3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0, 0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0, 0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0, 0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0, 3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0, 0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3, 0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0, 0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0, 3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0, 0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0, 0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0, 0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0, 3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0, 0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3, 0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0, 0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0, }; void rectf(Image *b, Rectangle r, Image *color){ draw(b, r, color, 0, ZP); } void show(Point p){ Point pp; int v=pix[p.y][p.x]; pp = addpt(bigr.min, mulpt(p, MAG)); draw(screen, Rpt(pp, addpt(pp, Pt(MAG, MAG))), flat[v], 0, flat[v]->r.min); pp = addpt(smallr.min, p); draw(screen, Rpt(pp, addpt(pp, Pt(1, 1))), flat[v], 0, addpt(ZP, Pt(1, 1))); } /* set the pixel value to v */ void set(Point p, char v){ if(v==4) v=pattern[p.y%16][p.x%16]; if(pix[p.y][p.x]!=v){ pix[p.y][p.x]=v; show(p); } } char region[SIZE][SIZE]; void getregion1(Point p, char v){ if(pix[p.y][p.x]!=v || region[p.y][p.x]) return; region[p.y][p.x]=1; if(p.x!=SIZE-1) getregion1(Pt(p.x+1, p.y), v); if(p.x!=0) getregion1(Pt(p.x-1, p.y), v); if(p.y!=SIZE-1) getregion1(Pt(p.x, p.y+1), v); if(p.y!=0) getregion1(Pt(p.x, p.y-1), v); } void getregion(Point p){ int x, y; for(y=0;y!=SIZE;y++) for(x=0;x!=SIZE;x++) region[y][x]=0; getregion1(p, pix[p.y][p.x]); } void fill(Point p, char v){ int x, y; getregion(p); for(y=0;y!=SIZE;y++) for(x=0;x!=SIZE;x++) if(region[y][x]) set(Pt(x, y), v); } int inregion(int x, int y){ return 0<=x && xr.min, Pt(3*BORDER, 3*BORDER)); smallr.max=addpt(smallr.min, Pt(SIZE, SIZE)); bigr.min=addpt(smallr.max, Pt(3*BORDER, 3*BORDER)); bigr.max=addpt(bigr.min, Pt(MAG*SIZE, MAG*SIZE)); if(!ptinrect(addpt(bigr.max, Pt(BORDER-1, BORDER-1)), screen->r)){ fprintf(stderr, "window too small, must be at least %d x %d\n", bigr.max.x-screen->r.min.x+BORDER-1, bigr.max.y-screen->r.min.y+BORDER-1); exits("window too big"); } rectf(screen, screen->r, bgcolor); color = darkgreen; border(screen, screen->r, BORDER, color, ZP); for(y=0; y!=SIZE; y++) for(x=0; x!=SIZE; x++) show(Pt(x, y)); } /* make magnufied lattice pattern image */ void initflats(void){ int i, scale; for(i=0; i>(6-x%4*2))&3); } void save(Image *b){ draw(b, b->r, screen, 0, smallr.min); } void input(char *name){ int i; Image *b; int fd=open(name, OREAD); if(fd<0){ Bad: fprintf(stderr, "Bad input %s\n", name); exits("bad input"); } for(i=0; i!=NPIECE; i++){ b=readimage(display, fd, 0); if(!b || !eqrect(b->r, Rect(0, 0, SIZE, SIZE)) || b->depth!=2) goto Bad; piece[i].image=b; } close(fd); } void output(char *name){ int i; int fd=create(name, OWRITE, 0666); if(fd<0){ fprintf(stderr, "Can't create %s\n", name); exits("bad output"); } for(i=0; i!=NPIECE; i++) writeimage(fd, piece[i].image, 0); close(fd); } void main(int argc, char *argv[]){ Mouse m; int i=0; if(argc!=3){ fprintf(stderr, "Usage: %s input output\n", argv[0]); exits("usage"); } initdraw(0, 0, "plumb"); einit(Emouse|Ekeyboard); darkgreen=allocimage(display, Rect(0, 0, 1, 1), display->windows->chan, 1, DDarkgreen); palegreen = allocimage(display, Rect(0,0,1,1), display->windows->chan, 1, DPalegreen); bgcolor = palegreen; initflats(); eresized(0); input(argv[1]); see(piece[i].image); for(;;){ m=emouse(); switch(m.buttons){ case 1: if(ptinrect(m.xy, bigr)){ switch(mode){ case Fill: fill(divpt(subpt(m.xy, bigr.min), MAG), curval); do m=emouse(); while(m.buttons); break; case Paint: set(divpt(subpt(m.xy, bigr.min), MAG), curval); break; case Relief: relief(divpt(subpt(m.xy, bigr.min), MAG)); do m=emouse(); while(m.buttons); break; } } break; case 2: switch(emenuhit(2, &m, &menu2)){ case 0: curval=3; break; case 1: curval=2; break; case 2: curval=1; break; case 3: curval=0; break; case 4: curval=4; break; case 5: mode=Paint; break; case 6: mode=Fill; break; case 7: mode=Relief; break; } break; case 4: switch(emenuhit(3, &m, &menu3)){ case 0: if(i0){ save(piece[i].image); see(piece[--i].image); } break; case 2: save(piece[i].image); output(argv[2]); break; case 3: save(piece[i].image); output(argv[2]); exits(0); } break; } } }