+static game_state *execute_move(game_state *from, char *move)
+{
+ game_state *ret;
+ int x1, y1, x2, y2, mode;
+
+ if (move[0] == 'S') {
+ char *p = move+1;
+ int x, y;
+
+ ret = dup_game(from);
+ ret->cheated = TRUE;
+
+ for (y = 0; y < ret->h; y++)
+ for (x = 1; x < ret->w; x++) {
+ vedge(ret, x, y) = (*p == '1');
+ if (*p) p++;
+ }
+ for (y = 1; y < ret->h; y++)
+ for (x = 0; x < ret->w; x++) {
+ hedge(ret, x, y) = (*p == '1');
+ if (*p) p++;
+ }
+
+ return ret;
+
+ } else if (move[0] == 'R' &&
+ sscanf(move+1, "%d,%d,%d,%d", &x1, &y1, &x2, &y2) == 4 &&
+ x1 >= 0 && x2 >= 0 && x1+x2 <= from->w &&
+ y1 >= 0 && y2 >= 0 && y1+y2 <= from->h) {
+ x2 += x1;
+ y2 += y1;
+ mode = move[0];
+ } else if ((move[0] == 'H' || move[0] == 'V') &&
+ sscanf(move+1, "%d,%d", &x1, &y1) == 2 &&
+ (move[0] == 'H' ? HRANGE(from, x1, y1) :
+ VRANGE(from, x1, y1))) {
+ mode = move[0];
+ } else
+ return NULL; /* can't parse move string */
+
+ ret = dup_game(from);
+
+ if (mode == 'R') {
+ grid_draw_rect(ret, ret->hedge, ret->vedge, 1, TRUE, x1, y1, x2, y2);
+ } else if (mode == 'H') {
+ hedge(ret,x1,y1) = !hedge(ret,x1,y1);
+ } else if (mode == 'V') {
+ vedge(ret,x1,y1) = !vedge(ret,x1,y1);
+ }
+
+ /*
+ * We've made a real change to the grid. Check to see
+ * if the game has been completed.
+ */
+ if (!ret->completed) {
+ int x, y, ok;
+ unsigned char *correct = get_correct(ret);
+
+ ok = TRUE;
+ for (x = 0; x < ret->w; x++)
+ for (y = 0; y < ret->h; y++)
+ if (!index(ret, correct, x, y))
+ ok = FALSE;
+
+ sfree(correct);
+
+ if (ok)
+ ret->completed = TRUE;
+ }
+
+ return ret;
+}
+