+ if (val & PIECE_TLCORNER)
+ draw_rect(dr, tx, ty, HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, ch);
+ if (val & PIECE_BRCORNER)
+ draw_rect(dr, tx+TILESIZE-HIGHLIGHT_WIDTH,
+ ty+TILESIZE-HIGHLIGHT_WIDTH,
+ HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, cl);
+}
+
+static void draw_piecepart(drawing *dr, game_drawstate *ds,
+ int tx, int ty, unsigned long val,
+ int cl, int cc, int ch)
+{
+ int x[6], y[6];
+
+ /*
+ * Drawing the blocks is hellishly fiddly. The blocks don't
+ * stretch to the full size of the tile; there's a border
+ * around them of size BORDER_WIDTH. Then they have bevelled
+ * borders of size HIGHLIGHT_WIDTH, and also rounded corners.
+ *
+ * I tried for some time to find a clean and clever way to
+ * figure out what needed drawing from the corner and border
+ * flags, but in the end the cleanest way I could find was the
+ * following. We divide the grid square into 25 parts by
+ * ruling four horizontal and four vertical lines across it;
+ * those lines are at BORDER_WIDTH and BORDER_WIDTH +
+ * HIGHLIGHT_WIDTH from the top, from the bottom, from the
+ * left and from the right. Then we carefully consider each of
+ * the resulting 25 sections of square, and decide separately
+ * what needs to go in it based on the flags. In complicated
+ * cases there can be up to five possibilities affecting any
+ * given section (no corner or border flags, just the corner
+ * flag, one border flag, the other border flag, both border
+ * flags). So there's a lot of very fiddly logic here and all
+ * I could really think to do was give it my best shot and
+ * then test it and correct all the typos. Not fun to write,
+ * and I'm sure it isn't fun to read either, but it seems to
+ * work.
+ */
+
+ x[0] = tx;
+ x[1] = x[0] + BORDER_WIDTH;
+ x[2] = x[1] + HIGHLIGHT_WIDTH;
+ x[5] = tx + TILESIZE;
+ x[4] = x[5] - BORDER_WIDTH;
+ x[3] = x[4] - HIGHLIGHT_WIDTH;
+
+ y[0] = ty;
+ y[1] = y[0] + BORDER_WIDTH;
+ y[2] = y[1] + HIGHLIGHT_WIDTH;
+ y[5] = ty + TILESIZE;
+ y[4] = y[5] - BORDER_WIDTH;
+ y[3] = y[4] - HIGHLIGHT_WIDTH;
+
+#define RECT(p,q) x[p], y[q], x[(p)+1]-x[p], y[(q)+1]-y[q]
+
+ maybe_rect(dr, RECT(0,0),
+ (val & (PIECE_TLCORNER | PIECE_TBORDER |
+ PIECE_LBORDER)) ? -1 : cc, -1);
+ maybe_rect(dr, RECT(1,0),
+ (val & PIECE_TLCORNER) ? ch : (val & PIECE_TBORDER) ? -1 :
+ (val & PIECE_LBORDER) ? ch : cc, -1);
+ maybe_rect(dr, RECT(2,0),
+ (val & PIECE_TBORDER) ? -1 : cc, -1);
+ maybe_rect(dr, RECT(3,0),
+ (val & PIECE_TRCORNER) ? cl : (val & PIECE_TBORDER) ? -1 :
+ (val & PIECE_RBORDER) ? cl : cc, -1);
+ maybe_rect(dr, RECT(4,0),
+ (val & (PIECE_TRCORNER | PIECE_TBORDER |
+ PIECE_RBORDER)) ? -1 : cc, -1);
+ maybe_rect(dr, RECT(0,1),
+ (val & PIECE_TLCORNER) ? ch : (val & PIECE_LBORDER) ? -1 :
+ (val & PIECE_TBORDER) ? ch : cc, -1);
+ maybe_rect(dr, RECT(1,1),
+ (val & PIECE_TLCORNER) ? cc : -1, -1);
+ maybe_rect(dr, RECT(1,1),
+ (val & PIECE_TLCORNER) ? ch | TYPE_TLCIRC :
+ !((PIECE_TBORDER | PIECE_LBORDER) &~ val) ? ch | TYPE_BRCIRC :
+ (val & (PIECE_TBORDER | PIECE_LBORDER)) ? ch : cc, -1);
+ maybe_rect(dr, RECT(2,1),
+ (val & PIECE_TBORDER) ? ch : cc, -1);
+ maybe_rect(dr, RECT(3,1),
+ (val & PIECE_TRCORNER) ? cc : -1, -1);
+ maybe_rect(dr, RECT(3,1),
+ (val & (PIECE_TBORDER | PIECE_RBORDER)) == PIECE_TBORDER ? ch :
+ (val & (PIECE_TBORDER | PIECE_RBORDER)) == PIECE_RBORDER ? cl :
+ !((PIECE_TBORDER|PIECE_RBORDER) &~ val) ? cl | TYPE_BLCIRC :
+ (val & PIECE_TRCORNER) ? cl | TYPE_TRCIRC :
+ cc, ch);
+ maybe_rect(dr, RECT(4,1),
+ (val & PIECE_TRCORNER) ? ch : (val & PIECE_RBORDER) ? -1 :
+ (val & PIECE_TBORDER) ? ch : cc, -1);
+ maybe_rect(dr, RECT(0,2),
+ (val & PIECE_LBORDER) ? -1 : cc, -1);
+ maybe_rect(dr, RECT(1,2),
+ (val & PIECE_LBORDER) ? ch : cc, -1);
+ maybe_rect(dr, RECT(2,2),
+ cc, -1);
+ maybe_rect(dr, RECT(3,2),
+ (val & PIECE_RBORDER) ? cl : cc, -1);
+ maybe_rect(dr, RECT(4,2),
+ (val & PIECE_RBORDER) ? -1 : cc, -1);
+ maybe_rect(dr, RECT(0,3),
+ (val & PIECE_BLCORNER) ? cl : (val & PIECE_LBORDER) ? -1 :
+ (val & PIECE_BBORDER) ? cl : cc, -1);
+ maybe_rect(dr, RECT(1,3),
+ (val & PIECE_BLCORNER) ? cc : -1, -1);
+ maybe_rect(dr, RECT(1,3),
+ (val & (PIECE_BBORDER | PIECE_LBORDER)) == PIECE_BBORDER ? cl :
+ (val & (PIECE_BBORDER | PIECE_LBORDER)) == PIECE_LBORDER ? ch :
+ !((PIECE_BBORDER|PIECE_LBORDER) &~ val) ? ch | TYPE_TRCIRC :
+ (val & PIECE_BLCORNER) ? ch | TYPE_BLCIRC :
+ cc, cl);
+ maybe_rect(dr, RECT(2,3),
+ (val & PIECE_BBORDER) ? cl : cc, -1);
+ maybe_rect(dr, RECT(3,3),
+ (val & PIECE_BRCORNER) ? cc : -1, -1);
+ maybe_rect(dr, RECT(3,3),
+ (val & PIECE_BRCORNER) ? cl | TYPE_BRCIRC :
+ !((PIECE_BBORDER | PIECE_RBORDER) &~ val) ? cl | TYPE_TLCIRC :
+ (val & (PIECE_BBORDER | PIECE_RBORDER)) ? cl : cc, -1);
+ maybe_rect(dr, RECT(4,3),
+ (val & PIECE_BRCORNER) ? cl : (val & PIECE_RBORDER) ? -1 :
+ (val & PIECE_BBORDER) ? cl : cc, -1);
+ maybe_rect(dr, RECT(0,4),
+ (val & (PIECE_BLCORNER | PIECE_BBORDER |
+ PIECE_LBORDER)) ? -1 : cc, -1);
+ maybe_rect(dr, RECT(1,4),
+ (val & PIECE_BLCORNER) ? ch : (val & PIECE_BBORDER) ? -1 :
+ (val & PIECE_LBORDER) ? ch : cc, -1);
+ maybe_rect(dr, RECT(2,4),
+ (val & PIECE_BBORDER) ? -1 : cc, -1);
+ maybe_rect(dr, RECT(3,4),
+ (val & PIECE_BRCORNER) ? cl : (val & PIECE_BBORDER) ? -1 :
+ (val & PIECE_RBORDER) ? cl : cc, -1);
+ maybe_rect(dr, RECT(4,4),
+ (val & (PIECE_BRCORNER | PIECE_BBORDER |
+ PIECE_RBORDER)) ? -1 : cc, -1);
+
+#undef RECT