Advertisement
r57shell

Sprites Splitting with GLPK

Jul 17th, 2013
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.35 KB | None | 0 0
  1. /////// DEFINES //////////////
  2. struct Sprite
  3. {
  4.     int type;
  5.     int x,y;
  6.     inline int sx() const
  7.     {
  8.         return ((type>>2)&3)+1;
  9.     }
  10.     inline int sy() const
  11.     {
  12.         return (type&3)+1;
  13.     }
  14.     int tc()
  15.     {
  16.         return sx()*sy();
  17.     }
  18. };
  19.  
  20. typedef std::vector<Sprite> SpriteList;
  21.  
  22. #define SIZE_X 400
  23. #define SIZE_Y 400
  24. #define CENTER_X (SIZE_X/2)
  25. #define CENTER_Y (SIZE_Y/2)
  26. unsigned char BMP[SIZE_X+32][SIZE_Y+32]; // FILL BMP YOURSELF
  27. char S[SIZE_X/8+4][SIZE_Y/8+4];
  28. bool N[0x10][SIZE_X/8][SIZE_Y/8];
  29.  
  30. ////// ALGORITHM /////////////
  31. int min = 100000, // min tiles init
  32.     mx, // x shift to achieve min tiles
  33.     my; // y shift to achieve min tiles
  34.  
  35. for (int sx=0; sx<8; ++sx) // brute x shift
  36.     for (int sy=0; sy<8; ++sy) // brute y shift
  37.     {
  38.         int c = 0; // tiles count for this shift
  39.         for (int x=sx; x<SIZE_X; x+=8) // brute x coord of tile
  40.             for (int y=sy; y<SIZE_Y; y+=8) // brute y coord of tile
  41.             {
  42.                 bool was = false; // was = tile not empty
  43.                 for (int i=0; i<8 && (!was); ++i)
  44.                     for (int j=0; j<8 && (!was); ++j)
  45.                         if (BMP[x+i][y+j])
  46.                             was = true; // tile not empty!
  47.                 if (was)
  48.                     ++c; // increment tiles count
  49.             }
  50.         if (c < min) // relax
  51.         {
  52.             min = c;
  53.             mx = sx;
  54.             my = sy;
  55.         }
  56.     }
  57.    
  58. memset(S, 0, sizeof(S)); // clear map: S[i][j] = not empty tile[i][j]?
  59.  
  60. for (int x=mx; x<SIZE_X; x+=8) // brute x coord of tile
  61.     for (int y=my; y<SIZE_Y; y+=8) // brute y coord of tile
  62.     {
  63.         bool was = false; // was = tile not empty?
  64.         for (int i=0; i<8 && (!was); ++i)
  65.             for (int j=0; j<8 && (!was); ++j)
  66.                 if (BMP[x+i][y+j])
  67.                     was = true; // tile not empty!
  68.         S[(x-mx)/8][(y-my)/8]=was; // tile[i][j] not empty!
  69.     }
  70.  
  71. FILE *f = fopen("tmtmp.gmpl", "w+"); // create temp gmpl file
  72.  
  73. memset(N, 0, sizeof(N)); // N[type][x][y] = need of var_type_x_y
  74. for (int x=0; x<SIZE_X/8; ++x)
  75.     for (int y=0; y<SIZE_Y/8; ++y)
  76.     {
  77.         Sprite s;   // dummy sprite object,
  78.                     // only for calculating sprite size from sprite type
  79.         for (s.type = 0; s.type < 0x10; ++s.type)
  80.         {
  81.             bool was = false; // was = sprite x,size_x,y,size_y not empty
  82.             for(int i=0; i<s.sx(); ++i) // calculate "was"
  83.                 for (int j=0; j<s.sy(); ++j)
  84.                     was |= S[x+i][y+j];
  85.             N[s.type][x][y] = was; // need of var_type_x_y.
  86.             if (was)
  87.                 fprintf(f,"var x%d_%d_%d, binary;\n",s.type,x,y); // define var in gmpl
  88.         }
  89.     }
  90.  
  91. // write function to minimize.
  92. fprintf(f,"minimize obj: ");
  93. {
  94. bool was = false; // was operand before?
  95. for (int x=0; x<SIZE_X/8; ++x)
  96.     for (int y=0; y<SIZE_Y/8; ++y)
  97.     {
  98.         Sprite s;   // dummy sprite object,
  99.                     // only for calculating sprite size from sprite type
  100.         for (s.type = 0; s.type < 0x10; ++s.type)
  101.         {
  102.             if (!N[s.type][x][y])
  103.                 continue;
  104.             if (!was) // if not was operand before - just space
  105.                 fprintf(f," ");
  106.             else
  107.                 fprintf(f," + ");
  108.             fprintf(f,"x%d_%d_%d*%d",s.type,x,y,s.tc()*200+1);
  109.             was = true;
  110.         }
  111.     }
  112. }
  113. fprintf(f,";\n");
  114.  
  115. // write optimizing bounds (conditions)
  116. int stc=0;
  117. for (int y=0; y<SIZE_Y/8; ++y)
  118.     for (int x=0; x<SIZE_X/8; ++x)
  119.     {
  120.         if (S[x][y]) // if tile x,y used
  121.         {
  122.             fprintf(f,"s.t. c%d: ", ++stc); // define new condition
  123.             bool was = false; // was first operand?
  124.             Sprite s;   // dummy sprite object,
  125.                         // only for calculating sprite size from sprite type
  126.             for (s.type = 0; s.type<0x10; ++s.type) // brute sprite type
  127.             {
  128.                 // brute sprites which can contain tile x,y
  129.                 for (int i=x-s.sx()+1; i<=x; ++i)
  130.                     for (int j=y-s.sy()+1; j<=y; ++j)
  131.                     {
  132.                         if (i<0||j<0)
  133.                             continue;
  134.                         if (was) // if was first operand, write +
  135.                             fprintf(f," + ");
  136.                         fprintf(f,"x%d_%d_%d",s.type,i,j);
  137.                         was = true;
  138.                     }
  139.             }
  140.             fprintf(f," >= 1;\n"); // tile x,y contains in one or more sprites
  141.         }
  142.     }
  143.  
  144. fprintf(f,"solve;\nend;\n"); // end of gmpl file
  145.  
  146. fclose(f);
  147. printf("%%%d\n",min); // write min tiles that can achieve if all sprites size = 1
  148.  
  149. SpriteList res1;
  150. char line[100];
  151.  
  152. // run glpsol
  153. system("glpk\\glpsol.exe -o qwqwe.txt -m tmtmp.gmpl >nul");
  154.  
  155. // read output
  156. f = fopen("qwqwe.txt","r");
  157. for(;!feof(f);)
  158. {
  159.     if (!fgets(line,100,f))
  160.         break; // end of file
  161.     int n = strlen(line);
  162.     if (n<8)
  163.         continue; // skip not needed lines
  164.     if (line[7]!='x')
  165.         continue; // skip not needed lines
  166.     Sprite s;
  167.     int w; // w = use of sprite
  168.     sscanf(line+7,"x%d_%d_%d * %d",&s.type,&s.x,&s.y,&w);
  169.     if (w) // if used
  170.         res1.push_back(s); // add sprite
  171. }
  172. fclose(f);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement