Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2005 Dave Chapman |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | |
| 22 | /*** |
| 23 | Sudoku by Dave Chapman |
| 24 | |
| 25 | User instructions |
| 26 | ----------------- |
| 27 | |
| 28 | Use the arrow keys to move cursor, and press SELECT/ON/F2 to increment |
| 29 | the number under the cursor. |
| 30 | |
| 31 | At any time during the game, press On to bring up the game menu with |
| 32 | further options: |
| 33 | |
| 34 | Save |
| 35 | Reload |
| 36 | Clear |
| 37 | Solve |
| 38 | |
| 39 | Sudoku is implemented as a "viewer" for a ".ss" file, as generated by |
| 40 | Simple Sudoku and other applications - http://angusj.com/sudoku/ |
| 41 | |
| 42 | In-progress game positions are saved in the original .ss file, with |
| 43 | A-I used to indicate numbers entered by the user. |
| 44 | |
| 45 | Example ".ss" file, and one with a saved state: |
| 46 | |
| 47 | ...|...|... ...|...|... |
| 48 | 2..|8.4|9.1 2.C|8.4|9.1 |
| 49 | ...|1.6|32. E..|1.6|32. |
| 50 | ----------- ----------- |
| 51 | ...|..5|.4. ...|..5|.4. |
| 52 | 8..|423|..6 8..|423|..6 |
| 53 | .3.|9..|... .3D|9..|A.. |
| 54 | ----------- ----------- |
| 55 | .63|7.9|... .63|7.9|... |
| 56 | 4.9|5.2|..8 4.9|5.2|.C8 |
| 57 | ...|...|... ...|...|... |
| 58 | |
| 59 | */ |
| 60 | |
| 61 | #include "plugin.h" |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 62 | #include "lib/configfile.h" |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 63 | #include "lib/oldmenuapi.h" |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 64 | |
| 65 | #ifdef HAVE_LCD_BITMAP |
| 66 | |
Dave Chapman | bf99952 | 2006-04-01 23:23:07 +0000 | [diff] [blame] | 67 | #include <lib/playback_control.h> |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 68 | #include "sudoku.h" |
| 69 | #include "generator.h" |
| 70 | |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 71 | /* The bitmaps */ |
| 72 | #include "sudoku_normal.h" |
| 73 | #include "sudoku_inverse.h" |
| 74 | #include "sudoku_start.h" |
| 75 | |
| 76 | #define BITMAP_HEIGHT (BMPHEIGHT_sudoku_normal/10) |
| 77 | #define BITMAP_STRIDE BMPWIDTH_sudoku_normal |
| 78 | |
Jens Arnold | a36b1d4 | 2006-01-15 18:20:18 +0000 | [diff] [blame] | 79 | PLUGIN_HEADER |
| 80 | |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 81 | /* here is a global api struct pointer. while not strictly necessary, |
| 82 | it's nice not to have to pass the api pointer in all function calls |
| 83 | in the plugin */ |
| 84 | |
Steve Bavin | 6526577 | 2008-05-13 09:57:56 +0000 | [diff] [blame] | 85 | const struct plugin_api* rb; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 86 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 87 | /* Default game - used to initialise sudoku.ss if it doesn't exist. */ |
| 88 | static const char default_game[9][9] = |
| 89 | { |
| 90 | { '0','1','0', '3','0','7', '0','0','4' }, |
| 91 | { '0','0','0', '0','6','0', '1','0','2' }, |
| 92 | { '0','0','0', '0','8','0', '5','6','0' }, |
| 93 | |
| 94 | { '0','6','0', '0','0','0', '0','2','9' }, |
| 95 | { '0','0','0', '5','0','3', '0','0','0' }, |
| 96 | { '7','9','0', '0','0','0', '0','3','0' }, |
| 97 | |
| 98 | { '0','8','5', '0','3','0', '0','0','0' }, |
| 99 | { '1','0','2', '0','7','0', '0','0','0' }, |
| 100 | { '0','0','0', '4','0','8', '0','5','0' }, |
| 101 | }; |
| 102 | |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 103 | #if LCD_HEIGHT <= LCD_WIDTH /* Horizontal layout, scratchpad at the left */ |
| 104 | |
| 105 | #if (LCD_HEIGHT==64) && (LCD_WIDTH==112) |
| 106 | /* Archos Recorders and Ondios - 112x64, 9 cells @ 8x6 with 10 border lines */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 107 | |
| 108 | /* Internal dimensions of a cell */ |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 109 | #define CELL_WIDTH 8 |
| 110 | #define CELL_HEIGHT 6 |
| 111 | #define SMALL_BOARD |
| 112 | |
Marianne Arnold | 12ddb8e | 2007-09-20 10:49:48 +0000 | [diff] [blame] | 113 | #elif ((LCD_HEIGHT==80) && (LCD_WIDTH==132)) |
| 114 | /* C200, 9 cells @ 8x8 with 8 border lines */ |
| 115 | |
| 116 | /* Internal dimensions of a cell */ |
| 117 | #define CELL_WIDTH 8 |
| 118 | #define CELL_HEIGHT 8 |
| 119 | #define SMALL_BOARD |
| 120 | |
Jens Arnold | 106ac75 | 2008-03-22 14:20:04 +0000 | [diff] [blame] | 121 | #elif ((LCD_HEIGHT==96) && (LCD_WIDTH==128)) |
| 122 | /* iAudio M3, 9 cells @ 9x9 with 14 border lines */ |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 123 | |
| 124 | /* Internal dimensions of a cell */ |
Jens Arnold | 106ac75 | 2008-03-22 14:20:04 +0000 | [diff] [blame] | 125 | #define CELL_WIDTH 9 |
| 126 | #define CELL_HEIGHT 9 |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 127 | |
Jens Arnold | 106ac75 | 2008-03-22 14:20:04 +0000 | [diff] [blame] | 128 | #elif (LCD_HEIGHT==110) && (LCD_WIDTH==138) \ |
| 129 | || (LCD_HEIGHT==128) && (LCD_WIDTH==128) |
| 130 | /* iPod Mini - 138x110, 9 cells @ 10x10 with 14 border lines */ |
Jens Arnold | f36d0de | 2006-09-18 21:44:24 +0000 | [diff] [blame] | 131 | /* iriver H10 5-6GB - 128x128, 9 cells @ 10x10 with 14 border lines */ |
| 132 | |
| 133 | /* Internal dimensions of a cell */ |
| 134 | #define CELL_WIDTH 10 |
| 135 | #define CELL_HEIGHT 10 |
| 136 | |
Jens Arnold | 106ac75 | 2008-03-22 14:20:04 +0000 | [diff] [blame] | 137 | #elif ((LCD_HEIGHT==128) && (LCD_WIDTH==160)) \ |
| 138 | || ((LCD_HEIGHT==132) && (LCD_WIDTH==176)) |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 139 | /* iAudio X5, Iriver H1x0, iPod G3, G4 - 160x128; */ |
| 140 | /* iPod Nano - 176x132, 9 cells @ 12x12 with 14 border lines */ |
| 141 | |
| 142 | /* Internal dimensions of a cell */ |
| 143 | #define CELL_WIDTH 12 |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 144 | #define CELL_HEIGHT 12 |
| 145 | |
Barry Wardell | 41ee9e3 | 2007-01-15 20:40:48 +0000 | [diff] [blame] | 146 | #elif ((LCD_HEIGHT==176) && (LCD_WIDTH==220)) |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 147 | /* Iriver h300, iPod Color/Photo - 220x176, 9 cells @ 16x16 with 14 border lines */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 148 | |
| 149 | /* Internal dimensions of a cell */ |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 150 | #define CELL_WIDTH 16 |
Dave Chapman | f1c0247 | 2005-11-27 23:59:05 +0000 | [diff] [blame] | 151 | #define CELL_HEIGHT 16 |
| 152 | |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 153 | #elif (LCD_HEIGHT>=240) && (LCD_WIDTH>=320) |
Jens Arnold | d158da2 | 2006-08-10 11:14:26 +0000 | [diff] [blame] | 154 | /* iPod Video - 320x240, 9 cells @ 24x24 with 14 border lines */ |
Dave Chapman | f1c0247 | 2005-11-27 23:59:05 +0000 | [diff] [blame] | 155 | |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 156 | /* Internal dimensions of a cell */ |
Jens Arnold | d158da2 | 2006-08-10 11:14:26 +0000 | [diff] [blame] | 157 | #define CELL_WIDTH 24 |
| 158 | #define CELL_HEIGHT 24 |
Dave Chapman | f1c0247 | 2005-11-27 23:59:05 +0000 | [diff] [blame] | 159 | |
Dave Chapman | f1c0247 | 2005-11-27 23:59:05 +0000 | [diff] [blame] | 160 | #else |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 161 | #error SUDOKU: Unsupported LCD size |
| 162 | #endif |
| 163 | |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 164 | #else /* Vertical layout, scratchpad at the bottom */ |
| 165 | #define VERTICAL_LAYOUT |
| 166 | |
Barry Wardell | 41ee9e3 | 2007-01-15 20:40:48 +0000 | [diff] [blame] | 167 | #if ((LCD_HEIGHT==220) && (LCD_WIDTH==176)) |
| 168 | /* e200, 9 cells @ 16x16 with 14 border lines */ |
| 169 | |
| 170 | /* Internal dimensions of a cell */ |
| 171 | #define CELL_WIDTH 16 |
| 172 | #define CELL_HEIGHT 16 |
| 173 | |
| 174 | #elif (LCD_HEIGHT>=320) && (LCD_WIDTH>=240) |
Jens Arnold | d158da2 | 2006-08-10 11:14:26 +0000 | [diff] [blame] | 175 | /* Gigabeat - 240x320, 9 cells @ 24x24 with 14 border lines */ |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 176 | |
| 177 | /* Internal dimensions of a cell */ |
Jens Arnold | d158da2 | 2006-08-10 11:14:26 +0000 | [diff] [blame] | 178 | #define CELL_WIDTH 24 |
| 179 | #define CELL_HEIGHT 24 |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 180 | |
| 181 | #else |
| 182 | #error SUDOKU: Unsupported LCD size |
| 183 | #endif |
| 184 | |
| 185 | #endif /* Layout */ |
| 186 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 187 | #define CFGFILE_VERSION 0 /* Current config file version */ |
| 188 | #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */ |
| 189 | |
| 190 | #ifdef HAVE_LCD_COLOR |
| 191 | /* settings */ |
| 192 | struct sudoku_config { |
| 193 | int number_display; |
| 194 | }; |
| 195 | struct sudoku_config sudcfg_disk = { 0 }; |
| 196 | struct sudoku_config sudcfg; |
| 197 | |
| 198 | static const char cfg_filename[] = "sudoku.cfg"; |
| 199 | static char *number_str[2] = { "black", "coloured" }; |
| 200 | |
| 201 | struct configdata disk_config[] = { |
| 202 | { TYPE_ENUM, 0, 2, &sudcfg_disk.number_display, "numbers", number_str, NULL }, |
| 203 | }; |
| 204 | #define NUMBER_TYPE (sudcfg.number_display*CELL_WIDTH) |
| 205 | #else |
| 206 | #define NUMBER_TYPE 0 |
| 207 | #endif |
| 208 | |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 209 | /* Size dependent build-time calculations */ |
| 210 | #ifdef SMALL_BOARD |
| 211 | #define BOARD_WIDTH (CELL_WIDTH*9+10) |
| 212 | #define BOARD_HEIGHT (CELL_HEIGHT*9+10) |
| 213 | static unsigned char cellxpos[9]={ |
| 214 | 1, (CELL_WIDTH+2), (2*CELL_WIDTH+3), |
| 215 | (3*CELL_WIDTH+4), (4*CELL_WIDTH+5), (5*CELL_WIDTH+6), |
| 216 | (6*CELL_WIDTH+7), (7*CELL_WIDTH+8), (8*CELL_WIDTH+9) |
| 217 | }; |
| 218 | static unsigned char cellypos[9]={ |
| 219 | 1, (CELL_HEIGHT+2), (2*CELL_HEIGHT+3), |
| 220 | (3*CELL_HEIGHT+4), (4*CELL_HEIGHT+5), (5*CELL_HEIGHT+6), |
| 221 | (6*CELL_HEIGHT+7), (7*CELL_HEIGHT+8), (8*CELL_HEIGHT+9) |
| 222 | }; |
| 223 | #else /* !SMALL_BOARD */ |
| 224 | #define BOARD_WIDTH (CELL_WIDTH*9+10+4) |
| 225 | #define BOARD_HEIGHT (CELL_HEIGHT*9+10+4) |
| 226 | static unsigned char cellxpos[9]={ |
| 227 | 2, (CELL_WIDTH +3), (2*CELL_WIDTH +4), |
| 228 | (3*CELL_WIDTH +6), (4*CELL_WIDTH +7), (5*CELL_WIDTH +8), |
| 229 | (6*CELL_WIDTH+10), (7*CELL_WIDTH+11), (8*CELL_WIDTH+12) |
| 230 | }; |
| 231 | static unsigned char cellypos[9]={ |
| 232 | 2, (CELL_HEIGHT +3), (2*CELL_HEIGHT +4), |
| 233 | (3*CELL_HEIGHT +6), (4*CELL_HEIGHT +7), (5*CELL_HEIGHT +8), |
| 234 | (6*CELL_HEIGHT+10), (7*CELL_HEIGHT+11), (8*CELL_HEIGHT+12) |
| 235 | }; |
| 236 | #endif |
| 237 | |
| 238 | #ifdef VERTICAL_LAYOUT |
| 239 | #define XOFS ((LCD_WIDTH-BOARD_WIDTH)/2) |
| 240 | #define YOFS ((LCD_HEIGHT-(BOARD_HEIGHT+CELL_HEIGHT*2+2))/2) |
| 241 | #define YOFSSCRATCHPAD (YOFS+BOARD_HEIGHT+CELL_WIDTH) |
| 242 | #else |
| 243 | #define XOFSSCRATCHPAD ((LCD_WIDTH-(BOARD_WIDTH+CELL_WIDTH*2+2))/2) |
| 244 | #define XOFS (XOFSSCRATCHPAD+CELL_WIDTH*2+2) |
| 245 | #define YOFS ((LCD_HEIGHT-BOARD_HEIGHT)/2) |
| 246 | #endif |
| 247 | |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 248 | /****** Solver routine by Tom Shackell <shackell@cs.york.ac.uk> |
| 249 | |
| 250 | Downloaded from: |
| 251 | |
| 252 | http://www-users.cs.york.ac.uk/~shackell/sudoku/Sudoku.html |
| 253 | |
| 254 | Released under GPLv2 |
| 255 | |
| 256 | */ |
| 257 | |
| 258 | typedef unsigned int Bitset; |
| 259 | |
| 260 | #define BLOCK 3 |
| 261 | #define SIZE (BLOCK*BLOCK) |
| 262 | |
| 263 | #define true 1 |
| 264 | #define false 0 |
| 265 | |
| 266 | typedef struct _Sudoku { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 267 | Bitset table[SIZE][SIZE]; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 268 | }Sudoku; |
| 269 | |
| 270 | typedef struct _Stats { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 271 | int numTries; |
| 272 | int backTracks; |
| 273 | int numEmpty; |
| 274 | bool solutionFound; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 275 | }Stats; |
| 276 | |
| 277 | typedef struct _Options { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 278 | bool allSolutions; |
| 279 | bool uniquenessCheck; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 280 | }Options; |
| 281 | |
| 282 | void sudoku_init(Sudoku* sud); |
| 283 | void sudoku_set(Sudoku* sud, int x, int y, int num, bool original); |
| 284 | int sudoku_get(Sudoku* sud, int x, int y, bool* original); |
| 285 | |
| 286 | #define BIT(n) ((Bitset)(1<<(n))) |
| 287 | #define BIT_TEST(v,n) ((((Bitset)v) & BIT(n)) != 0) |
| 288 | #define BIT_CLEAR(v,n) (v) &= ~BIT(n) |
| 289 | #define MARK_BIT BIT(0) |
| 290 | #define ORIGINAL_BIT BIT(SIZE+1) |
| 291 | |
| 292 | #define ALL_BITS (BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9)) |
| 293 | |
| 294 | /* initialize a sudoku problem, should be called before using set or get */ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 295 | void sudoku_init(Sudoku* sud) |
| 296 | { |
| 297 | int y, x; |
| 298 | for (y = 0; y < SIZE; y++){ |
| 299 | for (x = 0; x < SIZE; x++){ |
| 300 | sud->table[x][y] = ALL_BITS; |
| 301 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 302 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 303 | } |
| 304 | |
| 305 | /* set the number at a particular x and y column */ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 306 | void sudoku_set(Sudoku* sud, int x, int y, int num, bool original) |
| 307 | { |
| 308 | int i, j; |
| 309 | int bx, by; |
| 310 | Bitset orig; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 311 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 312 | /* clear the row and columns */ |
| 313 | for (i = 0; i < SIZE; i++){ |
| 314 | BIT_CLEAR(sud->table[i][y], num); |
| 315 | BIT_CLEAR(sud->table[x][i], num); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 316 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 317 | /* clear the block */ |
| 318 | bx = x - (x % BLOCK); |
| 319 | by = y - (y % BLOCK); |
| 320 | for (i = 0; i < BLOCK; i++){ |
| 321 | for (j = 0; j < BLOCK; j++){ |
| 322 | BIT_CLEAR(sud->table[bx+j][by+i], num); |
| 323 | } |
| 324 | } |
| 325 | /* mark the table */ |
| 326 | orig = original ? ORIGINAL_BIT : 0; |
| 327 | sud->table[x][y] = BIT(num) | MARK_BIT | orig; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 328 | } |
| 329 | |
| 330 | /* get the number at a particular x and y column, if this |
| 331 | is not unique return 0 */ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 332 | int sudoku_get(Sudoku* sud, int x, int y, bool* original) |
| 333 | { |
| 334 | Bitset val = sud->table[x][y]; |
| 335 | int result = 0; |
| 336 | int i; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 337 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 338 | if (original) { |
| 339 | *original = val & ORIGINAL_BIT; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 340 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 341 | for (i = 1; i <= SIZE; i++){ |
| 342 | if (BIT_TEST(val, i)){ |
| 343 | if (result != 0){ |
| 344 | return 0; |
| 345 | } |
| 346 | result = i; |
| 347 | } |
| 348 | } |
| 349 | return result; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 350 | } |
| 351 | |
| 352 | /* returns true if this is a valid problem, this is necessary because the input |
| 353 | problem might be degenerate which breaks the solver algorithm. */ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 354 | static bool is_valid(const Sudoku* sud) |
| 355 | { |
| 356 | int x, y; |
| 357 | |
| 358 | for (y = 0; y < SIZE; y++){ |
| 359 | for (x = 0; x < SIZE; x++){ |
| 360 | if ((sud->table[x][y] & ALL_BITS) == 0){ |
| 361 | return false; |
| 362 | } |
| 363 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 364 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 365 | return true; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 366 | } |
| 367 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 368 | /* scan the table for the most constrained item, giving all it's options, sets |
| 369 | the best x and y coordinates, the number of options and the options for |
| 370 | that coordinate and returns true if the puzzle is finished */ |
| 371 | static bool scan(const Sudoku* sud, int* rX, int* rY, int *num, int* options) |
| 372 | { |
| 373 | int x, y, i, j; |
| 374 | int bestCount = SIZE+1; |
| 375 | Bitset val; |
| 376 | bool allMarked = true; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 377 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 378 | for (y = 0; y < SIZE; y++){ |
| 379 | for (x = 0; x < SIZE; x++){ |
| 380 | Bitset val = sud->table[x][y]; |
| 381 | int i; |
| 382 | int count = 0; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 383 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 384 | if (val & MARK_BIT) { |
| 385 | /* already set */ |
| 386 | continue; |
| 387 | } |
| 388 | allMarked = false; |
| 389 | for (i = 1; i <= SIZE; i++){ |
| 390 | if (BIT_TEST(val, i)){ |
| 391 | count++; |
| 392 | } |
| 393 | } |
| 394 | if (count < bestCount){ |
| 395 | bestCount = count; |
| 396 | *rX = x; |
| 397 | *rY = y; |
| 398 | if (count == 0){ |
| 399 | /* can't possibly be beaten */ |
| 400 | *num = 0; |
| 401 | return false; |
| 402 | } |
| 403 | } |
| 404 | } |
| 405 | } |
| 406 | /* now copy into options */ |
| 407 | *num = bestCount; |
| 408 | val = sud->table[*rX][*rY]; |
| 409 | for (i = 1, j = 0; i <= SIZE; i++){ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 410 | if (BIT_TEST(val, i)){ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 411 | options[j++] = i; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 412 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 413 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 414 | return allMarked; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 415 | } |
| 416 | |
| 417 | static bool solve(Sudoku* sud, Stats* stats, const Options* options); |
| 418 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 419 | /* try a particular option and return true if that gives a solution or false |
| 420 | if it doesn't, restores board on backtracking */ |
| 421 | static bool spawn_option(Sudoku* sud, Stats* stats, const Options* options, |
| 422 | int x, int y, int num) |
| 423 | { |
| 424 | Sudoku copy; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 425 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 426 | rb->memcpy(©,sud,sizeof(Sudoku)); |
| 427 | sudoku_set(©, x, y, num, false); |
| 428 | stats->numTries += 1; |
| 429 | if (solve(©, stats, options)){ |
| 430 | if (!options->allSolutions && stats->solutionFound){ |
| 431 | rb->memcpy(sud,©,sizeof(Sudoku)); |
| 432 | } |
| 433 | return true; |
| 434 | }else{ |
| 435 | stats->backTracks++; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 436 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 437 | return false; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 438 | } |
| 439 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 440 | /* solve a sudoku problem, returns true if there is a solution and false |
| 441 | otherwise. stats is used to track statisticss */ |
| 442 | static bool solve(Sudoku* sud, Stats* stats, const Options* options) |
| 443 | { |
| 444 | while (true){ |
Jens Arnold | f376eb5 | 2006-04-30 12:24:55 +0000 | [diff] [blame] | 445 | int x = 0; |
| 446 | int y = 0; |
| 447 | int i, num; |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 448 | int places[SIZE]; |
| 449 | |
| 450 | if (scan(sud, &x, &y, &num, places)){ |
| 451 | /* a solution was found! */ |
| 452 | if (options->uniquenessCheck && stats->solutionFound){ |
| 453 | /*printf("\n\t... But the solution is not unique!\n"); */ |
| 454 | return true; |
| 455 | } |
| 456 | stats->solutionFound = true; |
| 457 | if (options->allSolutions || options->uniquenessCheck){ |
| 458 | /*printf("\n\tSolution after %d iterations\n", stats->numTries); */ |
| 459 | /*sudoku_print(sud); */ |
| 460 | return false; |
| 461 | } |
| 462 | else{ |
| 463 | return true; |
| 464 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 465 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 466 | if (num == 0){ |
| 467 | /* can't be satisfied */ |
| 468 | return false; |
| 469 | } |
| 470 | /* try all the places (except the last one) */ |
| 471 | for (i = 0; i < num-1; i++){ |
| 472 | if (spawn_option(sud, stats, options, x, y, places[i])){ |
| 473 | /* solution found! */ |
| 474 | if (!options->allSolutions && stats->solutionFound){ |
| 475 | return true; |
| 476 | } |
| 477 | } |
| 478 | } |
| 479 | /* take the last place ourself */ |
| 480 | stats->numTries += 1; |
| 481 | sudoku_set(sud, x, y, places[num-1], false); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 482 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 483 | } |
| 484 | |
| 485 | /******** END OF IMPORTED CODE */ |
| 486 | |
| 487 | |
| 488 | /* A wrapper function between the Sudoku plugin and the above solver code */ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 489 | void sudoku_solve(struct sudoku_state_t* state) |
| 490 | { |
| 491 | bool ret; |
| 492 | Stats stats; |
| 493 | Options options; |
| 494 | Sudoku sud; |
| 495 | bool original; |
| 496 | int r,c; |
| 497 | |
| 498 | /* Initialise the parameters */ |
| 499 | sudoku_init(&sud); |
| 500 | rb->memset(&stats,0,sizeof(stats)); |
| 501 | options.allSolutions=false; |
| 502 | options.uniquenessCheck=false; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 503 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 504 | /* Convert Rockbox format into format for solver */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 505 | for (r=0;r<9;r++) { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 506 | for (c=0;c<9;c++) { |
| 507 | if (state->startboard[r][c]!='0') { |
| 508 | sudoku_set(&sud, c, r, state->startboard[r][c]-'0', true); |
| 509 | } |
| 510 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 511 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 512 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 513 | /* need to check for degenerate input problems ... */ |
| 514 | if (is_valid(&sud)){ |
| 515 | ret = solve(&sud, &stats, &options); |
| 516 | } else { |
| 517 | ret = false; |
| 518 | } |
| 519 | |
| 520 | if (ret) { |
| 521 | /* Populate the board with the solution. */ |
| 522 | for (r=0;r<9;r++) { |
| 523 | for (c=0;c<9;c++) { |
| 524 | state->currentboard[r][c]='0'+ |
| 525 | sudoku_get(&sud, c, r, &original); |
| 526 | } |
| 527 | } |
| 528 | } else { |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 529 | rb->splash(HZ*2, "Solve failed"); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 530 | } |
| 531 | |
| 532 | return; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 533 | } |
| 534 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 535 | void default_state(struct sudoku_state_t* state) |
| 536 | { |
| 537 | int r,c; |
| 538 | |
| 539 | rb->strncpy(state->filename,GAME_FILE,MAX_PATH); |
| 540 | for (r=0;r<9;r++) { |
| 541 | for (c=0;c<9;c++) { |
| 542 | state->startboard[r][c]=default_game[r][c]; |
| 543 | state->currentboard[r][c]=default_game[r][c]; |
| 544 | #ifdef SUDOKU_BUTTON_POSSIBLE |
| 545 | state->possiblevals[r][c]=0; |
| 546 | #endif |
| 547 | } |
| 548 | } |
| 549 | |
| 550 | state->x=0; |
| 551 | state->y=0; |
| 552 | state->editmode=0; |
| 553 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 554 | |
| 555 | void clear_state(struct sudoku_state_t* state) |
| 556 | { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 557 | int r,c; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 558 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 559 | rb->strncpy(state->filename,GAME_FILE,MAX_PATH); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 560 | for (r=0;r<9;r++) { |
| 561 | for (c=0;c<9;c++) { |
| 562 | state->startboard[r][c]='0'; |
| 563 | state->currentboard[r][c]='0'; |
Dave Chapman | 61eac11 | 2005-11-29 00:02:00 +0000 | [diff] [blame] | 564 | #ifdef SUDOKU_BUTTON_POSSIBLE |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 565 | state->possiblevals[r][c]=0; |
Dave Chapman | 61eac11 | 2005-11-29 00:02:00 +0000 | [diff] [blame] | 566 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 567 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 568 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 569 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 570 | state->x=0; |
| 571 | state->y=0; |
| 572 | state->editmode=0; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 573 | } |
| 574 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 575 | /* Check the status of the board, assuming a change at the cursor location */ |
| 576 | bool check_status(struct sudoku_state_t* state) |
| 577 | { |
| 578 | int check[9]; |
| 579 | int r,c; |
| 580 | int r1,c1; |
| 581 | int cell; |
| 582 | |
| 583 | /* First, check the column */ |
| 584 | for (cell=0;cell<9;cell++) { |
| 585 | check[cell]=0; |
| 586 | } |
| 587 | for (r=0;r<9;r++) { |
| 588 | cell=state->currentboard[r][state->x]; |
| 589 | if (cell!='0') { |
| 590 | if (check[cell-'1']==1) { |
| 591 | return true; |
| 592 | } |
| 593 | check[cell-'1']=1; |
| 594 | } |
| 595 | } |
| 596 | |
| 597 | /* Second, check the row */ |
| 598 | for (cell=0;cell<9;cell++) { |
| 599 | check[cell]=0; |
| 600 | } |
| 601 | for (c=0;c<9;c++) { |
| 602 | cell=state->currentboard[state->y][c]; |
| 603 | if (cell!='0') { |
| 604 | if (check[cell-'1']==1) { |
| 605 | return true; |
| 606 | } |
| 607 | check[cell-'1']=1; |
| 608 | } |
| 609 | } |
| 610 | |
| 611 | /* Finally, check the 3x3 sub-grid */ |
| 612 | for (cell=0;cell<9;cell++) { |
| 613 | check[cell]=0; |
| 614 | } |
| 615 | r1=(state->y/3)*3; |
| 616 | c1=(state->x/3)*3; |
| 617 | for (r=r1;r<r1+3;r++) { |
| 618 | for (c=c1;c<c1+3;c++) { |
| 619 | cell=state->currentboard[r][c]; |
| 620 | if (cell!='0') { |
| 621 | if (check[cell-'1']==1) { |
| 622 | return true; |
| 623 | } |
| 624 | check[cell-'1']=1; |
| 625 | } |
| 626 | } |
| 627 | } |
| 628 | |
| 629 | /* We passed all the checks :) */ |
| 630 | |
| 631 | return false; |
| 632 | } |
| 633 | |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 634 | /* Load game - only ".ss" is officially supported, but any sensible |
| 635 | text representation (one line per row) may load. |
| 636 | */ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 637 | bool load_sudoku(struct sudoku_state_t* state, char* filename) |
| 638 | { |
| 639 | int fd; |
| 640 | size_t n; |
| 641 | int r = 0, c = 0; |
| 642 | unsigned int i; |
| 643 | int valid=0; |
| 644 | char buf[300]; /* A buffer to read a sudoku board from */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 645 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 646 | fd=rb->open(filename, O_RDONLY); |
| 647 | if (fd < 0) { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 648 | LOGF("Invalid sudoku file: %s\n",filename); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 649 | return(false); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 650 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 651 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 652 | rb->strncpy(state->filename,filename,MAX_PATH); |
| 653 | n=rb->read(fd,buf,300); |
| 654 | if (n <= 0) { |
| 655 | return(false); |
| 656 | } |
| 657 | rb->close(fd); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 658 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 659 | r=0; |
| 660 | c=0; |
| 661 | i=0; |
| 662 | while ((i < n) && (r < 9)) { |
| 663 | switch (buf[i]){ |
| 664 | case ' ': case '\t': |
| 665 | if (c > 0) |
| 666 | valid=1; |
| 667 | break; |
| 668 | case '|': |
| 669 | case '*': |
| 670 | case '-': |
| 671 | case '\r': |
| 672 | break; |
| 673 | case '\n': |
| 674 | if (valid) { |
| 675 | r++; |
| 676 | valid=0; |
| 677 | } |
| 678 | c = 0; |
| 679 | break; |
| 680 | case '_': case '.': |
| 681 | valid=1; |
| 682 | if (c >= SIZE || r >= SIZE){ |
| 683 | LOGF("ERROR: sudoku problem is the wrong size (%d,%d)\n", |
| 684 | c, r); |
| 685 | return(false); |
| 686 | } |
| 687 | c++; |
| 688 | break; |
| 689 | default: |
| 690 | if (((buf[i]>='A') && (buf[i]<='I')) || |
| 691 | ((buf[i]>='0') && (buf[i]<='9'))) { |
| 692 | valid=1; |
| 693 | if (r >= SIZE || c >= SIZE){ |
| 694 | LOGF("ERROR: sudoku problem is the wrong size " |
| 695 | "(%d,%d)\n", c, r); |
| 696 | return(false); |
| 697 | } |
| 698 | if ((buf[i]>='0') && (buf[i]<='9')) { |
| 699 | state->startboard[r][c]=buf[i]; |
| 700 | state->currentboard[r][c]=buf[i]; |
| 701 | } else { |
| 702 | state->currentboard[r][c]='1'+(buf[i]-'A'); |
| 703 | } |
| 704 | c++; |
| 705 | } |
| 706 | /* Ignore any other characters */ |
| 707 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 708 | } |
| 709 | i++; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 710 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 711 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 712 | /* Check that the board is valid - we need to check every row/column |
| 713 | individually, so we check the diagonal from top-left to bottom-right */ |
| 714 | for (state->x = 0; state->x < 9; state->x++) { |
| 715 | state->y = state->x; |
| 716 | if (check_status(state)) return false; |
| 717 | } |
| 718 | state->x = 0; |
| 719 | state->y = 0; |
| 720 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 721 | /* Save a copy of the saved state - so we can reload without using the |
| 722 | disk */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 723 | rb->memcpy(state->savedboard,state->currentboard,81); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 724 | return(true); |
| 725 | } |
| 726 | |
| 727 | bool save_sudoku(struct sudoku_state_t* state) |
| 728 | { |
| 729 | int fd; |
| 730 | int r,c; |
| 731 | int i; |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 732 | char line[13]; |
| 733 | char sep[13]; |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 734 | |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 735 | rb->splash(0, "Saving..."); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 736 | rb->memcpy(line,"...|...|...\r\n",13); |
| 737 | rb->memcpy(sep,"-----------\r\n",13); |
| 738 | |
| 739 | if (state->filename[0]==0) { |
| 740 | return false; |
| 741 | } |
| 742 | |
| 743 | fd=rb->open(state->filename, O_WRONLY|O_CREAT); |
| 744 | if (fd >= 0) { |
| 745 | for (r=0;r<9;r++) { |
| 746 | i=0; |
| 747 | for (c=0;c<9;c++) { |
| 748 | if (state->startboard[r][c]!='0') { |
| 749 | line[i]=state->startboard[r][c]; |
| 750 | } else if (state->currentboard[r][c]!='0') { |
| 751 | line[i]='A'+(state->currentboard[r][c]-'1'); |
| 752 | } else { |
| 753 | line[i]='.'; |
| 754 | } |
| 755 | i++; |
| 756 | if ((c==2) || (c==5)) { |
| 757 | i++; |
| 758 | } |
| 759 | } |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 760 | rb->write(fd,line,sizeof(line)); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 761 | if ((r==2) || (r==5)) { |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 762 | rb->write(fd,sep,sizeof(sep)); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 763 | } |
| 764 | } |
| 765 | /* Add a blank line at end */ |
| 766 | rb->write(fd,"\r\n",2); |
| 767 | rb->close(fd); |
Hardeep Sidhu | ab3e71c | 2006-06-04 16:36:49 +0000 | [diff] [blame] | 768 | rb->reload_directory(); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 769 | /* Save a copy of the saved state - so we can reload without |
| 770 | using the disk */ |
| 771 | rb->memcpy(state->savedboard,state->currentboard,81); |
| 772 | return true; |
| 773 | } else { |
| 774 | return false; |
| 775 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 776 | } |
| 777 | |
| 778 | void restore_state(struct sudoku_state_t* state) |
| 779 | { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 780 | rb->memcpy(state->currentboard,state->savedboard,81); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 781 | } |
| 782 | |
| 783 | void clear_board(struct sudoku_state_t* state) |
| 784 | { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 785 | int r,c; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 786 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 787 | for (r=0;r<9;r++) { |
| 788 | for (c=0;c<9;c++) { |
| 789 | state->currentboard[r][c]=state->startboard[r][c]; |
| 790 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 791 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 792 | state->x=0; |
| 793 | state->y=0; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 794 | } |
| 795 | |
| 796 | void update_cell(struct sudoku_state_t* state, int r, int c) |
| 797 | { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 798 | /* We have four types of cell: |
| 799 | 1) User-entered number |
| 800 | 2) Starting number |
| 801 | 3) Cursor in cell |
| 802 | */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 803 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 804 | if ((r==state->y) && (c==state->x)) { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 805 | rb->lcd_bitmap_part(sudoku_inverse,NUMBER_TYPE, |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 806 | BITMAP_HEIGHT*(state->currentboard[r][c]-'0'), |
| 807 | BITMAP_STRIDE, |
| 808 | XOFS+cellxpos[c],YOFS+cellypos[r],CELL_WIDTH, |
| 809 | CELL_HEIGHT); |
| 810 | } else { |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 811 | if (state->startboard[r][c]!='0') { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 812 | rb->lcd_bitmap_part(sudoku_start,NUMBER_TYPE, |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 813 | BITMAP_HEIGHT*(state->startboard[r][c]-'0'), |
| 814 | BITMAP_STRIDE, |
| 815 | XOFS+cellxpos[c],YOFS+cellypos[r], |
| 816 | CELL_WIDTH,CELL_HEIGHT); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 817 | } else { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 818 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE, |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 819 | BITMAP_HEIGHT*(state->currentboard[r][c]-'0'), |
| 820 | BITMAP_STRIDE, |
| 821 | XOFS+cellxpos[c],YOFS+cellypos[r], |
| 822 | CELL_WIDTH,CELL_HEIGHT); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 823 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 824 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 825 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 826 | rb->lcd_update_rect(cellxpos[c],cellypos[r],CELL_WIDTH,CELL_HEIGHT); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 827 | } |
| 828 | |
| 829 | |
| 830 | void display_board(struct sudoku_state_t* state) |
| 831 | { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 832 | int r,c; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 833 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 834 | /* Clear the display buffer */ |
| 835 | rb->lcd_clear_display(); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 836 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 837 | /* Draw the gridlines - differently for different targets */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 838 | |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 839 | #ifdef SMALL_BOARD |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 840 | /* Small targets - draw dotted/single lines */ |
| 841 | for (r=0;r<9;r++) { |
| 842 | if ((r % 3)==0) { |
| 843 | /* Solid Line */ |
| 844 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[r]-1); |
| 845 | rb->lcd_vline(XOFS+cellxpos[r]-1,YOFS,YOFS+BOARD_HEIGHT-1); |
| 846 | } else { |
| 847 | /* Dotted line */ |
| 848 | for (c=XOFS;c<XOFS+BOARD_WIDTH;c+=2) { |
| 849 | rb->lcd_drawpixel(c,YOFS+cellypos[r]-1); |
| 850 | } |
| 851 | for (c=YOFS;c<YOFS+BOARD_HEIGHT;c+=2) { |
| 852 | rb->lcd_drawpixel(XOFS+cellxpos[r]-1,c); |
| 853 | } |
| 854 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 855 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 856 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[8]+CELL_HEIGHT); |
| 857 | rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH,YOFS,YOFS+BOARD_HEIGHT-1); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 858 | #else |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 859 | /* Large targets - draw single/double lines */ |
| 860 | for (r=0;r<9;r++) { |
| 861 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[r]-1); |
| 862 | rb->lcd_vline(XOFS+cellxpos[r]-1,YOFS,YOFS+BOARD_HEIGHT-1); |
| 863 | if ((r % 3)==0) { |
| 864 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[r]-2); |
| 865 | rb->lcd_vline(XOFS+cellxpos[r]-2,YOFS,YOFS+BOARD_HEIGHT-1); |
| 866 | } |
| 867 | } |
| 868 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[8]+CELL_HEIGHT); |
| 869 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[8]+CELL_HEIGHT+1); |
| 870 | rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH,YOFS,YOFS+BOARD_HEIGHT-1); |
| 871 | rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH+1,YOFS,YOFS+BOARD_HEIGHT-1); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 872 | #endif |
| 873 | |
Dave Chapman | 61eac11 | 2005-11-29 00:02:00 +0000 | [diff] [blame] | 874 | #ifdef SUDOKU_BUTTON_POSSIBLE |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 875 | #ifdef VERTICAL_LAYOUT |
| 876 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFSSCRATCHPAD); |
| 877 | rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFSSCRATCHPAD+CELL_HEIGHT+1); |
| 878 | for (r=0;r<9;r++) { |
| 879 | #ifdef SMALL_BOARD |
| 880 | /* Small targets - draw dotted/single lines */ |
| 881 | if ((r % 3)==0) { |
| 882 | /* Solid Line */ |
| 883 | rb->lcd_vline(XOFS+cellxpos[r]-1,YOFSSCRATCHPAD, |
| 884 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
| 885 | } else { |
| 886 | /* Dotted line */ |
| 887 | for (c=YOFSSCRATCHPAD;c<YOFSSCRATCHPAD+CELL_HEIGHT+1;c+=2) { |
| 888 | rb->lcd_drawpixel(XOFS+cellxpos[r]-1,c); |
| 889 | } |
| 890 | } |
| 891 | #else |
| 892 | /* Large targets - draw single/double lines */ |
| 893 | rb->lcd_vline(XOFS+cellxpos[r]-1,YOFSSCRATCHPAD, |
| 894 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
| 895 | if ((r % 3)==0) |
| 896 | rb->lcd_vline(XOFS+cellxpos[r]-2,YOFSSCRATCHPAD, |
| 897 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
| 898 | #endif |
| 899 | if ((r>0) && state->possiblevals[state->y][state->x]&(1<<(r))) |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 900 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
| 901 | BITMAP_STRIDE,XOFS+cellxpos[r-1], |
| 902 | YOFSSCRATCHPAD+1,CELL_WIDTH,CELL_HEIGHT); |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 903 | } |
| 904 | rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH,YOFSSCRATCHPAD, |
| 905 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
| 906 | #ifndef SMALL_BOARD |
| 907 | rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH+1,YOFSSCRATCHPAD, |
| 908 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
| 909 | #endif |
| 910 | if (state->possiblevals[state->y][state->x]&(1<<(r))) |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 911 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
| 912 | BITMAP_STRIDE,XOFS+cellxpos[8],YOFSSCRATCHPAD+1, |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 913 | CELL_WIDTH,CELL_HEIGHT); |
| 914 | #else /* Horizontal layout */ |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 915 | rb->lcd_vline(XOFSSCRATCHPAD,YOFS,YOFS+BOARD_HEIGHT-1); |
| 916 | rb->lcd_vline(XOFSSCRATCHPAD+CELL_WIDTH+1,YOFS,YOFS+BOARD_HEIGHT-1); |
| 917 | for (r=0;r<9;r++) { |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 918 | #ifdef SMALL_BOARD |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 919 | /* Small targets - draw dotted/single lines */ |
| 920 | if ((r % 3)==0) { |
| 921 | /* Solid Line */ |
| 922 | rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1, |
| 923 | YOFS+cellypos[r]-1); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 924 | } else { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 925 | /* Dotted line */ |
| 926 | for (c=XOFSSCRATCHPAD;c<XOFSSCRATCHPAD+CELL_WIDTH+1;c+=2) { |
| 927 | rb->lcd_drawpixel(c,YOFS+cellypos[r]-1); |
| 928 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 929 | } |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 930 | #else |
| 931 | /* Large targets - draw single/double lines */ |
| 932 | rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1, |
| 933 | YOFS+cellypos[r]-1); |
| 934 | if ((r % 3)==0) |
| 935 | rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1, |
| 936 | YOFS+cellypos[r]-2); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 937 | #endif |
| 938 | if ((r>0) && state->possiblevals[state->y][state->x]&(1<<(r))) |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 939 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
| 940 | BITMAP_STRIDE,XOFSSCRATCHPAD+1, |
| 941 | YOFS+cellypos[r-1],CELL_WIDTH,CELL_HEIGHT); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 942 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 943 | rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1, |
| 944 | YOFS+cellypos[8]+CELL_HEIGHT); |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 945 | #ifndef SMALL_BOARD |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 946 | rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1, |
| 947 | YOFS+cellypos[8]+CELL_HEIGHT+1); |
| 948 | #endif |
| 949 | if (state->possiblevals[state->y][state->x]&(1<<(r))) |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 950 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
| 951 | BITMAP_STRIDE,XOFSSCRATCHPAD+1,YOFS+cellypos[8], |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 952 | CELL_WIDTH,CELL_HEIGHT); |
Jens Arnold | f742c35 | 2006-08-09 20:31:38 +0000 | [diff] [blame] | 953 | #endif /* Layout */ |
| 954 | #endif /* SUDOKU_BUTTON_POSSIBLE */ |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 955 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 956 | /* Draw the numbers */ |
| 957 | for (r=0;r<9;r++) { |
| 958 | for (c=0;c<9;c++) { |
| 959 | /* We have four types of cell: |
| 960 | 1) User-entered number |
| 961 | 2) Starting number |
| 962 | 3) Cursor in cell |
| 963 | */ |
| 964 | |
| 965 | if ((r==state->y) && (c==state->x)) { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 966 | rb->lcd_bitmap_part(sudoku_inverse,NUMBER_TYPE, |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 967 | BITMAP_HEIGHT*(state->currentboard[r][c]- |
| 968 | '0'), |
| 969 | BITMAP_STRIDE, |
| 970 | XOFS+cellxpos[c],YOFS+cellypos[r], |
| 971 | CELL_WIDTH,CELL_HEIGHT); |
| 972 | } else { |
| 973 | if (state->startboard[r][c]!='0') { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 974 | rb->lcd_bitmap_part(sudoku_start,NUMBER_TYPE, |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 975 | BITMAP_HEIGHT*(state->startboard[r][c]- |
| 976 | '0'), |
| 977 | BITMAP_STRIDE, |
| 978 | XOFS+cellxpos[c],YOFS+cellypos[r], |
| 979 | CELL_WIDTH,CELL_HEIGHT); |
| 980 | } else { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 981 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE, |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 982 | BITMAP_HEIGHT* |
| 983 | (state->currentboard[r][c]-'0'), |
| 984 | BITMAP_STRIDE, |
| 985 | XOFS+cellxpos[c],YOFS+cellypos[r], |
| 986 | CELL_WIDTH,CELL_HEIGHT); |
| 987 | } |
| 988 | } |
| 989 | } |
| 990 | } |
| 991 | |
| 992 | /* update the screen */ |
| 993 | rb->lcd_update(); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 994 | } |
| 995 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 996 | bool sudoku_generate(struct sudoku_state_t* state) |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 997 | { |
| 998 | char* difficulty; |
| 999 | char str[80]; |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1000 | bool res; |
| 1001 | struct sudoku_state_t new_state; |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1002 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1003 | clear_state(&new_state); |
| 1004 | display_board(&new_state); |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1005 | rb->splash(0, "Generating..."); |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1006 | |
Dave Chapman | 65293be | 2006-04-09 14:20:14 +0000 | [diff] [blame] | 1007 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
Christian Gmeiner | f03e053 | 2006-04-09 13:47:28 +0000 | [diff] [blame] | 1008 | rb->cpu_boost(true); |
| 1009 | #endif |
Dave Chapman | 65293be | 2006-04-09 14:20:14 +0000 | [diff] [blame] | 1010 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1011 | res = sudoku_generate_board(&new_state,&difficulty); |
Dave Chapman | 65293be | 2006-04-09 14:20:14 +0000 | [diff] [blame] | 1012 | |
| 1013 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
Christian Gmeiner | f03e053 | 2006-04-09 13:47:28 +0000 | [diff] [blame] | 1014 | rb->cpu_boost(false); |
| 1015 | #endif |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1016 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1017 | if (res) { |
| 1018 | rb->memcpy(state,&new_state,sizeof(new_state)); |
| 1019 | rb->snprintf(str,sizeof(str),"Difficulty: %s",difficulty); |
| 1020 | display_board(state); |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1021 | rb->splash(HZ*3, str); |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1022 | rb->strncpy(state->filename,GAME_FILE,MAX_PATH); |
| 1023 | } else { |
| 1024 | display_board(&new_state); |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1025 | rb->splash(HZ*2, "Aborted"); |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1026 | } |
| 1027 | return res; |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1028 | } |
| 1029 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1030 | #ifdef HAVE_LCD_COLOR |
| 1031 | static bool numdisplay_setting(void) |
| 1032 | { |
| 1033 | static const struct opt_items names[] = { |
| 1034 | {"Black", -1}, |
| 1035 | {"Coloured", -1}, |
| 1036 | }; |
| 1037 | |
| 1038 | return rb->set_option("Number Display", &sudcfg.number_display, INT, names, |
| 1039 | sizeof(names) / sizeof(names[0]), NULL); |
| 1040 | } |
| 1041 | #endif |
| 1042 | |
| 1043 | enum { |
| 1044 | SM_AUDIO_PLAYBACK = 0, |
| 1045 | #ifdef HAVE_LCD_COLOR |
| 1046 | SM_NUMBER_DISPLAY, |
| 1047 | #endif |
| 1048 | SM_SAVE, |
| 1049 | SM_RELOAD, |
| 1050 | SM_CLEAR, |
| 1051 | SM_SOLVE, |
| 1052 | SM_GENERATE, |
| 1053 | SM_NEW, |
| 1054 | SM_QUIT, |
| 1055 | }; |
| 1056 | |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1057 | bool sudoku_menu(struct sudoku_state_t* state) |
| 1058 | { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1059 | int m; |
| 1060 | int result; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1061 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1062 | static const struct menu_item items[] = { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1063 | [SM_AUDIO_PLAYBACK] = { "Audio Playback", NULL }, |
| 1064 | #ifdef HAVE_LCD_COLOR |
| 1065 | [SM_NUMBER_DISPLAY] = { "Number Display", NULL }, |
| 1066 | #endif |
| 1067 | [SM_SAVE] = { "Save", NULL }, |
| 1068 | [SM_RELOAD] = { "Reload", NULL }, |
| 1069 | [SM_CLEAR] = { "Clear", NULL }, |
| 1070 | [SM_SOLVE] = { "Solve", NULL }, |
| 1071 | [SM_GENERATE] = { "Generate", NULL }, |
| 1072 | [SM_NEW] = { "New", NULL }, |
| 1073 | [SM_QUIT] = { "Quit", NULL }, |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1074 | }; |
| 1075 | |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 1076 | m = menu_init(rb,items, sizeof(items) / sizeof(*items), |
Shachar Liberman | 0ed4904 | 2006-08-12 13:43:20 +0000 | [diff] [blame] | 1077 | NULL, NULL, NULL, NULL); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1078 | |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 1079 | result=menu_show(m); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1080 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1081 | switch (result) { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1082 | case SM_AUDIO_PLAYBACK: |
Jonathan Gordon | 33b785e | 2008-04-23 10:28:34 +0000 | [diff] [blame] | 1083 | playback_control(rb, NULL); |
Dave Chapman | bf99952 | 2006-04-01 23:23:07 +0000 | [diff] [blame] | 1084 | break; |
| 1085 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1086 | #ifdef HAVE_LCD_COLOR |
| 1087 | case SM_NUMBER_DISPLAY: |
| 1088 | numdisplay_setting(); |
| 1089 | break; |
| 1090 | #endif |
| 1091 | case SM_SAVE: |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1092 | save_sudoku(state); |
| 1093 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1094 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1095 | case SM_RELOAD: |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1096 | restore_state(state); |
| 1097 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1098 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1099 | case SM_CLEAR: |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1100 | clear_board(state); |
| 1101 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1102 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1103 | case SM_SOLVE: |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1104 | sudoku_solve(state); |
| 1105 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1106 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1107 | case SM_GENERATE: |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1108 | sudoku_generate(state); |
| 1109 | break; |
| 1110 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1111 | case SM_NEW: |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1112 | clear_state(state); |
| 1113 | state->editmode=1; |
| 1114 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1115 | |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1116 | case SM_QUIT: |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1117 | save_sudoku(state); |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 1118 | menu_exit(m); |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1119 | return true; |
| 1120 | break; |
| 1121 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1122 | default: |
| 1123 | break; |
| 1124 | } |
Dave Chapman | 33e935c | 2005-10-04 23:36:03 +0000 | [diff] [blame] | 1125 | |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 1126 | menu_exit(m); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1127 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1128 | return (result==MENU_ATTACHED_USB); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1129 | } |
| 1130 | |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1131 | /* Menu used when user is in edit mode - i.e. creating a new game manually */ |
| 1132 | int sudoku_edit_menu(struct sudoku_state_t* state) |
| 1133 | { |
| 1134 | int m; |
| 1135 | int result; |
| 1136 | |
| 1137 | static const struct menu_item items[] = { |
| 1138 | { "Save as", NULL }, |
| 1139 | { "Quit", NULL }, |
| 1140 | }; |
| 1141 | |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 1142 | m = menu_init(rb,items, sizeof(items) / sizeof(*items), |
Shachar Liberman | 0ed4904 | 2006-08-12 13:43:20 +0000 | [diff] [blame] | 1143 | NULL, NULL, NULL, NULL); |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1144 | |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 1145 | result=menu_show(m); |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1146 | |
| 1147 | switch (result) { |
| 1148 | case 0: /* Save new game */ |
| 1149 | rb->kbd_input(state->filename,MAX_PATH); |
| 1150 | if (save_sudoku(state)) { |
| 1151 | state->editmode=0; |
| 1152 | } else { |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1153 | rb->splash(HZ*2, "Save failed"); |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1154 | } |
| 1155 | break; |
| 1156 | |
| 1157 | case 1: /* Quit */ |
| 1158 | break; |
| 1159 | |
| 1160 | default: |
| 1161 | break; |
| 1162 | } |
| 1163 | |
Jonathan Gordon | 77a458a | 2007-05-08 11:55:43 +0000 | [diff] [blame] | 1164 | menu_exit(m); |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1165 | |
| 1166 | return result; |
| 1167 | } |
| 1168 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1169 | void move_cursor(struct sudoku_state_t* state, int newx, int newy) |
| 1170 | { |
| 1171 | int oldx, oldy; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1172 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1173 | /* Check that the character at the cursor position is legal */ |
| 1174 | if (check_status(state)) { |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1175 | rb->splash(HZ*2, "Illegal move!"); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1176 | /* Ignore any button presses during the splash */ |
| 1177 | rb->button_clear_queue(); |
| 1178 | return; |
| 1179 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1180 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1181 | /* Move Cursor */ |
| 1182 | oldx=state->x; |
| 1183 | oldy=state->y; |
| 1184 | state->x=newx; |
| 1185 | state->y=newy; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1186 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1187 | /* Redraw current and old cells */ |
| 1188 | update_cell(state,oldx,oldy); |
| 1189 | update_cell(state,newx,newy); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1190 | } |
| 1191 | |
| 1192 | /* plugin entry point */ |
Steve Bavin | 6526577 | 2008-05-13 09:57:56 +0000 | [diff] [blame] | 1193 | enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1194 | { |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1195 | bool exit; |
| 1196 | int button; |
| 1197 | int lastbutton = BUTTON_NONE; |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1198 | int res; |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1199 | int rc = PLUGIN_OK; |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1200 | long ticks; |
| 1201 | struct sudoku_state_t state; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1202 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1203 | /* plugin init */ |
| 1204 | rb = api; |
| 1205 | /* end of plugin init */ |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1206 | |
| 1207 | #ifdef HAVE_LCD_COLOR |
| 1208 | configfile_init(rb); |
| 1209 | configfile_load(cfg_filename, disk_config, |
| 1210 | sizeof(disk_config) / sizeof(disk_config[0]), |
| 1211 | CFGFILE_MINVERSION); |
| 1212 | rb->memcpy(&sudcfg, &sudcfg_disk, sizeof(sudcfg)); /* copy to running config */ |
| 1213 | #endif |
Karl Kurbjun | 1a9442c | 2006-11-15 06:46:35 +0000 | [diff] [blame] | 1214 | |
| 1215 | #if LCD_DEPTH > 1 |
Karl Kurbjun | d6b0c97 | 2006-11-15 06:14:27 +0000 | [diff] [blame] | 1216 | rb->lcd_set_backdrop(NULL); |
Jonathan Gordon | cf887d6 | 2006-12-18 02:33:39 +0000 | [diff] [blame] | 1217 | rb->lcd_set_foreground(LCD_BLACK); |
| 1218 | rb->lcd_set_background(LCD_WHITE); |
Karl Kurbjun | 1a9442c | 2006-11-15 06:46:35 +0000 | [diff] [blame] | 1219 | #endif |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1220 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1221 | clear_state(&state); |
Dave Chapman | 33e935c | 2005-10-04 23:36:03 +0000 | [diff] [blame] | 1222 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1223 | if (parameter==NULL) { |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1224 | /* We have been started as a plugin - try default sudoku.ss */ |
| 1225 | if (!load_sudoku(&state,GAME_FILE)) { |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1226 | /* No previous game saved, use the default */ |
| 1227 | default_state(&state); |
Dave Chapman | 0f619c6 | 2006-04-01 18:38:34 +0000 | [diff] [blame] | 1228 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1229 | } else { |
| 1230 | if (!load_sudoku(&state,(char*)parameter)) { |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1231 | rb->splash(HZ*2, "Load error"); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1232 | return(PLUGIN_ERROR); |
| 1233 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1234 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1235 | |
Jonathan Gordon | cf887d6 | 2006-12-18 02:33:39 +0000 | [diff] [blame] | 1236 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1237 | display_board(&state); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1238 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1239 | /* The main game loop */ |
| 1240 | exit=false; |
| 1241 | ticks=0; |
| 1242 | while(!exit) { |
| 1243 | button = rb->button_get(true); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1244 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1245 | switch(button){ |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1246 | #ifdef SUDOKU_BUTTON_QUIT |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1247 | /* Exit game */ |
| 1248 | case SUDOKU_BUTTON_QUIT: |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1249 | if (check_status(&state)) { |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1250 | rb->splash(HZ*2, "Illegal move!"); |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1251 | /* Ignore any button presses during the splash */ |
| 1252 | rb->button_clear_queue(); |
| 1253 | } else { |
| 1254 | save_sudoku(&state); |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1255 | exit=true; |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1256 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1257 | break; |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1258 | #endif |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1259 | |
| 1260 | /* Increment digit */ |
Dave Chapman | 567718d | 2005-09-22 20:17:21 +0000 | [diff] [blame] | 1261 | #ifdef SUDOKU_BUTTON_ALTTOGGLE |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1262 | case SUDOKU_BUTTON_ALTTOGGLE | BUTTON_REPEAT: |
Dave Chapman | 567718d | 2005-09-22 20:17:21 +0000 | [diff] [blame] | 1263 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1264 | case SUDOKU_BUTTON_TOGGLE | BUTTON_REPEAT: |
| 1265 | /* Slow down the repeat speed to 1/3 second */ |
| 1266 | if ((*rb->current_tick-ticks) < (HZ/3)) { |
| 1267 | break; |
| 1268 | } |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1269 | |
Dave Chapman | 567718d | 2005-09-22 20:17:21 +0000 | [diff] [blame] | 1270 | #ifdef SUDOKU_BUTTON_ALTTOGGLE |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1271 | case SUDOKU_BUTTON_ALTTOGGLE: |
Dave Chapman | 567718d | 2005-09-22 20:17:21 +0000 | [diff] [blame] | 1272 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1273 | case SUDOKU_BUTTON_TOGGLE: |
Jens Arnold | e85fe09 | 2005-09-22 21:00:03 +0000 | [diff] [blame] | 1274 | #ifdef SUDOKU_BUTTON_TOGGLE_PRE |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1275 | if ((button == SUDOKU_BUTTON_TOGGLE) |
| 1276 | && (lastbutton != SUDOKU_BUTTON_TOGGLE_PRE)) |
| 1277 | break; |
Jens Arnold | e85fe09 | 2005-09-22 21:00:03 +0000 | [diff] [blame] | 1278 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1279 | /* Increment digit */ |
| 1280 | ticks=*rb->current_tick; |
| 1281 | if (state.editmode) { |
| 1282 | if (state.startboard[state.y][state.x]=='9') { |
| 1283 | state.startboard[state.y][state.x]='0'; |
| 1284 | state.currentboard[state.y][state.x]='0'; |
| 1285 | } else { |
| 1286 | state.startboard[state.y][state.x]++; |
| 1287 | state.currentboard[state.y][state.x]++; |
| 1288 | } |
| 1289 | } else { |
| 1290 | if (state.startboard[state.y][state.x]=='0') { |
| 1291 | if (state.currentboard[state.y][state.x]=='9') { |
| 1292 | state.currentboard[state.y][state.x]='0'; |
| 1293 | } else { |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1294 | state.currentboard[state.y][state.x]++; |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1295 | } |
| 1296 | } |
| 1297 | } |
| 1298 | update_cell(&state,state.y,state.x); |
| 1299 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1300 | |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1301 | #ifdef SUDOKU_BUTTON_TOGGLEBACK |
| 1302 | case SUDOKU_BUTTON_TOGGLEBACK | BUTTON_REPEAT: |
| 1303 | /* Slow down the repeat speed to 1/3 second */ |
| 1304 | if ((*rb->current_tick-ticks) < (HZ/3)) { |
| 1305 | break; |
| 1306 | } |
| 1307 | |
| 1308 | case SUDOKU_BUTTON_TOGGLEBACK: |
| 1309 | /* Decrement digit */ |
| 1310 | ticks=*rb->current_tick; |
| 1311 | if (state.editmode) { |
| 1312 | if (state.startboard[state.y][state.x]=='0') { |
| 1313 | state.startboard[state.y][state.x]='9'; |
| 1314 | state.currentboard[state.y][state.x]='9'; |
| 1315 | } else { |
| 1316 | state.startboard[state.y][state.x]--; |
| 1317 | state.currentboard[state.y][state.x]--; |
| 1318 | } |
| 1319 | } else { |
| 1320 | if (state.startboard[state.y][state.x]=='0') { |
| 1321 | if (state.currentboard[state.y][state.x]=='0') { |
| 1322 | state.currentboard[state.y][state.x]='9'; |
| 1323 | } else { |
| 1324 | state.currentboard[state.y][state.x]--; |
| 1325 | } |
| 1326 | } |
| 1327 | } |
| 1328 | update_cell(&state,state.y,state.x); |
| 1329 | break; |
| 1330 | #endif |
| 1331 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1332 | /* move cursor left */ |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1333 | case SUDOKU_BUTTON_LEFT: |
| 1334 | case (SUDOKU_BUTTON_LEFT | BUTTON_REPEAT): |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1335 | if (state.x==0) { |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1336 | #ifndef SUDOKU_BUTTON_UP |
| 1337 | if (state.y==0) { |
| 1338 | move_cursor(&state,8,8); |
| 1339 | } else { |
| 1340 | move_cursor(&state,8,state.y-1); |
| 1341 | } |
| 1342 | #else |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1343 | move_cursor(&state,8,state.y); |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1344 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1345 | } else { |
| 1346 | move_cursor(&state,state.x-1,state.y); |
| 1347 | } |
| 1348 | break; |
| 1349 | |
| 1350 | /* move cursor right */ |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1351 | case SUDOKU_BUTTON_RIGHT: |
| 1352 | case (SUDOKU_BUTTON_RIGHT | BUTTON_REPEAT): |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1353 | if (state.x==8) { |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1354 | #ifndef SUDOKU_BUTTON_DOWN |
| 1355 | if (state.y==8) { |
| 1356 | move_cursor(&state,0,0); |
| 1357 | } else { |
| 1358 | move_cursor(&state,0,state.y+1); |
| 1359 | } |
| 1360 | #else |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1361 | move_cursor(&state,0,state.y); |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1362 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1363 | } else { |
| 1364 | move_cursor(&state,state.x+1,state.y); |
| 1365 | } |
| 1366 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1367 | |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1368 | #ifdef SUDOKU_BUTTON_UP |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1369 | /* move cursor up */ |
| 1370 | case SUDOKU_BUTTON_UP: |
| 1371 | case (SUDOKU_BUTTON_UP | BUTTON_REPEAT): |
| 1372 | if (state.y==0) { |
| 1373 | move_cursor(&state,state.x,8); |
| 1374 | } else { |
| 1375 | move_cursor(&state,state.x,state.y-1); |
| 1376 | } |
| 1377 | break; |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1378 | #endif |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1379 | |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1380 | #ifdef SUDOKU_BUTTON_DOWN |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1381 | /* move cursor down */ |
| 1382 | case SUDOKU_BUTTON_DOWN: |
| 1383 | case (SUDOKU_BUTTON_DOWN | BUTTON_REPEAT): |
| 1384 | if (state.y==8) { |
| 1385 | move_cursor(&state,state.x,0); |
| 1386 | } else { |
| 1387 | move_cursor(&state,state.x,state.y+1); |
| 1388 | } |
| 1389 | break; |
Dave Chapman | a698c3e | 2006-04-02 00:09:33 +0000 | [diff] [blame] | 1390 | #endif |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1391 | |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1392 | case SUDOKU_BUTTON_MENU: |
Jens Arnold | e85fe09 | 2005-09-22 21:00:03 +0000 | [diff] [blame] | 1393 | #ifdef SUDOKU_BUTTON_MENU_PRE |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1394 | if (lastbutton != SUDOKU_BUTTON_MENU_PRE) |
| 1395 | break; |
Jens Arnold | e85fe09 | 2005-09-22 21:00:03 +0000 | [diff] [blame] | 1396 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1397 | /* Don't let the user leave a game in a bad state */ |
| 1398 | if (check_status(&state)) { |
Jens Arnold | 4d6374c | 2007-03-16 21:56:08 +0000 | [diff] [blame] | 1399 | rb->splash(HZ*2, "Illegal move!"); |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1400 | /* Ignore any button presses during the splash */ |
| 1401 | rb->button_clear_queue(); |
| 1402 | } else { |
| 1403 | if (state.editmode) { |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1404 | res = sudoku_edit_menu(&state); |
| 1405 | if (res == MENU_ATTACHED_USB) { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1406 | rc = PLUGIN_USB_CONNECTED; |
| 1407 | exit = true; |
Dave Chapman | 506bac9 | 2006-05-15 20:08:37 +0000 | [diff] [blame] | 1408 | } else if (res == 1) { /* Quit */ |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1409 | exit = true; |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1410 | } |
| 1411 | } else { |
| 1412 | if (sudoku_menu(&state)) { |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1413 | rc = PLUGIN_USB_CONNECTED; |
| 1414 | exit = true; |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1415 | } |
| 1416 | } |
| 1417 | } |
| 1418 | break; |
Dave Chapman | 61eac11 | 2005-11-29 00:02:00 +0000 | [diff] [blame] | 1419 | #ifdef SUDOKU_BUTTON_POSSIBLE |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1420 | case SUDOKU_BUTTON_POSSIBLE: |
| 1421 | /* Toggle current number in the possiblevals structure */ |
| 1422 | if (state.currentboard[state.y][state.x]!='0') { |
| 1423 | state.possiblevals[state.y][state.x]^= |
| 1424 | (1 << (state.currentboard[state.y][state.x] - '0')); |
| 1425 | } |
| 1426 | break; |
Dave Chapman | 61eac11 | 2005-11-29 00:02:00 +0000 | [diff] [blame] | 1427 | #endif |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1428 | default: |
| 1429 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { |
| 1430 | /* Quit if USB has been connected */ |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1431 | rc = PLUGIN_USB_CONNECTED; |
| 1432 | exit = true; |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1433 | } |
| 1434 | break; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1435 | } |
Daniel Stenberg | 220fafd | 2006-03-03 08:14:44 +0000 | [diff] [blame] | 1436 | if (button != BUTTON_NONE) |
| 1437 | lastbutton = button; |
| 1438 | |
| 1439 | display_board(&state); |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1440 | } |
Jens Arnold | 65b4aae | 2007-09-16 18:46:39 +0000 | [diff] [blame] | 1441 | #ifdef HAVE_LCD_COLOR |
| 1442 | if (rb->memcmp(&sudcfg, &sudcfg_disk, sizeof(sudcfg))) /* save settings if changed */ |
| 1443 | { |
| 1444 | rb->memcpy(&sudcfg_disk, &sudcfg, sizeof(sudcfg)); |
| 1445 | configfile_save(cfg_filename, disk_config, |
| 1446 | sizeof(disk_config) / sizeof(disk_config[0]), |
| 1447 | CFGFILE_VERSION); |
| 1448 | } |
| 1449 | #endif |
| 1450 | return rc; |
Dave Chapman | 6afb017 | 2005-09-22 08:53:04 +0000 | [diff] [blame] | 1451 | } |
| 1452 | |
| 1453 | #endif |