/********************************************************
PROGRAM_ID  : grim_ps.c converted from grim_app.c
PROGRAMMER  : Jaewook Shin
Date        : 95 . 4, 
              Jan. 2008
Description : The program generates the solution figures of the 
              Ji-Su-Gui-Moon-Do (Korean Magic Hexagon) program in 
              file "grim.ps" in postscript.
**********************************************************/
#include <stdio.h>




#define I_OFFSET    100
#define UNIT        50
#define RADIUS      15
#define	V_OFFSET    200
#define	H_OFFSET    100
#define	ROOT_2	    1.414
#define	THICK	    2
#define FONTSIZE    25
#define	C_OFFSET    (FONTSIZE/2)
#define NUM_SOL     30
#define HEIGHT      (UNIT*11)
#define WIDTH       (UNIT*6)
#define HAN         50
#define SCALE       0.34
#define PAGEHEIGHT  1700


void    print_field(char*,int,int);
void    print_line(int,int,int,int);
void 	print_hexagon(int, int);
void 	print_hexagon1(int, int);
void 	print_circle(int, int);
void 	circle(int, int);
void 	print_number(int, int);
void 	print_solval(int);
void    print_begin(); 

FILE    *outfp;

int e[40][30]={
/* 79 */{26, 14, 21, 3, 11, 29, 4, 23, 16, 15, 7, 13, 12, 19, 25, 27, 1, 2, 18, 10, 30, 8, 24, 5, 28, 9, 6, 20, 22, 17},
/* 80 */{17, 24, 16, 6, 14, 29, 3, 23, 10, 28, 7, 18, 4, 5, 9, 22, 11, 13, 26, 15, 19, 20, 21, 2, 25, 12, 1, 30, 8, 27},
/* 81 */{30, 25, 16, 1, 4, 26, 5, 28, 22, 24, 14, 8, 3, 6, 11, 18, 21, 20, 17, 9, 7, 13, 27, 2, 29, 15, 10, 12, 19, 23},
/* 82 */{6, 25, 26, 3, 17, 20, 5, 28, 24, 18, 10, 23, 12, 4, 30, 7, 14, 19, 8, 2, 15, 11, 29, 1, 27, 21, 9, 16, 22, 13},
/* 83 */{18, 23, 15, 20, 6, 21, 1, 30, 12, 19, 25, 29, 10, 2, 4, 13, 14, 16, 28, 5, 22, 8, 24, 11, 17, 7, 9, 26, 27, 3},
/* 84 */{8, 30, 18, 17, 6, 14, 5, 29, 25, 21, 4, 10, 2, 19, 12, 27, 9, 20, 26, 11, 13, 3, 28, 1, 24, 22, 23, 15, 7, 16},
/* 85 */{1, 19, 26, 20, 13, 16, 6, 30, 17, 24, 3, 14, 2, 9, 15, 29, 5, 23, 28, 18, 22, 7, 25, 4, 8, 11, 21, 27, 10, 12},
/* 86 */{4, 7, 25, 21, 19, 9, 10, 30, 1, 22, 3, 26, 23, 2, 28, 13, 6, 18, 27, 17, 15, 8, 29, 5, 16, 14, 24, 12, 11, 20},
/* 87 */{30, 26, 1, 3, 13, 11, 14, 8, 27, 20, 22, 16, 12, 10, 25, 18, 9, 7, 6, 5, 29, 17, 21, 4, 28, 19, 2, 23, 15, 24},
/* 88 */{10, 14, 27, 3, 21, 18, 13, 19, 25, 24, 4, 15, 5, 7, 23, 6, 20, 30, 8, 17, 2, 16, 22, 1, 28, 26, 11, 29, 9, 12},
/* 89 */{30, 7, 20, 5, 17, 29, 10, 4, 24, 18, 15, 11, 3, 25, 14, 19, 23, 12, 21, 9, 8, 2, 22, 26, 28, 1, 13, 6, 27, 16},
/* 90 */{6, 11, 5, 30, 25, 26, 13, 22, 10, 3, 18, 14, 8, 9, 4, 29, 28, 15, 21, 1, 27, 23, 20, 2, 7, 12, 16, 19, 24, 17},
/* 91 */{21, 27, 11, 2, 17, 24, 13, 19, 20, 23, 3, 30, 9, 16, 26, 25, 6, 22, 10, 1, 15, 14, 12, 28, 8, 29, 4, 18, 7, 5},
/* 92 */{27, 1, 17, 4, 30, 24, 13, 3, 9, 20, 18, 21, 22, 8, 29, 5, 7, 12, 14, 28, 23, 11, 2, 6, 25, 26, 15, 10, 19, 16},
/* 93 */{4, 23, 24, 13, 18, 28, 11, 29, 30, 8, 2, 12, 3, 25, 26, 15, 16, 21, 14, 17, 20, 5, 7, 27, 1, 6, 19, 10, 22, 9},
/* 94 */{29, 15, 12, 1, 9, 11, 28, 2, 7, 22, 10, 24, 25, 23, 18, 16, 14, 4, 19, 8, 6, 20, 27, 13, 21, 26, 30, 5, 3, 17},
/* 95 */{28, 21, 1, 26, 15, 25, 4, 29, 16, 19, 10, 9, 5, 18, 20, 11, 24, 27, 6, 30, 2, 14, 3, 23, 7, 13, 22, 8, 12, 17},
/* 96 */{22, 1, 8, 28, 30, 21, 7, 24, 25, 9, 16, 17, 6, 10, 20, 4, 29, 23, 14, 15, 19, 13, 5, 26, 3, 2, 12, 18, 11, 27},
/* 97 */{1, 3, 12, 30, 25, 13, 26, 6, 4, 16, 2, 20, 8, 22, 28, 9, 27, 14, 7, 29, 10, 24, 11, 5, 21, 15, 23, 18, 19, 17},
/* 98 */{14, 9, 3, 24, 28, 21, 20, 8, 18, 10, 2, 12, 5, 30, 22, 19, 27, 11, 4, 17, 15, 29, 6, 7, 13, 26, 23, 25, 1, 16},
/* 99 */{1, 28, 23, 19, 4, 9, 24, 3, 15, 14, 29, 17, 18, 25, 10, 20, 13, 21, 2, 16, 8, 12, 30, 26, 5, 6, 27, 7, 11, 22},
/* 100*/{27, 16, 2, 26, 4, 3, 25, 11, 7, 19, 29, 6, 20, 12, 10, 9, 28, 8, 17, 30, 13, 24, 5, 23, 14, 1, 18, 15, 21, 22},
/* 101*/{6, 16, 21, 11, 28, 5, 19, 2, 15, 26, 22, 10, 25, 4, 8, 18, 9, 23, 17, 24, 14, 27, 13, 29, 1, 12, 7, 30, 20, 3},
/* 102*/{30, 14, 3, 20, 11, 8, 24, 16, 26, 9, 25, 4, 15, 17, 21, 6, 29, 19, 2, 22, 13, 18, 10, 23, 1, 5, 28, 27, 7, 12},
/* 103*/{28, 6, 7, 15, 17, 11, 30, 1, 5, 18, 25, 29, 24, 12, 2, 8, 10, 23, 22, 27, 16, 19, 3, 21, 4, 26, 20, 14, 13, 9},
/* 104*/{1, 8, 23, 28, 14, 2, 30, 5, 19, 13, 27, 6, 12, 15, 7, 21, 29, 26, 11, 17, 9, 18, 4, 25, 16, 20, 10, 3, 22, 24},
/* 105*/{29, 16, 13, 14, 9, 8, 24, 4, 22, 17, 28, 11, 20, 23, 2, 15, 19, 25, 6, 18, 1, 21, 10, 27, 5, 30, 26, 7, 3, 12},
/* 106*/{6, 25, 10, 24, 11, 4, 30, 12, 18, 13, 21, 15, 17, 19, 9, 8, 28, 27, 1, 20, 2, 29, 7, 23, 3, 26, 22, 14, 5, 16},
/* 107*/{20, 4, 9, 30, 15, 1, 29, 7, 21, 16, 17, 13, 10, 23, 3, 11, 28, 25, 12, 24, 5, 27, 6, 26, 2, 18, 22, 19, 14, 8},
/* 108*/{4, 12, 9, 26, 27, 5, 30, 1, 20, 8, 17, 10, 19, 25, 11, 7, 24, 18, 15, 28, 14, 22, 3, 23, 2, 16, 29, 13, 6, 21}};

struct	{int	x,y;}
pos[30]={{3,0}, {2,1}, {4,1}, {2,2}, {4,2}, {1,3}, {3,3}, {5,3},
	 {1,4}, {3,4}, {5,4}, {0,5}, {2,5}, {4,5}, {6,5}, {0,6}, {2,6}, {4,6}, {6,6},
	 {1,7}, {3,7}, {5,7}, {1,8}, {3,8}, {5,8}, {2,9}, {4,9}, {2,10}, {4,10}, {3,11}};

int v_offset,
    h_offset;

main ()
{
    int i, j, k, page=1;

    print_begin();
    for(j=k=0; k<NUM_SOL; j++, k++){
	if(j%12==0){
	    if (j==12) fprintf(outfp, "showpage\n");
	    fprintf(outfp, "%%%%Page: %d\n", page++);
	    fprintf(outfp, "%f %f scale\n", SCALE, SCALE);
/* 	    print_field("Jaewook Shin, 1995, 2008", 100, 2350); */
            j = 0;
        }
	v_offset = PAGEHEIGHT-(I_OFFSET + j/4*V_OFFSET + j/4*HEIGHT);
	h_offset = I_OFFSET + j%4*H_OFFSET + j%4*WIDTH;
        print_hexagon(3, 0);circle(3,0);
        print_hexagon(2, 2);circle(2,2);
        print_hexagon(4, 2);circle(4,2);
        print_hexagon(1, 4);circle(1,4);
        print_hexagon(3, 4);circle(3,4);
        print_hexagon(5, 4);circle(5,4);
        print_hexagon(2, 6);circle(2,6);
        print_hexagon(4, 6);circle(4,6);
        print_hexagon(3, 8);circle(3,8);

	fprintf(outfp, "/Times-Roman findfont %d scalefont setfont\n", FONTSIZE);
        for(i=0; i<30; i++) print_number(k, i);
	fprintf(outfp, "/Times-Roman findfont %d scalefont setfont\n", HAN);
        print_solval(79+k);
    }
    fprintf(outfp, "showpage\n");
    fclose(outfp);

    return 0;
}

void print_solval(int solval)
{
    char    buf[20];
    int	h_o, v_o;

    v_o = HAN;
    h_o= HAN-15;
    sprintf(buf, "solution : %d", solval);
    print_field(buf, h_offset+h_o, 12*UNIT+v_offset+v_o);
}

void print_number(int k, int i)
{
    char buf[3];
    int	h_o, v_o;

    sprintf(buf, "%d", e[k][i]);
    v_o = FONTSIZE/2-20;
    if(e[k][i]>9) h_o=-FONTSIZE/2;
    else h_o=-FONTSIZE/4;

    print_field(buf, pos[i].x*UNIT+h_offset+h_o, pos[i].y*UNIT+v_offset+v_o);
}

void print_hexagon(int x, int y)
{
    int	r=(double)RADIUS/(double)ROOT_2+1;

    print_line(h_offset+UNIT*x-r,v_offset+UNIT*y+r,h_offset+UNIT*(x-1)+r,v_offset+UNIT*(y+1)-r);
    print_line(h_offset+UNIT*x+r,v_offset+UNIT*y+r,h_offset+UNIT*(x+1)-r,v_offset+UNIT*(y+1)-r);
    print_line(h_offset+UNIT*(x-1),v_offset+UNIT*(y+1)+RADIUS,h_offset+UNIT*(x-1),v_offset+UNIT*(y+2)-RADIUS);
    print_line(h_offset+UNIT*(x+1),v_offset+UNIT*(y+1)+RADIUS,h_offset+UNIT*(x+1),v_offset+UNIT*(y+2)-RADIUS);
    print_line(h_offset+UNIT*(x-1)+r,v_offset+UNIT*(y+2)+r,h_offset+UNIT*x-r,v_offset+UNIT*(y+3)-r);
    print_line(h_offset+UNIT*(x+1)-r,v_offset+UNIT*(y+2)+r,h_offset+UNIT*x+r,v_offset+UNIT*(y+3)-r);
    fprintf(outfp, "stroke\n");
}

void print_hexagon1(int x, int y)
{
    print_line(H_OFFSET+UNIT*x,V_OFFSET+UNIT*y,H_OFFSET+UNIT*(x-1),V_OFFSET+UNIT*(y+1));
    print_line(H_OFFSET+UNIT*x,V_OFFSET+UNIT*y,H_OFFSET+UNIT*(x+1),V_OFFSET+UNIT*(y+1));
    print_line(H_OFFSET+UNIT*(x-1),V_OFFSET+UNIT*(y+1),H_OFFSET+UNIT*(x-1),V_OFFSET+UNIT*(y+2));
    print_line(H_OFFSET+UNIT*(x+1),V_OFFSET+UNIT*(y+1),H_OFFSET+UNIT*(x+1),V_OFFSET+UNIT*(y+2));
    print_line(H_OFFSET+UNIT*(x-1),V_OFFSET+UNIT*(y+2),H_OFFSET+UNIT*x,V_OFFSET+UNIT*(y+3));
    print_line(H_OFFSET+UNIT*(x+1),V_OFFSET+UNIT*(y+2),H_OFFSET+UNIT*x,V_OFFSET+UNIT*(y+3));
    fprintf(outfp, "stroke\n");
}

void circle(int x, int y)
{
    print_circle(x,y);
    print_circle(x-1,y+1);
    print_circle(x+1,y+1);
    print_circle(x-1,y+2);
    print_circle(x+1,y+2);
    print_circle(x,y+3);
}

void print_circle(int x, int y)
{
    fprintf(outfp, "%d %d %d 0 360 arc\nclosepath\nstroke\n", 
	    h_offset+x*UNIT, v_offset+y*UNIT, RADIUS);
}

void print_begin() 
{
    outfp = fopen("grim.ps", "w");
    fprintf(outfp, "\%!PS-Adobe-2.0\n");
    fprintf(outfp, "\%\%Creator: Jaewook Shin\n\n");
    fprintf(outfp, "gsave\n");
    fprintf(outfp, "/Times-Roman findfont\n");
}


/*--------------------------------------------------------
  Line drawing
  ---------------------------------------------------------*/
void   print_line(int x1, int y1, int x2, int y2)
{
    fprintf(outfp, "%d %d moveto\n", x1, y1);
    fprintf(outfp, "%d %d lineto\n", x2, y2);
}

/*------------------------------------------------------
  For the title at the top
  --------------------------------------------------------*/
void   print_field(char* title, int x, int y)
{
    fprintf(outfp, "%d %d moveto\n", x, y);
    fprintf(outfp, "(%s) show\n", title);
}
