+ sprintf(buf, "%c%d,%d,%d",
+ (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);
+
+ ui->hx = ui->hy = -1;
+
+ return dupstr(buf);
+ }
+
+ return NULL;
+}
+
+static game_state *execute_move(game_state *from, char *move)
+{
+ int c = from->c, r = from->r, cr = c*r;
+ game_state *ret;
+ int x, y, n;
+
+ if (move[0] == 'S') {
+ char *p;
+
+ ret = dup_game(from);
+ ret->completed = ret->cheated = TRUE;
+
+ p = move+1;
+ for (n = 0; n < cr*cr; n++) {
+ ret->grid[n] = atoi(p);
+
+ if (!*p || ret->grid[n] < 1 || ret->grid[n] > cr) {
+ free_game(ret);
+ return NULL;
+ }
+
+ while (*p && isdigit((unsigned char)*p)) p++;
+ if (*p == ',') p++;
+ }
+
+ return ret;
+ } else if ((move[0] == 'P' || move[0] == 'R') &&
+ sscanf(move+1, "%d,%d,%d", &x, &y, &n) == 3 &&
+ x >= 0 && x < cr && y >= 0 && y < cr && n >= 0 && n <= cr) {
+