···11+# 1010 for Arduboy
22+33+Gameplay and scoring modeled after the
44+[1010!](https://itunes.apple.com/us/app/1010/id911793120?mt=8)
55+game for iOS.
66+77+Highlight one of the three randomly selected pieces with the left and
88+right directional buttons, then choose a piece with the A button.
99+Move it around on the board and place it anywhere that isn't overlapping
1010+with the A button, or press B to go back and choose a different piece.
1111+1212+Position ten blocks in a row or column and it is freed up, play continues
1313+until there are no free spaces to place any of the three pieces.
1414+1515+One point is scored for each block in the piece placed, and ten points
1616+are scored for clearing a row or column.
1717+1818+## Command Mode
1919+2020+Hold down both A+B buttons and:
2121+2222+- Up to make the screen backlight brighter,
2323+- Down to make it dimmer, or
2424+- Left or Right to reset the game.
2525+2626+## Compiling
2727+2828+Requires
2929+[Arduino-Makefile](https://github.com/sudar/Arduino-Makefile)
3030+installed.
3131+Adjust the path to `Arduino.mk` in `Makefile`.
3232+3333+Compile with `make` (requires GNU Make, which is `gmake` on OpenBSD).
3434+3535+Connect your Arduboy and power it on, then flash it with `make upload`.
+760
arduboy-1010.ino
···11+/*
22+ * 1010 for Arduboy
33+ * Copyright (c) 2018 joshua stein <jcs@jcs.org>
44+ *
55+ * Permission to use, copy, modify, and distribute this software for any
66+ * purpose with or without fee is hereby granted, provided that the above
77+ * copyright notice and this permission notice appear in all copies.
88+ *
99+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1010+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1111+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1212+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1313+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1414+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1515+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1616+ */
1717+1818+#include <EEPROM.h>
1919+#include <SPI.h>
2020+2121+#include <Arduboy2.h>
2222+2323+Arduboy2 arduboy;
2424+2525+/* this many tiles wide and tall */
2626+const byte BOARD_SIZE = 10;
2727+2828+/* pixel position of board */
2929+const byte BOARD_X = 66;
3030+const byte BOARD_Y = 1;
3131+3232+/* first two bytes of eeprom set to this to indicate a saved game */
3333+const byte SAVEFLAG = 254;
3434+3535+/* pieces to choose from in each round */
3636+const byte ONDECK = 3;
3737+3838+/* wait this many milliseconds between auto-repeat of d-pad buttons */
3939+const unsigned int AUTOREPEAT1 = 300;
4040+const unsigned int AUTOREPEATN = 75;
4141+4242+/* screen backlight levels */
4343+const byte SCREEN_MAX = 255;
4444+const byte SCREEN_MIN = 10;
4545+4646+/* game state, written out to eeprom as saved game */
4747+struct __attribute__((packed)) game_data {
4848+ byte saveflag0, saveflag1;
4949+ unsigned long hiscore, score;
5050+ byte ondeck[ONDECK];
5151+ byte ondecksel;
5252+ byte curshape;
5353+ byte x, y;
5454+ byte over;
5555+ byte board[BOARD_SIZE][BOARD_SIZE];
5656+} game;
5757+5858+/* possible tile modes */
5959+enum {
6060+ EMPTY,
6161+ TAKEN,
6262+ PLACING,
6363+ SWEEPING,
6464+};
6565+6666+/* tile pixmaps */
6767+const byte TILE_SIZE = 7;
6868+const byte BLOCK_SIZE = TILE_SIZE - 1;
6969+const byte colors[][TILE_SIZE] PROGMEM = {
7070+ { /* EMPTY */
7171+ B1111111,
7272+ B1000001,
7373+ B1000001,
7474+ B1000001,
7575+ B1000001,
7676+ B1000001,
7777+ B1111111,
7878+ },
7979+ { /* TAKEN */
8080+ B1111111,
8181+ B1010101,
8282+ B1101011,
8383+ B1010101,
8484+ B1101011,
8585+ B1010101,
8686+ B1111111,
8787+ },
8888+ {
8989+ /* PLACING */
9090+ B1111111,
9191+ B1111111,
9292+ B1111111,
9393+ B1111111,
9494+ B1111111,
9595+ B1111111,
9696+ B1111111,
9797+ },
9898+};
9999+100100+/* tiny tile pixmap to use for ondeck pieces */
101101+const byte PREVIEW_SIZE = 4;
102102+const byte preview_color[PREVIEW_SIZE] PROGMEM = {
103103+ B1111,
104104+ B1001,
105105+ B1001,
106106+ B1111,
107107+};
108108+109109+/* tile shapes */
110110+typedef struct {
111111+ const byte width, height;
112112+ const byte tiles[9];
113113+} shape;
114114+115115+const shape shapes[] = {
116116+ { 0, 0, { // empty
117117+ 0,
118118+ }
119119+ },
120120+ { 1, 1, { // dot
121121+ 1,
122122+ }
123123+ },
124124+ { 2, 2, { // 2x2 square
125125+ 1, 1,
126126+ 1, 1,
127127+ }
128128+ },
129129+ { 3, 3, { // 3x3 square
130130+ 1, 1, 1,
131131+ 1, 1, 1,
132132+ 1, 1, 1,
133133+ }
134134+ },
135135+ { 2, 1, { // 2x1 horizontal
136136+ 1, 1,
137137+ }
138138+ },
139139+ { 3, 1, { // 3x1 horizontal
140140+ 1, 1, 1,
141141+ }
142142+ },
143143+ { 4, 1, { // 4x1 horizontal
144144+ 1, 1, 1, 1,
145145+ }
146146+ },
147147+ { 5, 1, { // 5x1 horizontal
148148+ 1, 1, 1, 1, 1,
149149+ }
150150+ },
151151+ { 1, 2, { // 1x2 vertical
152152+ 1,
153153+ 1,
154154+ }
155155+ },
156156+ { 1, 3, { // 1x3 vertical
157157+ 1,
158158+ 1,
159159+ 1,
160160+ }
161161+ },
162162+ { 1, 4, { // 1x4 vertical
163163+ 1,
164164+ 1,
165165+ 1,
166166+ 1,
167167+ }
168168+ },
169169+ { 1, 5, { // 1x5 vertical
170170+ 1,
171171+ 1,
172172+ 1,
173173+ 1,
174174+ 1,
175175+ }
176176+ },
177177+ { 2, 2, { // 2x2 elbow
178178+ 1, 1,
179179+ 0, 1,
180180+ }
181181+ },
182182+ { 2, 2, { // 2x2 elbow
183183+ 1, 0,
184184+ 1, 1,
185185+ }
186186+ },
187187+ { 2, 2, { // 2x2 elbow
188188+ 1, 1,
189189+ 1, 0,
190190+ }
191191+ },
192192+ { 2, 2, { // 2x2 elbow
193193+ 0, 1,
194194+ 1, 1,
195195+ }
196196+ },
197197+ { 3, 3, { // 3x3 elbow
198198+ 1, 1, 1,
199199+ 0, 0, 1,
200200+ 0, 0, 1,
201201+ }
202202+ },
203203+ { 3, 3, { // 3x3 elbow
204204+ 1, 0, 0,
205205+ 1, 0, 0,
206206+ 1, 1, 1,
207207+ }
208208+ },
209209+ { 3, 3, { // 3x3 elbow
210210+ 1, 1, 1,
211211+ 1, 0, 0,
212212+ 1, 0, 0,
213213+ }
214214+ },
215215+ { 3, 3, { // 3x3 elbow
216216+ 0, 0, 1,
217217+ 0, 0, 1,
218218+ 1, 1, 1,
219219+ }
220220+ },
221221+};
222222+223223+void backlight(int);
224224+void new_game(void);
225225+void save_game(void);
226226+uint8_t pressed_dpad_autorepeat(void);
227227+bool place_shape(void);
228228+void draw_screen(void);
229229+void draw_board(void);
230230+void draw_shape(const shape *s, const byte, const byte, const byte,
231231+ const byte[]);
232232+byte left_ondeck(void);
233233+void new_shapes(void);
234234+bool shape_clear(const shape *s, const byte, const byte);
235235+bool move_to_clear(const shape *s);
236236+237237+/* these don't need to be preserved in game state */
238238+static byte leds[3] = { 0 };
239239+static int8_t ledsweep[3] = { 0 };
240240+static unsigned long dpad_millis_next = 0;
241241+static bool dpad_repeatn = false;
242242+static int screen_backlight = SCREEN_MAX;
243243+244244+void
245245+setup(void)
246246+{
247247+ arduboy.begin();
248248+ arduboy.initRandomSeed();
249249+250250+ /*
251251+ * setup screen backlight adjustment
252252+ * https://community.arduboy.com/t/screen-brightness/2662/22
253253+ */
254254+ arduboy.LCDCommandMode();
255255+ SPI.transfer(0xd9);
256256+ SPI.transfer(0x2f);
257257+ SPI.transfer(0xdb);
258258+ SPI.transfer(0x00);
259259+ SPI.transfer(0x81);
260260+ SPI.transfer(screen_backlight);
261261+ arduboy.LCDDataMode();
262262+263263+ if (EEPROM.read(0) == SAVEFLAG && EEPROM.read(1) == SAVEFLAG) {
264264+ EEPROM.get(0, game);
265265+266266+ if (game.over)
267267+ new_game();
268268+ }
269269+ else
270270+ new_game();
271271+272272+ arduboy.fillRect(0, 0, BOARD_X - 1, 64, BLACK);
273273+ draw_screen();
274274+}
275275+276276+void
277277+backlight(int level)
278278+{
279279+ if (level < SCREEN_MIN)
280280+ level = SCREEN_MIN;
281281+ else if (level > SCREEN_MAX)
282282+ level = SCREEN_MAX;
283283+284284+ arduboy.LCDCommandMode();
285285+ SPI.transfer(0x81);
286286+ SPI.transfer(level);
287287+ arduboy.LCDDataMode();
288288+289289+ screen_backlight = level;
290290+}
291291+292292+void
293293+new_game(void)
294294+{
295295+ unsigned long oldhi = game.hiscore;
296296+297297+ memset(&game, 0, sizeof(game_data));
298298+ game.hiscore = oldhi;
299299+300300+ memset(&leds, 0, sizeof(leds));
301301+ memset(&ledsweep, 0, sizeof(ledsweep));
302302+ game.saveflag0 = SAVEFLAG;
303303+ game.saveflag1 = SAVEFLAG;
304304+305305+ arduboy.setRGBled(0, 0, 0);
306306+307307+ new_shapes();
308308+309309+ save_game();
310310+}
311311+312312+void
313313+save_game(void)
314314+{
315315+ EEPROM.put(0, game);
316316+}
317317+318318+uint8_t
319319+pressed_dpad_autorepeat(void)
320320+{
321321+ bool left = false;
322322+ bool right = false;
323323+ bool up = false;
324324+ bool down = false;
325325+ uint8_t ret = 0;
326326+327327+ /*
328328+ * arduboy.pressed() checks for all passed buttons at once, so check
329329+ * each individually
330330+ */
331331+ left = arduboy.pressed(LEFT_BUTTON);
332332+ right = arduboy.pressed(RIGHT_BUTTON);
333333+ up = arduboy.pressed(UP_BUTTON);
334334+ down = arduboy.pressed(DOWN_BUTTON);
335335+336336+ ret = (left ? LEFT_BUTTON : 0) | (right ? RIGHT_BUTTON : 0) |
337337+ (up ? UP_BUTTON : 0) | (down ? DOWN_BUTTON : 0);
338338+339339+ if (ret == 0) {
340340+ dpad_millis_next = 0;
341341+ dpad_repeatn = false;
342342+ return 0;
343343+ }
344344+345345+ if (dpad_millis_next == 0) {
346346+ /* first pressing of buttons, return immediately */
347347+ dpad_millis_next = millis() + AUTOREPEAT1;
348348+ dpad_repeatn = true;
349349+ return ret;
350350+ }
351351+352352+ if (millis() >= dpad_millis_next) {
353353+ dpad_millis_next = millis() + (dpad_repeatn ? AUTOREPEATN :
354354+ AUTOREPEAT1);
355355+ return ret;
356356+ }
357357+358358+ /* otherwise we're waiting until dpad_millis_next */
359359+ return 0;
360360+}
361361+362362+void
363363+game_over(void)
364364+{
365365+ game.over = true;
366366+ ledsweep[0] = 1;
367367+368368+ arduboy.fillRect(0, 40, BOARD_X - 1, 64, BLACK);
369369+370370+ arduboy.setCursor(0, 50);
371371+ arduboy.print(F("Game Over"));
372372+373373+ arduboy.display();
374374+ save_game();
375375+}
376376+377377+void
378378+loop(void)
379379+{
380380+ const shape *s;
381381+ bool redraw = false;
382382+ int8_t x;
383383+ uint8_t dpad;
384384+385385+ if (!arduboy.nextFrame())
386386+ return;
387387+388388+ arduboy.pollButtons();
389389+390390+ /* command mode */
391391+ if (arduboy.pressed(A_BUTTON + B_BUTTON)) {
392392+ if (arduboy.justPressed(DOWN_BUTTON))
393393+ backlight(screen_backlight - 20);
394394+ else if (arduboy.justPressed(UP_BUTTON))
395395+ backlight(screen_backlight + 20);
396396+ else if (arduboy.justPressed(LEFT_BUTTON) ||
397397+ arduboy.justPressed(RIGHT_BUTTON)) {
398398+ new_game();
399399+ draw_screen();
400400+ }
401401+402402+ return;
403403+ }
404404+405405+ if (game.over) {
406406+ /* if we achieved the high score, flash green, else red */
407407+ x = (game.score == game.hiscore ? 1 : 0);
408408+409409+ if (ledsweep[x] == 1) {
410410+ if (leds[x] >= 50)
411411+ ledsweep[x] = -1;
412412+ else
413413+ leds[x]++;
414414+ } else {
415415+ if (leds[x] <= 10)
416416+ ledsweep[x] = 1;
417417+ else
418418+ leds[x]--;
419419+ }
420420+421421+ arduboy.setRGBled(leds[0], leds[1], leds[2]);
422422+423423+ if (arduboy.justPressed(A_BUTTON) ||
424424+ arduboy.justPressed(B_BUTTON)) {
425425+ new_game();
426426+ draw_screen();
427427+ return;
428428+ }
429429+ }
430430+431431+ if (game.curshape == 0) {
432432+ /* selecting an ondeck piece */
433433+ if (arduboy.justPressed(LEFT_BUTTON)) {
434434+ for (x = game.ondecksel - 1; x >= 0; x--) {
435435+ if (game.ondeck[x]) {
436436+ game.ondecksel = x;
437437+ redraw = true;
438438+ break;
439439+ }
440440+ }
441441+ } else if (arduboy.justPressed(RIGHT_BUTTON)) {
442442+ for (x = game.ondecksel + 1; x < ONDECK; x++) {
443443+ if (game.ondeck[x]) {
444444+ game.ondecksel = x;
445445+ redraw = true;
446446+ break;
447447+ }
448448+ }
449449+ } else if (arduboy.justPressed(A_BUTTON) ||
450450+ arduboy.justPressed(B_BUTTON)) {
451451+ game.curshape = game.ondeck[game.ondecksel];
452452+ game.ondeck[game.ondecksel] = 0;
453453+454454+ if (!move_to_clear(&shapes[game.curshape])) {
455455+ game_over();
456456+ return;
457457+ }
458458+459459+ redraw = true;
460460+ }
461461+ } else {
462462+ /* moving the selected piece around on the board */
463463+ s = &shapes[game.curshape];
464464+465465+ if (arduboy.justPressed(A_BUTTON)) {
466466+ if (place_shape())
467467+ redraw = true;
468468+ else {
469469+ arduboy.setRGBled(50, 0, 0);
470470+ delay(50);
471471+ arduboy.setRGBled(leds[0], leds[1], leds[2]);
472472+ }
473473+ } else if (arduboy.justPressed(B_BUTTON)) {
474474+ /* put the piece back on deck */
475475+ game.ondeck[game.ondecksel] = game.curshape;
476476+ game.curshape = 0;
477477+ redraw = true;
478478+ } else {
479479+ dpad = pressed_dpad_autorepeat();
480480+ redraw = true;
481481+482482+ if ((dpad & UP_BUTTON) && (game.y > 0))
483483+ game.y--;
484484+ else if ((dpad & DOWN_BUTTON) &&
485485+ (game.y < BOARD_SIZE - s->height))
486486+ game.y++;
487487+ else if ((dpad & LEFT_BUTTON) && (game.x > 0))
488488+ game.x--;
489489+ else if ((dpad & RIGHT_BUTTON) &&
490490+ (game.x < BOARD_SIZE - s->width))
491491+ game.x++;
492492+ else
493493+ redraw = false;
494494+ }
495495+ }
496496+497497+ if (redraw)
498498+ draw_screen();
499499+}
500500+501501+void
502502+draw_screen(void)
503503+{
504504+ const shape *s = NULL;
505505+ const shape *ts = NULL;
506506+ int i;
507507+ byte x;
508508+509509+ draw_board();
510510+511511+ if (game.curshape > 0 && !game.over) {
512512+ s = &shapes[game.curshape];
513513+514514+ draw_shape(s, BOARD_X + (game.x * BLOCK_SIZE),
515515+ BOARD_Y + (game.y * BLOCK_SIZE), BLOCK_SIZE,
516516+ colors[PLACING]);
517517+ }
518518+519519+ arduboy.setCursor(0, 0);
520520+ arduboy.print(F("Score\n"));
521521+ arduboy.print(game.score);
522522+523523+ arduboy.setCursor(0, 20);
524524+ arduboy.print(F("Hi-Score\n"));
525525+ arduboy.print(game.hiscore);
526526+527527+ /* previews */
528528+ for (x = 0; x < sizeof(game.ondeck); x++) {
529529+ ts = &shapes[game.ondeck[x]];
530530+ if (ts == 0)
531531+ continue;
532532+533533+ i = (((BOARD_X - 10) / ONDECK) * (x + 1)) -
534534+ ((BOARD_X - 10) / (ONDECK * 2));
535535+536536+ draw_shape(ts,
537537+ i - ((ts->width * PREVIEW_SIZE) / 2),
538538+ 48 - ((ts->height * PREVIEW_SIZE) / 2),
539539+ PREVIEW_SIZE, preview_color);
540540+541541+ if (x == game.ondecksel && !game.curshape) {
542542+ arduboy.drawPixel(i, 59, WHITE);
543543+ arduboy.drawLine(i - 1, 60, i + 1, 60, WHITE);
544544+ arduboy.drawLine(i - 2, 61, i + 2, 61, WHITE);
545545+ }
546546+ }
547547+548548+ arduboy.display();
549549+}
550550+551551+void
552552+draw_board(void)
553553+{
554554+ byte x, y;
555555+556556+ arduboy.clear();
557557+558558+ for (y = 0; y < BOARD_SIZE; y++)
559559+ for (x = 0; x < BOARD_SIZE; x++)
560560+ arduboy.drawBitmap(BOARD_X + (x * BLOCK_SIZE),
561561+ BOARD_Y + (y * BLOCK_SIZE),
562562+ colors[game.board[x][y]],
563563+ TILE_SIZE, TILE_SIZE, WHITE);
564564+565565+ arduboy.drawLine(BOARD_X + 1,
566566+ BOARD_Y + (BOARD_SIZE * BLOCK_SIZE) + 1,
567567+ BOARD_X + (BOARD_SIZE * BLOCK_SIZE) + 1,
568568+ BOARD_Y + (BOARD_SIZE * BLOCK_SIZE) + 1,
569569+ WHITE);
570570+ arduboy.drawLine(BOARD_X + (BOARD_SIZE * BLOCK_SIZE) + 1,
571571+ BOARD_Y + 1,
572572+ BOARD_X + (BOARD_SIZE * BLOCK_SIZE) + 1,
573573+ BOARD_Y + (BOARD_SIZE * BLOCK_SIZE) + 1,
574574+ WHITE);
575575+}
576576+577577+byte
578578+left_ondeck(void)
579579+{
580580+ byte x, od = 0;
581581+582582+ for (x = 0; x < ONDECK; x++) {
583583+ if (game.ondeck[x] != 0)
584584+ od++;
585585+ }
586586+587587+ return od;
588588+}
589589+590590+void
591591+new_shapes(void)
592592+{
593593+ byte x;
594594+595595+ if (left_ondeck())
596596+ return;
597597+598598+ for (x = 0; x < ONDECK; x++)
599599+ game.ondeck[x] = random(1, sizeof(shapes) / sizeof(shape));
600600+}
601601+602602+bool
603603+shape_clear(const shape *s, const byte x, const byte y)
604604+{
605605+ byte tx, ty;
606606+607607+ if (x + s->width > BOARD_SIZE || y + s->height > BOARD_SIZE)
608608+ return false;
609609+610610+ for (ty = 0; ty < s->height; ty++)
611611+ for (tx = 0; tx < s->width; tx++)
612612+ if (s->tiles[tx + (ty * s->width)] != EMPTY &&
613613+ game.board[x + tx][y + ty] != EMPTY)
614614+ return false;
615615+616616+ return true;
617617+}
618618+619619+bool
620620+move_to_clear(const shape *s)
621621+{
622622+ for (game.y = 0; game.y <= BOARD_SIZE - s->height; game.y++)
623623+ for (game.x = 0; game.x <= BOARD_SIZE - s->width; game.x++)
624624+ if (shape_clear(s, game.x, game.y))
625625+ return true;
626626+627627+ return false;
628628+}
629629+630630+void
631631+draw_shape(const shape *s, const byte x, const byte y, const byte size,
632632+ const byte color[])
633633+{
634634+ byte tx, ty;
635635+636636+ /* walk the shape, stamping its tile in each non-zero spot */
637637+ for (ty = 0; ty < s->height; ty++)
638638+ for (tx = 0; tx < s->width; tx++)
639639+ if (s->tiles[tx + (ty * s->width)])
640640+ arduboy.drawBitmap(x + (tx * size),
641641+ y + (ty * size), color, size, size,
642642+ WHITE);
643643+}
644644+645645+void
646646+explode_swept(void)
647647+{
648648+ byte i, x, y;
649649+650650+ for (i = 1; i < TILE_SIZE; i++) {
651651+ for (x = 0; x < BOARD_SIZE; x++)
652652+ for (y = 0; y < BOARD_SIZE; y++) {
653653+ if (game.board[x][y] != SWEEPING)
654654+ continue;
655655+656656+ arduboy.drawRect(BOARD_X + (x * BLOCK_SIZE) + i,
657657+ BOARD_Y + (y * BLOCK_SIZE) + i,
658658+ BLOCK_SIZE - i, BLOCK_SIZE - i,
659659+ BLACK);
660660+ }
661661+662662+ arduboy.display();
663663+ delay(40 + (i * 10));
664664+ }
665665+666666+ for (x = 0; x < BOARD_SIZE; x++)
667667+ for (y = 0; y < BOARD_SIZE; y++)
668668+ if (game.board[x][y] == SWEEPING)
669669+ game.board[x][y] = EMPTY;
670670+}
671671+672672+bool
673673+place_shape(void)
674674+{
675675+ const shape *s = &shapes[game.curshape];
676676+ byte x, y;
677677+ int c;
678678+ bool swept = false;
679679+680680+ if (!shape_clear(s, game.x, game.y))
681681+ return false;
682682+683683+ for (y = 0; y < s->height; y++) {
684684+ for (x = 0; x < s->width; x++) {
685685+ if (s->tiles[x + (y * s->width)] != EMPTY) {
686686+ game.board[game.x + x][game.y + y] =
687687+ s->tiles[x + (y * s->width)];
688688+689689+ game.score++;
690690+ }
691691+ }
692692+ }
693693+694694+ /*
695695+ * Sweep through each row, then each column, and mark any completed
696696+ * rows or columns as such. Then sweep through again and clear them
697697+ * out.
698698+ *
699699+ * This must be done twice because otherwise when a column and row are
700700+ * both complete, clearing out one would break the completion of the
701701+ * other one.
702702+ */
703703+ for (y = 0; y < BOARD_SIZE; y++) {
704704+ for (x = 0, c = 0; x < BOARD_SIZE; x++)
705705+ if (game.board[x][y] != EMPTY)
706706+ c++;
707707+708708+ if (c == BOARD_SIZE) {
709709+ /* complete row, empty */
710710+ for (x = 0; x < BOARD_SIZE; x++) {
711711+ game.board[x][y] = SWEEPING;
712712+ game.score++;
713713+ swept = true;
714714+ }
715715+ }
716716+ }
717717+718718+ for (x = 0; x < BOARD_SIZE; x++) {
719719+ for (y = 0, c = 0; y < BOARD_SIZE; y++)
720720+ if (game.board[x][y] != EMPTY)
721721+ c++;
722722+723723+ if (c == BOARD_SIZE) {
724724+ /* complete column, empty */
725725+ for (y = 0; y < BOARD_SIZE; y++) {
726726+ game.board[x][y] = SWEEPING;
727727+ game.score++;
728728+ swept = true;
729729+ }
730730+ }
731731+ }
732732+733733+ if (swept)
734734+ explode_swept();
735735+736736+ if (game.score > game.hiscore)
737737+ game.hiscore = game.score;
738738+739739+ game.curshape = 0;
740740+ new_shapes();
741741+742742+ /* auto-highlight the next available on-deck piece */
743743+ for (x = 0; x < ONDECK; x++)
744744+ if (game.ondeck[x] != 0) {
745745+ game.ondecksel = x;
746746+ break;
747747+ }
748748+749749+ save_game();
750750+751751+ /* if there is only one piece left and it can't be placed, don't bother
752752+ * waiting for the user to select it */
753753+ if (left_ondeck() == 1 &&
754754+ !move_to_clear(&shapes[game.ondeck[game.ondecksel]])) {
755755+ game_over();
756756+ return false;
757757+ }
758758+759759+ return true;
760760+}