diff options
Diffstat (limited to 'apps')
17 files changed, 1884 insertions, 0 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index b060c8230e..3a1f52c9b1 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -16711,3 +16711,227 @@ | |||
16711 | *: "Default Browser" | 16711 | *: "Default Browser" |
16712 | </voice> | 16712 | </voice> |
16713 | </phrase> | 16713 | </phrase> |
16714 | <phrase> | ||
16715 | id: LANG_AMAZE_MENU | ||
16716 | desc: Amaze game | ||
16717 | user: core | ||
16718 | <source> | ||
16719 | *: "Amaze Main Menu" | ||
16720 | </source> | ||
16721 | <dest> | ||
16722 | *: "Amaze Main Menu" | ||
16723 | </dest> | ||
16724 | <voice> | ||
16725 | *: "Amaze Main Menu" | ||
16726 | </voice> | ||
16727 | </phrase> | ||
16728 | <phrase> | ||
16729 | id: LANG_SET_MAZE_SIZE | ||
16730 | desc: Maze size in Amaze game | ||
16731 | user: core | ||
16732 | <source> | ||
16733 | *: "Set Maze Size" | ||
16734 | </source> | ||
16735 | <dest> | ||
16736 | *: "Set Maze Size" | ||
16737 | </dest> | ||
16738 | <voice> | ||
16739 | *: "Set Maze Size" | ||
16740 | </voice> | ||
16741 | </phrase> | ||
16742 | <phrase> | ||
16743 | id: LANG_VIEW_MAP | ||
16744 | desc: Map in Amaze game | ||
16745 | user: core | ||
16746 | <source> | ||
16747 | *: "View Map" | ||
16748 | </source> | ||
16749 | <dest> | ||
16750 | *: "View Map" | ||
16751 | </dest> | ||
16752 | <voice> | ||
16753 | *: "View Map" | ||
16754 | </voice> | ||
16755 | </phrase> | ||
16756 | <phrase> | ||
16757 | id: LANG_SHOW_COMPASS | ||
16758 | desc: Compass in Amaze game | ||
16759 | user: core | ||
16760 | <source> | ||
16761 | *: "Show Compass" | ||
16762 | </source> | ||
16763 | <dest> | ||
16764 | *: "Show Compass" | ||
16765 | </dest> | ||
16766 | <voice> | ||
16767 | *: "Show Compass" | ||
16768 | </voice> | ||
16769 | </phrase> | ||
16770 | <phrase> | ||
16771 | id: LANG_SHOW_MAP | ||
16772 | desc: Map in Amaze game | ||
16773 | user: core | ||
16774 | <source> | ||
16775 | *: "Show Map" | ||
16776 | </source> | ||
16777 | <dest> | ||
16778 | *: "Show Map" | ||
16779 | </dest> | ||
16780 | <voice> | ||
16781 | *: "Show Map" | ||
16782 | </voice> | ||
16783 | </phrase> | ||
16784 | <phrase> | ||
16785 | id: LANG_REMEMBER_PATH | ||
16786 | desc: Map in Amaze game | ||
16787 | user: core | ||
16788 | <source> | ||
16789 | *: "Remember Path" | ||
16790 | </source> | ||
16791 | <dest> | ||
16792 | *: "Remember Path" | ||
16793 | </dest> | ||
16794 | <voice> | ||
16795 | *: "Remember Path" | ||
16796 | </voice> | ||
16797 | </phrase> | ||
16798 | <phrase> | ||
16799 | id: LANG_USE_LARGE_TILES | ||
16800 | desc: Map in Amaze game | ||
16801 | user: core | ||
16802 | <source> | ||
16803 | *: "Use Large Tiles" | ||
16804 | </source> | ||
16805 | <dest> | ||
16806 | *: "Use Large Tiles" | ||
16807 | </dest> | ||
16808 | <voice> | ||
16809 | *: "Use Large Tiles" | ||
16810 | </voice> | ||
16811 | </phrase> | ||
16812 | <phrase> | ||
16813 | id: LANG_SHOW_SOLUTION | ||
16814 | desc: Map in Amaze game | ||
16815 | user: core | ||
16816 | <source> | ||
16817 | *: "Show Solution" | ||
16818 | </source> | ||
16819 | <dest> | ||
16820 | *: "Show Solution" | ||
16821 | </dest> | ||
16822 | <voice> | ||
16823 | *: "Show Solution" | ||
16824 | </voice> | ||
16825 | </phrase> | ||
16826 | <phrase> | ||
16827 | id: LANG_QUIT_WITHOUT_SAVING | ||
16828 | desc: | ||
16829 | user: core | ||
16830 | <source> | ||
16831 | *: "Quit without saving" | ||
16832 | </source> | ||
16833 | <dest> | ||
16834 | *: "Quit without saving" | ||
16835 | </dest> | ||
16836 | <voice> | ||
16837 | *: "Quit without saving" | ||
16838 | </voice> | ||
16839 | </phrase> | ||
16840 | <phrase> | ||
16841 | id: LANG_GENERATING_MAZE | ||
16842 | desc: Amaze game | ||
16843 | user: core | ||
16844 | <source> | ||
16845 | *: "Generating maze..." | ||
16846 | </source> | ||
16847 | <dest> | ||
16848 | *: "Generating maze..." | ||
16849 | </dest> | ||
16850 | <voice> | ||
16851 | *: "Generating maze..." | ||
16852 | </voice> | ||
16853 | </phrase> | ||
16854 | <phrase> | ||
16855 | id: LANG_YOU_WIN | ||
16856 | desc: Success in game | ||
16857 | user: core | ||
16858 | <source> | ||
16859 | *: "You win!" | ||
16860 | </source> | ||
16861 | <dest> | ||
16862 | *: "You win!" | ||
16863 | </dest> | ||
16864 | <voice> | ||
16865 | *: "You win!" | ||
16866 | </voice> | ||
16867 | </phrase> | ||
16868 | <phrase> | ||
16869 | id: LANG_YOU_CHEATED | ||
16870 | desc: Cheated in game | ||
16871 | user: core | ||
16872 | <source> | ||
16873 | *: "You cheated!" | ||
16874 | </source> | ||
16875 | <dest> | ||
16876 | *: "You cheated!" | ||
16877 | </dest> | ||
16878 | <voice> | ||
16879 | *: "You cheated!" | ||
16880 | </voice> | ||
16881 | </phrase> | ||
16882 | <phrase> | ||
16883 | id: LANG_DIFFICULTY_EASY | ||
16884 | desc: Game difficulty | ||
16885 | user: core | ||
16886 | <source> | ||
16887 | *: "Easy" | ||
16888 | </source> | ||
16889 | <dest> | ||
16890 | *: "Easy" | ||
16891 | </dest> | ||
16892 | <voice> | ||
16893 | *: "Easy" | ||
16894 | </voice> | ||
16895 | </phrase> | ||
16896 | <phrase> | ||
16897 | id: LANG_DIFFICULTY_MEDIUM | ||
16898 | desc: Game difficulty | ||
16899 | user: core | ||
16900 | <source> | ||
16901 | *: "Medium" | ||
16902 | </source> | ||
16903 | <dest> | ||
16904 | *: "Medium" | ||
16905 | </dest> | ||
16906 | <voice> | ||
16907 | *: "Medium" | ||
16908 | </voice> | ||
16909 | </phrase> | ||
16910 | <phrase> | ||
16911 | id: LANG_DIFFICULTY_HARD | ||
16912 | desc: Game difficulty | ||
16913 | user: core | ||
16914 | <source> | ||
16915 | *: "Hard" | ||
16916 | </source> | ||
16917 | <dest> | ||
16918 | *: "Hard" | ||
16919 | </dest> | ||
16920 | <voice> | ||
16921 | *: "Hard" | ||
16922 | </voice> | ||
16923 | </phrase> | ||
16924 | <phrase> | ||
16925 | id: LANG_DIFFICULTY_EXPERT | ||
16926 | desc: Game difficulty | ||
16927 | user: core | ||
16928 | <source> | ||
16929 | *: "Expert" | ||
16930 | </source> | ||
16931 | <dest> | ||
16932 | *: "Expert" | ||
16933 | </dest> | ||
16934 | <voice> | ||
16935 | *: "Expert" | ||
16936 | </voice> | ||
16937 | </phrase> | ||
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 5320015772..28b8b67c68 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES | |||
@@ -2,6 +2,7 @@ | |||
2 | alpine_cdc,apps | 2 | alpine_cdc,apps |
3 | alarmclock,apps | 3 | alarmclock,apps |
4 | announce_status,demos | 4 | announce_status,demos |
5 | amaze,games | ||
5 | autostart,apps | 6 | autostart,apps |
6 | battery_bench,apps | 7 | battery_bench,apps |
7 | bench_scaler,apps | 8 | bench_scaler,apps |
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index bf36d50a40..3d520dea39 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES | |||
@@ -112,6 +112,7 @@ pictureflow.c | |||
112 | metronome.c | 112 | metronome.c |
113 | 113 | ||
114 | 2048.c | 114 | 2048.c |
115 | amaze.c | ||
115 | 116 | ||
116 | /* Lua needs at least 160 KB to work in */ | 117 | /* Lua needs at least 160 KB to work in */ |
117 | #if PLUGIN_BUFFER_SIZE >= 0x80000 | 118 | #if PLUGIN_BUFFER_SIZE >= 0x80000 |
diff --git a/apps/plugins/amaze.c b/apps/plugins/amaze.c new file mode 100644 index 0000000000..2af9463a16 --- /dev/null +++ b/apps/plugins/amaze.c | |||
@@ -0,0 +1,1620 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2014 Franklin Wei, (c) 2018 Sebastian Leonhardt | ||
11 | * | ||
12 | * Original work (C) 2000 David Leonard, public domain according to | ||
13 | * http://www.adaptive-enterprises.com.au/~d/software/amaze/ | ||
14 | * | ||
15 | * Original Rockbox port by Jerry Chapman, 2007 | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or | ||
18 | * modify it under the terms of the GNU General Public License | ||
19 | * as published by the Free Software Foundation; either version 2 | ||
20 | * of the License, or (at your option) any later version. | ||
21 | * | ||
22 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
23 | * KIND, either express or implied. | ||
24 | * | ||
25 | ***************************************************************************/ | ||
26 | |||
27 | #include "plugin.h" | ||
28 | #include "lib/pluginlib_actions.h" | ||
29 | |||
30 | const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; | ||
31 | |||
32 | static const struct opt_items noyes_text[] = { | ||
33 | { STR(LANG_SET_BOOL_NO) }, | ||
34 | { STR(LANG_SET_BOOL_YES) } | ||
35 | }; | ||
36 | |||
37 | static const struct opt_items mazesize_text[] = { | ||
38 | { STR(LANG_DIFFICULTY_EASY) }, | ||
39 | { STR(LANG_DIFFICULTY_MEDIUM) }, | ||
40 | { STR(LANG_DIFFICULTY_HARD) }, | ||
41 | { STR(LANG_DIFFICULTY_EXPERT) } | ||
42 | }; | ||
43 | |||
44 | bool show_map; | ||
45 | bool remember_visited; | ||
46 | bool use_large_tiles; | ||
47 | int maze_size; | ||
48 | |||
49 | #if LCD_DEPTH >= 16 | ||
50 | #define COLOR_GROUND LCD_RGBPACK(51,51,51) | ||
51 | #define COLOR_SKY LCD_RGBPACK(51,51,102) | ||
52 | #define COLOR_VISITED LCD_RGBPACK(102,77,51) | ||
53 | #define COLOR_MARK LCD_RGBPACK(255,100,61) | ||
54 | #define COLOR_GOAL LCD_RGBPACK(128,0,0) /* red */ | ||
55 | #define COLOR_COMPASS LCD_RGBPACK(255,255,0) /* yellow */ | ||
56 | #define COLOR_PARA LCD_RGBPACK(153,153,102) /* color side wall */ | ||
57 | /* #define COLOR_PERP LCD_RGBPACK(102,51,0) */ | ||
58 | #define COLOR_PERP LCD_RGBPACK(204,153,102) /* color wall perp */ | ||
59 | #elif LCD_DEPTH == 2 | ||
60 | #define COLOR_GROUND LCD_BLACK | ||
61 | #define COLOR_SKY LCD_WHITE | ||
62 | #define COLOR_VISITED LCD_DARKGRAY | ||
63 | #define COLOR_GOAL LCD_WHITE | ||
64 | #define COLOR_COMPASS LCD_BLACK | ||
65 | #define COLOR_MARK LCD_WHITE | ||
66 | #define COLOR_PARA LCD_DARKGRAY /* color side wall */ | ||
67 | #define COLOR_PERP LCD_LIGHTGRAY /* color wall perp */ | ||
68 | #else /* mono */ | ||
69 | #define COLOR_GROUND LCD_BLACK | ||
70 | #define COLOR_SKY LCD_BLACK | ||
71 | #define COLOR_VISITED LCD_BLACK | ||
72 | #define COLOR_GOAL LCD_BLACK | ||
73 | #define COLOR_COMPASS LCD_WHITE | ||
74 | #define COLOR_PARA LCD_BLACK /* color side wall */ | ||
75 | #define COLOR_PERP LCD_WHITE /* color wall perp */ | ||
76 | #endif | ||
77 | |||
78 | #define A_DOWN 'v' | ||
79 | #define A_RIGHT '>' | ||
80 | #define A_UP '^' | ||
81 | #define A_LEFT '<' | ||
82 | #define SPACE ' ' /* Space you can walk through */ | ||
83 | #define BLOCK 'B' /* A block that you can't walk through */ | ||
84 | #define OBSPACE '#' /* Obscured space */ | ||
85 | #define VISITED '.' /* Visited space */ | ||
86 | #define GOAL '%' /* Exit from the maze */ | ||
87 | #define START '+' /* Starting point in the maze */ | ||
88 | |||
89 | enum dir { DIR_DOWN=0, DIR_RIGHT=1, DIR_UP=2, DIR_LEFT=3 }; | ||
90 | #define _TOD(d) (enum dir)((d) % 4) | ||
91 | #define _TOI(d) (int)(d) | ||
92 | #define LEFT_OF(d) _TOD(_TOI(d) + 1) | ||
93 | #define REVERSE_OF(d) _TOD(_TOI(d) + 2) | ||
94 | #define RIGHT_OF(d) _TOD(_TOI(d) + 3) | ||
95 | |||
96 | static struct { int y, x; } dirtab[4] = | ||
97 | { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; | ||
98 | static char ptab[4] = { A_DOWN, A_RIGHT, A_UP, A_LEFT }; | ||
99 | |||
100 | int px, py; /* Player position */ | ||
101 | enum dir pdir; /* Player direction */ | ||
102 | char punder; /* character under player, if any */ | ||
103 | int sx, sy; /* Start position */ | ||
104 | int gx, gy; /* Goal position */ | ||
105 | int gdist; /* Distance from start to goal */ | ||
106 | int won = 0; /* Reached goal */ | ||
107 | int cheated = 0; /* Cheated somehow */ | ||
108 | bool compass = false; /* show compass */ | ||
109 | int button; /* Button data */ | ||
110 | bool loaded=false; /* Loaded? */ | ||
111 | |||
112 | #define FIELD_SIZE 80 | ||
113 | #define MAP_CONST 20 | ||
114 | |||
115 | static char map[FIELD_SIZE * FIELD_SIZE]; /* map storage */ | ||
116 | static char umap[FIELD_SIZE * FIELD_SIZE]; | ||
117 | |||
118 | /* visible depth */ | ||
119 | #define MAX_DEPTH 20 | ||
120 | int depth; | ||
121 | |||
122 | /* CX,CY = center of screen */ | ||
123 | #define CX LCD_WIDTH / 2 | ||
124 | #define CY LCD_HEIGHT / 2 | ||
125 | |||
126 | int crd_x[MAX_DEPTH], crd_y[MAX_DEPTH]; /* screen vertices */ | ||
127 | |||
128 | #if LCD_WIDTH >= 220 || LCD_HEIGHT >= 220 | ||
129 | #include "pluginbitmaps/amaze_tiles_9.h" | ||
130 | #define amaze_tiles_large amaze_tiles_9 | ||
131 | #define TILESIZE_LARGE BMPWIDTH_amaze_tiles_9 | ||
132 | #include "pluginbitmaps/amaze_tiles_7.h" | ||
133 | #define amaze_tiles_small amaze_tiles_7 | ||
134 | #define TILESIZE_SMALL BMPWIDTH_amaze_tiles_7 | ||
135 | #elif LCD_WIDTH >= 160 || LCD_HEIGHT >= 160 | ||
136 | #include "pluginbitmaps/amaze_tiles_7.h" | ||
137 | #define amaze_tiles_large amaze_tiles_7 | ||
138 | #define TILESIZE_LARGE BMPWIDTH_amaze_tiles_7 | ||
139 | #include "pluginbitmaps/amaze_tiles_5.h" | ||
140 | #define amaze_tiles_small amaze_tiles_5 | ||
141 | #define TILESIZE_SMALL BMPWIDTH_amaze_tiles_5 | ||
142 | #else | ||
143 | #include "pluginbitmaps/amaze_tiles_5.h" | ||
144 | #define amaze_tiles_large amaze_tiles_5 | ||
145 | #define TILESIZE_LARGE BMPWIDTH_amaze_tiles_5 | ||
146 | #include "pluginbitmaps/amaze_tiles_3.h" | ||
147 | #define amaze_tiles_small amaze_tiles_3 | ||
148 | #define TILESIZE_SMALL BMPWIDTH_amaze_tiles_3 | ||
149 | #endif | ||
150 | |||
151 | /* save file names */ | ||
152 | #define UMAP_FILE PLUGIN_GAMES_DIR "/amaze_umap.sav" | ||
153 | #define MAP_FILE PLUGIN_GAMES_DIR "/amaze_map.sav" | ||
154 | #define PREF_FILE PLUGIN_GAMES_DIR "/amaze_prefs.sav" | ||
155 | |||
156 | void clearscreen (void) | ||
157 | { | ||
158 | #if LCD_DEPTH > 1 | ||
159 | rb->lcd_set_background(LCD_BLACK); | ||
160 | rb->lcd_set_foreground(LCD_WHITE); | ||
161 | #endif | ||
162 | rb->lcd_clear_display(); | ||
163 | rb->lcd_update(); | ||
164 | } | ||
165 | |||
166 | void getmaxyx(int *y, int *x) | ||
167 | { | ||
168 | *y = (maze_size + 1) * MAP_CONST; | ||
169 | *x = (maze_size + 1) * MAP_CONST; | ||
170 | } | ||
171 | |||
172 | void map_write (char *pane, int y, int x, char c) | ||
173 | { | ||
174 | int maxy, maxx; | ||
175 | |||
176 | getmaxyx(&maxy, &maxx); | ||
177 | |||
178 | if (x<0 || x>=maxx || y<0 || y>=maxy) return; | ||
179 | |||
180 | pane[x * FIELD_SIZE + y] = c; | ||
181 | |||
182 | } | ||
183 | char map_read (char *pane, int y, int x) | ||
184 | { | ||
185 | int maxy, maxx; | ||
186 | |||
187 | getmaxyx(&maxy, &maxx); | ||
188 | |||
189 | if (x<0 || x>=maxx || y<0 || y>=maxy) { | ||
190 | return SPACE; | ||
191 | } | ||
192 | |||
193 | return pane[x * FIELD_SIZE + y]; | ||
194 | } | ||
195 | |||
196 | /* redefine ncurses werase */ | ||
197 | void werase (char *pane) | ||
198 | { | ||
199 | int y, x; | ||
200 | int maxy, maxx; | ||
201 | |||
202 | getmaxyx(&maxy, &maxx); | ||
203 | |||
204 | for (y = 0; y < maxy; y++) | ||
205 | for (x = 0; x < maxx; x++) | ||
206 | map_write(pane, y, x, SPACE); | ||
207 | } | ||
208 | |||
209 | /* start of David Leonard's code */ | ||
210 | |||
211 | /* Look at position (y,x) in the maze map */ | ||
212 | char at(int y, int x) | ||
213 | { | ||
214 | int maxy, maxx; | ||
215 | |||
216 | getmaxyx(&maxy, &maxx); | ||
217 | |||
218 | if (y == py && x == px) | ||
219 | return punder; | ||
220 | |||
221 | if (y < 0 || y >= maxy || x < 0 || x >= maxx) | ||
222 | return SPACE; | ||
223 | else { | ||
224 | return map_read(map, y, x); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | void copyumap(int y, int x, int fullvis) | ||
229 | { | ||
230 | char c; | ||
231 | |||
232 | c = at(y, x); | ||
233 | if (!fullvis && c == SPACE && map_read(umap, y, x) != SPACE) | ||
234 | c = OBSPACE; | ||
235 | map_write(umap, y, x, c); | ||
236 | } | ||
237 | |||
238 | struct path { | ||
239 | int y, x; | ||
240 | int ttl; /* Time until this path stops */ | ||
241 | int spawns; /* Max number of forks this path can do */ | ||
242 | int distance; /* Distance from start */ | ||
243 | struct path *next; | ||
244 | }; | ||
245 | |||
246 | /* | ||
247 | * A better maze-digging algorithm. | ||
248 | * Simultaneously advance multiple digging paths through the map. | ||
249 | * This is done by having a work queue of advancing paths. | ||
250 | * Occasionally a path can fork; thus adding more to the work | ||
251 | * queue and diversifying the maze. | ||
252 | */ | ||
253 | void eatmaze(int starty, int startx) | ||
254 | { | ||
255 | struct path { | ||
256 | int y, x; | ||
257 | int ttl; /* Time until this path stops */ | ||
258 | int spawns; /* Max number of forks this path can do */ | ||
259 | int distance; /* Distance from start */ | ||
260 | struct path *next; | ||
261 | }; | ||
262 | struct path *path_free, *path_head, *path_tail; | ||
263 | struct path *p, *s; | ||
264 | /* static -- per <hcs> in #rockbox -- was having stack issues */ | ||
265 | static struct path path_storage[2000]; | ||
266 | int try; | ||
267 | unsigned i; | ||
268 | int y, x, dy, dx; | ||
269 | int sdir; | ||
270 | |||
271 | /* Set up the free list of path cells */ | ||
272 | for (i = 2; i < sizeof path_storage / sizeof path_storage[0]; i++) | ||
273 | path_storage[i].next = &path_storage[i-1]; | ||
274 | path_storage[1].next = NULL; | ||
275 | path_free = &path_storage[sizeof path_storage / sizeof path_storage[0] - 1]; | ||
276 | |||
277 | /* Set up the initial path cell */ | ||
278 | path_storage[0].y = starty; | ||
279 | path_storage[0].x = startx; | ||
280 | map_write(map, starty, startx, SPACE); | ||
281 | |||
282 | /* Set up the initial goal. It will move later. */ | ||
283 | gy = starty; | ||
284 | gx = startx; | ||
285 | gdist = 0; | ||
286 | |||
287 | /* Initial properties of the root path */ | ||
288 | path_storage[0].ttl = 50; | ||
289 | path_storage[0].spawns = 20; | ||
290 | path_storage[0].distance = 0; | ||
291 | |||
292 | /* Put the initial path into the queue */ | ||
293 | path_storage[0].next = NULL; | ||
294 | path_head = path_tail = &path_storage[0]; | ||
295 | |||
296 | while (path_head != NULL) { | ||
297 | /* Dequeue */ | ||
298 | p = path_head; | ||
299 | path_head = p->next; | ||
300 | if (path_head == NULL) | ||
301 | path_tail = NULL; | ||
302 | |||
303 | /* There's a large chance that some paths miss a turn */ | ||
304 | if (rb->rand() % 100 < 60) | ||
305 | goto requeue; | ||
306 | |||
307 | /* First thing we do is advance the path. */ | ||
308 | y = p->y; | ||
309 | x = p->x; | ||
310 | |||
311 | sdir = rb->rand() % 4; | ||
312 | for (try = 0; try < 4; try ++) { | ||
313 | dx = dirtab[(sdir + try) % 4].x; | ||
314 | dy = dirtab[(sdir + try) % 4].y; | ||
315 | |||
316 | /* Going back on ourselves? */ | ||
317 | if (at(y + dy, x + dx) != BLOCK) | ||
318 | continue; | ||
319 | |||
320 | /* Connecting to another path? */ | ||
321 | if (at(y + dy * 2, x + dx * 2) != BLOCK) | ||
322 | continue; | ||
323 | if (at(y + dy + dx, x + dx - dy) != BLOCK) | ||
324 | continue; | ||
325 | if (at(y + dy - dx, x + dx + dy) != BLOCK) | ||
326 | continue; | ||
327 | |||
328 | break; | ||
329 | } | ||
330 | if (try == 4 || p->ttl <= 0) { | ||
331 | /* Failed: the path is placed on the free list. */ | ||
332 | p->next = path_free; | ||
333 | path_free = p; | ||
334 | continue; | ||
335 | } | ||
336 | |||
337 | /* Dig the path a bit */ | ||
338 | p->y = y + dy; | ||
339 | p->x = x + dx; | ||
340 | map_write(map, p->y, p->x, SPACE); | ||
341 | p->ttl--; | ||
342 | p->distance++; | ||
343 | |||
344 | if (p->distance > gdist) { | ||
345 | gx = p->x; | ||
346 | gy = p->y; | ||
347 | gdist = p->distance; | ||
348 | } | ||
349 | |||
350 | /* Decide if we should spawn */ | ||
351 | if (/* rb->rand() % (p->ttl + 1) < p->spawns && */ path_free) { | ||
352 | /* Take a new path element off the free list */ | ||
353 | s = path_free; | ||
354 | path_free = s->next; | ||
355 | |||
356 | /* Insert it at the tail of the queue */ | ||
357 | s->next = NULL; | ||
358 | if (path_tail) path_tail->next = s; | ||
359 | else path_head = s; | ||
360 | path_tail = s; | ||
361 | |||
362 | /* Newly spawned path s will inherit most properties from p */ | ||
363 | s->y = p->y; | ||
364 | s->x = p->x; | ||
365 | s->ttl = p->ttl + rb->rand() % 10; | ||
366 | s->spawns = p->spawns; | ||
367 | s->distance = p->distance; | ||
368 | |||
369 | /* p->spawns--; */ | ||
370 | } | ||
371 | |||
372 | requeue: | ||
373 | /* Put p onto the tail of the queue */ | ||
374 | p->next = NULL; | ||
375 | if (path_tail) path_tail->next = p; | ||
376 | else path_head = p; | ||
377 | path_tail = p; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* Move the player to a new position/direction in the maze map */ | ||
382 | void mappmove(int newpy, int newpx, enum dir newpdir) | ||
383 | { | ||
384 | map_write(map, py, px, punder); | ||
385 | copyumap(py, px, 1); | ||
386 | punder = at(newpy, newpx); | ||
387 | py = newpy; | ||
388 | px = newpx; | ||
389 | pdir = newpdir; | ||
390 | copyumap(py, px, 1); | ||
391 | map_write(umap, py, px, ptab[_TOI(pdir)]); | ||
392 | rb->lcd_update(); | ||
393 | } | ||
394 | |||
395 | void clearmap (char *amap) | ||
396 | { | ||
397 | int maxy, maxx; | ||
398 | int y, x; | ||
399 | |||
400 | getmaxyx(&maxy, &maxx); | ||
401 | |||
402 | |||
403 | for (y = 0; y < maxy; y++) | ||
404 | for (x = 0; x < maxx; x++) | ||
405 | map_write(amap, y, x, BLOCK); | ||
406 | } | ||
407 | |||
408 | /* Reveal the solution to the user */ | ||
409 | void showmap(void) | ||
410 | { | ||
411 | int maxy, maxx, y, x; | ||
412 | char ch, och; | ||
413 | |||
414 | getmaxyx(&maxy, &maxx); | ||
415 | for (y = 0; y < maxy; y++) | ||
416 | for (x = 0; x < maxx; x++) { | ||
417 | ch = at(y, x); | ||
418 | if (ch == SPACE) { | ||
419 | och = map_read(umap, y, x); | ||
420 | if (och == BLOCK || och == OBSPACE) | ||
421 | ch = OBSPACE; | ||
422 | } | ||
423 | map_write(umap, y, x, ch); | ||
424 | rb->yield(); | ||
425 | } | ||
426 | map_write(umap, py, px, ptab[_TOI(pdir)]); | ||
427 | rb->lcd_update(); | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * Create a new maze map | ||
432 | * The algorithm here is quite inferior to that presented in the | ||
433 | * magazine. I could only remember the gist of it: recursively dig a | ||
434 | * trail that doesn't touch any other part of the maze, keeping track | ||
435 | * of all possible points where the path could fork. Later on try those | ||
436 | * possible branches; put limits on the segment lengths etc. | ||
437 | */ | ||
438 | void makemaze(void) | ||
439 | { | ||
440 | int maxy, maxx; | ||
441 | int i; | ||
442 | |||
443 | /* Get the window dimensions */ | ||
444 | getmaxyx(&maxy, &maxx); | ||
445 | |||
446 | clearmap(map); | ||
447 | |||
448 | py = rb->rand() % (maxy - 2) + 1; /* maxy/2 */ | ||
449 | px = rb->rand() % (maxx - 2) + 1; /* maxx/2 */ | ||
450 | |||
451 | eatmaze(py, px); | ||
452 | |||
453 | sx = px; /* starting position */ | ||
454 | sy = py; | ||
455 | |||
456 | /* Face in an interesting direction: */ | ||
457 | pdir = DIR_UP; | ||
458 | for (i = 0; | ||
459 | i < 4 && at(py + dirtab[pdir].y, | ||
460 | px + dirtab[pdir].x) == BLOCK; | ||
461 | i++) | ||
462 | pdir = LEFT_OF(pdir); | ||
463 | |||
464 | map_write(map, py, px, START); | ||
465 | map_write(map, gy, gx, GOAL); | ||
466 | punder = START; | ||
467 | mappmove(py, px, pdir); | ||
468 | } | ||
469 | |||
470 | /* new drawing routines */ | ||
471 | |||
472 | void draw_arrow(int dir, int sx, int sy, int pass) | ||
473 | { | ||
474 | if (pass > 2) return; | ||
475 | |||
476 | rb->lcd_fillrect(sx, sy, 1, 1); | ||
477 | switch(dir) { | ||
478 | case 0: /* down */ | ||
479 | rb->lcd_fillrect(sx + 2*pass, sy, 1, 1); | ||
480 | draw_arrow(dir, sx - 1, sy - 1, pass + 1); | ||
481 | break; | ||
482 | case 2: /* up */ | ||
483 | rb->lcd_fillrect(sx + 2*pass, sy, 1, 1); | ||
484 | draw_arrow(dir, sx - 1, sy + 1, pass + 1); | ||
485 | break; | ||
486 | case 1: /* left */ | ||
487 | rb->lcd_fillrect(sx, sy + 2*pass, 1, 1); | ||
488 | draw_arrow(dir, sx + 1, sy - 1, pass + 1); | ||
489 | break; | ||
490 | case 3: /* right */ | ||
491 | rb->lcd_fillrect(sx, sy + 2*pass, 1, 1); | ||
492 | draw_arrow(dir, sx - 1, sy - 1, pass +1); | ||
493 | break; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | /* Provide a compass pointing 'north' or draw arrow mark on the floor */ | ||
498 | void draw_pointer(int dir, bool is_compass) | ||
499 | { | ||
500 | int offset; | ||
501 | |||
502 | if(is_compass) | ||
503 | offset = -crd_y[1]*2/3; /* draw compass at the top */ | ||
504 | else | ||
505 | offset = crd_y[1]/2; /* draw mark on the floor */ | ||
506 | |||
507 | #if LCD_DEPTH > 1 | ||
508 | if(is_compass) | ||
509 | rb->lcd_set_foreground(COLOR_COMPASS); | ||
510 | else | ||
511 | rb->lcd_set_foreground(COLOR_MARK); | ||
512 | #else | ||
513 | rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
514 | #endif | ||
515 | switch(dir) { | ||
516 | case 0: /* point down */ | ||
517 | draw_arrow(dir, CX - 1, CY + offset + 6, 0); | ||
518 | rb->lcd_fillrect(CX - 1, CY + offset + 1, 1, 3); | ||
519 | break; | ||
520 | case 2: /* point up */ | ||
521 | draw_arrow(dir, CX - 1, CY + offset, 0); | ||
522 | rb->lcd_fillrect(CX - 1, CY + offset + 3, 1, 3); | ||
523 | break; | ||
524 | case 1: /* point left */ | ||
525 | draw_arrow(dir, CX - 6, CY + offset + 6, 0); | ||
526 | rb->lcd_fillrect(CX - 3, CY + offset + 6, 3, 1); | ||
527 | break; | ||
528 | case 3: /* point right */ | ||
529 | draw_arrow(dir, CX + 1, CY + offset + 6, 0); | ||
530 | rb->lcd_fillrect(CX - 4, CY + offset + 6, 3, 1); | ||
531 | break; | ||
532 | } | ||
533 | #if LCD_DEPTH == 1 | ||
534 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
535 | #endif | ||
536 | rb->lcd_update(); | ||
537 | } | ||
538 | |||
539 | void draw_end_wall(int bx, int by) | ||
540 | { | ||
541 | #if LCD_DEPTH > 1 | ||
542 | rb->lcd_set_foreground(COLOR_PERP); | ||
543 | rb->lcd_fillrect(CX - bx/2, CY - by/2, bx + 1, by); | ||
544 | #else | ||
545 | rb->lcd_drawrect(CX - bx/2, CY - by/2, bx + 1, by); | ||
546 | #endif | ||
547 | } | ||
548 | |||
549 | void draw_side(int fx, int bx, int by, int tan_n, int tan_d, bool isleft) | ||
550 | { | ||
551 | int signx; | ||
552 | |||
553 | if(isleft) | ||
554 | signx = -1; | ||
555 | else | ||
556 | signx = 1; | ||
557 | |||
558 | #if LCD_DEPTH > 1 | ||
559 | for(int i = bx; i < fx + 1; i++) | ||
560 | { | ||
561 | /* add some stripes */ | ||
562 | if(i % 3 == 0) | ||
563 | rb->lcd_set_foreground(COLOR_PERP); | ||
564 | else | ||
565 | rb->lcd_set_foreground(COLOR_PARA); | ||
566 | rb->lcd_vline(CX + signx * i/2, | ||
567 | CY - tan_n * (i-bx)/2 / tan_d - by/2, | ||
568 | CY + tan_n * (i-bx)/2 / tan_d + by/2); | ||
569 | } | ||
570 | #else | ||
571 | rb->lcd_vline(CX + signx * bx/2, | ||
572 | CY - by/2, | ||
573 | CY + by/2); | ||
574 | rb->lcd_vline(CX + signx * (fx + 1)/2, | ||
575 | CY - tan_n * (fx - bx + 1)/2 / tan_d - by/2, | ||
576 | CY + tan_n * (fx - bx + 1)/2 / tan_d + by/2); | ||
577 | rb->lcd_drawline(CX + signx * bx/2, | ||
578 | CY - by/2, | ||
579 | CX + signx * (fx + 1)/2, | ||
580 | CY - tan_n * (fx - bx + 1)/2 / tan_d - by/2); | ||
581 | rb->lcd_drawline(CX + signx * bx/2, | ||
582 | CY + by/2, | ||
583 | CX + signx * (fx + 1)/2, | ||
584 | CY + tan_n * (fx - bx + 1)/2 / tan_d + by/2); | ||
585 | #endif | ||
586 | } | ||
587 | |||
588 | void draw_hall(int fx, int bx, int by, bool isleft) | ||
589 | { | ||
590 | #if LCD_DEPTH > 1 | ||
591 | rb->lcd_set_foreground(COLOR_PERP); | ||
592 | |||
593 | if(isleft) | ||
594 | rb->lcd_fillrect(CX - fx/2, CY - by/2, (fx - bx)/2 + 1, by); | ||
595 | else | ||
596 | rb->lcd_fillrect(CX + bx/2, CY - by/2, (fx - bx)/2 + 1, by); | ||
597 | #else | ||
598 | if(isleft) | ||
599 | rb->lcd_drawrect(CX - fx/2, CY - by/2, (fx - bx)/2 + 1, by); | ||
600 | else | ||
601 | rb->lcd_drawrect(CX + bx/2, CY - by/2, (fx - bx)/2 + 1, by); | ||
602 | #endif | ||
603 | } | ||
604 | |||
605 | void draw_side_tri(int fx, int fy, int bx, int tan_n, int tan_d, | ||
606 | bool isvisited, bool isgoal) | ||
607 | { | ||
608 | int i; | ||
609 | int signx, signy; | ||
610 | |||
611 | signy = 1; | ||
612 | |||
613 | while(signy >= -1) | ||
614 | { | ||
615 | #if LCD_DEPTH > 1 | ||
616 | if(signy == 1) | ||
617 | if(isgoal) | ||
618 | rb->lcd_set_foreground(COLOR_GOAL); | ||
619 | else if(isvisited) | ||
620 | rb->lcd_set_foreground(COLOR_VISITED); | ||
621 | else | ||
622 | rb->lcd_set_foreground(COLOR_GROUND); | ||
623 | else | ||
624 | rb->lcd_set_foreground(COLOR_SKY); | ||
625 | #endif | ||
626 | |||
627 | signx = 1; | ||
628 | |||
629 | while(signx >= -1) | ||
630 | { | ||
631 | for(i = fx; i > bx; i--) { | ||
632 | #if LCD_DEPTH == 1 /* if unvisited floor draw pattern, otherwise solid */ | ||
633 | if (signy!=1 || isgoal || isvisited || (CX + signx * i/2) & 1) | ||
634 | #endif | ||
635 | rb->lcd_vline(CX + signx * i/2, | ||
636 | CY + signy * fy/2, | ||
637 | CY + signy * fy/2 | ||
638 | + signy * tan_n | ||
639 | * (i - fx)/2 / tan_d); | ||
640 | } | ||
641 | signx-=2; | ||
642 | } | ||
643 | signy-=2; | ||
644 | } | ||
645 | } | ||
646 | |||
647 | void draw_hall_crnr(int fx, int fy, int bx, int by, | ||
648 | bool isleft, bool isvisited, bool isgoal) | ||
649 | { | ||
650 | #if LCD_DEPTH > 1 | ||
651 | rb->lcd_set_foreground(COLOR_SKY); | ||
652 | #endif | ||
653 | if(isleft) | ||
654 | rb->lcd_fillrect(CX - fx/2, CY - fy/2, | ||
655 | (fx - bx)/2 + 1, (fy - by)/2); | ||
656 | else | ||
657 | rb->lcd_fillrect(CX + bx/2, CY - fy/2, | ||
658 | (fx - bx)/2 + 1, (fy - by)/2); | ||
659 | |||
660 | #if LCD_DEPTH > 1 | ||
661 | if(isgoal) | ||
662 | rb->lcd_set_foreground(COLOR_GOAL); | ||
663 | else if(isvisited) | ||
664 | rb->lcd_set_foreground(COLOR_VISITED); | ||
665 | else | ||
666 | rb->lcd_set_foreground(COLOR_GROUND); | ||
667 | |||
668 | if(isleft) | ||
669 | rb->lcd_fillrect(CX - fx/2, CY + by/2, | ||
670 | (fx - bx)/2 + 1, (fy - by)/2); | ||
671 | else | ||
672 | rb->lcd_fillrect(CX + bx/2, CY + by/2, | ||
673 | (fx - bx)/2 + 1, (fy - by)/2); | ||
674 | #else /* LCD_DEPTH == 1 */ | ||
675 | /* if unvisited floor draw pattern, otherwise solid */ | ||
676 | if(isleft) | ||
677 | for (int x = CX-fx/2; x <= CX-bx/2; x++) { | ||
678 | if (isgoal || isvisited || x & 1) | ||
679 | rb->lcd_vline(x, CY + by/2, CY + fy/2); | ||
680 | } | ||
681 | else | ||
682 | for (int x = CX+bx/2; x <= CX+fx/2; x++) { | ||
683 | if (isgoal || isvisited || x & 1) | ||
684 | rb->lcd_vline(x, CY + by/2, CY + fy/2); | ||
685 | } | ||
686 | #endif | ||
687 | } | ||
688 | |||
689 | void draw_center_sq(int fy, int bx, int by, bool isvisited, bool isgoal, | ||
690 | bool isfront, int chr) | ||
691 | { | ||
692 | chr = chr - '0'; /* get the integer value */ | ||
693 | |||
694 | #if LCD_DEPTH > 1 | ||
695 | rb->lcd_set_foreground(COLOR_SKY); | ||
696 | #endif | ||
697 | rb->lcd_fillrect(CX - bx/2, CY - fy/2, bx, (fy - by)/2); | ||
698 | |||
699 | #if LCD_DEPTH > 1 | ||
700 | if(isgoal) | ||
701 | rb->lcd_set_foreground(COLOR_GOAL); | ||
702 | else if(isvisited) | ||
703 | rb->lcd_set_foreground(COLOR_VISITED); | ||
704 | else | ||
705 | rb->lcd_set_foreground(COLOR_GROUND); | ||
706 | rb->lcd_fillrect(CX - bx/2, CY + by/2, bx, (fy - by)/2 + 1); | ||
707 | #else | ||
708 | /* if unvisited floor draw pattern, otherwise solid */ | ||
709 | for (int x = CX-bx/2; x <= CX+bx/2; x++) { | ||
710 | if (isgoal || isvisited || x & 1) | ||
711 | rb->lcd_vline(x, CY + by/2, CY + fy/2 + 1); | ||
712 | } | ||
713 | #endif | ||
714 | |||
715 | if(isvisited && chr >= 0 && chr <= 3) | ||
716 | { | ||
717 | #if LCD_DEPTH > 1 | ||
718 | rb->lcd_set_foreground(COLOR_MARK); | ||
719 | #else | ||
720 | rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
721 | #endif | ||
722 | if(isfront) | ||
723 | { /* cell is marked in front, draw arrow */ | ||
724 | if (chr == ((int)(pdir) + 3) % 4) | ||
725 | draw_pointer(DIR_LEFT, false); | ||
726 | else if (chr == ((int)(pdir) + 1) % 4) | ||
727 | draw_pointer(DIR_RIGHT, false); | ||
728 | else if (chr == ((int)(pdir) + 2) % 4) | ||
729 | draw_pointer(DIR_DOWN, false); | ||
730 | else /* same direction */ | ||
731 | draw_pointer(DIR_UP, false); | ||
732 | } | ||
733 | else /* cell is marked but is in distance */ | ||
734 | rb->lcd_fillrect(CX, CY + (fy + by)/4, 2, 2); | ||
735 | #if LCD_DEPTH == 1 | ||
736 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
737 | #endif | ||
738 | } | ||
739 | } | ||
740 | |||
741 | bool is_visited(char cell) | ||
742 | { | ||
743 | if (cell - '0' >= 0 && cell - '0' <= 3) | ||
744 | return true; | ||
745 | else if (cell == VISITED) | ||
746 | return true; | ||
747 | else | ||
748 | return false; | ||
749 | } | ||
750 | |||
751 | void graphic_view(void) | ||
752 | { | ||
753 | int dist; | ||
754 | int x, y, dx, dy; | ||
755 | int a, l, r; /* is block? ahead/left/right */ | ||
756 | bool g, gl, gr; /* ground visted? under/left/right */ | ||
757 | bool e, el, er; /* is goal? under/left/right */ | ||
758 | int tan_n, tan_d; /* tangent numerator/denominator */ | ||
759 | |||
760 | dx = dirtab[(int)pdir].x; | ||
761 | dy = dirtab[(int)pdir].y; | ||
762 | |||
763 | for (dist = 1; dist < depth; dist++) | ||
764 | if (at(py + dy * dist, px + dx * dist) == BLOCK) | ||
765 | break; | ||
766 | |||
767 | if (!show_map) | ||
768 | { | ||
769 | clearmap(umap); | ||
770 | copyumap(gy, gx, 1); | ||
771 | } | ||
772 | |||
773 | #if LCD_DEPTH == 1 | ||
774 | clearscreen(); | ||
775 | #endif | ||
776 | |||
777 | while (--dist >= 0) | ||
778 | { | ||
779 | x = px + dx * dist; | ||
780 | y = py + dy * dist; | ||
781 | |||
782 | /* ground */ | ||
783 | g = is_visited(at(y, x)); | ||
784 | gl = is_visited(at(y - dx, x + dy)); | ||
785 | gr = is_visited(at(y + dx, x - dy)); | ||
786 | /* goal/end */ | ||
787 | e = at(y, x) == GOAL; | ||
788 | el = at(y - dx, x + dy) == GOAL; | ||
789 | er = at(y + dx, x - dy) == GOAL; | ||
790 | /* ahead */ | ||
791 | a = at(y + dy, x + dx) == BLOCK; | ||
792 | /* to the left */ | ||
793 | l = at(y - dx, x + dy) == BLOCK; | ||
794 | /* to the right */ | ||
795 | r = at(y + dx, x - dy) == BLOCK; | ||
796 | |||
797 | tan_n = crd_y[dist] - crd_y[dist+1]; | ||
798 | tan_d = crd_x[dist] - crd_x[dist+1]; | ||
799 | |||
800 | if (a) | ||
801 | draw_end_wall(crd_x[dist+1], crd_y[dist+1]); | ||
802 | if (l) | ||
803 | { | ||
804 | draw_side(crd_x[dist], crd_x[dist+1], | ||
805 | crd_y[dist+1], tan_n, tan_d, true); | ||
806 | } | ||
807 | else | ||
808 | { | ||
809 | draw_hall(crd_x[dist], crd_x[dist+1], | ||
810 | crd_y[dist+1], true); | ||
811 | draw_hall_crnr(crd_x[dist], crd_y[dist], crd_x[dist+1], | ||
812 | crd_y[dist+1], true, gl, el); | ||
813 | } | ||
814 | if (r) | ||
815 | { | ||
816 | draw_side(crd_x[dist], crd_x[dist+1], | ||
817 | crd_y[dist+1], tan_n, tan_d, false); | ||
818 | } | ||
819 | else | ||
820 | { | ||
821 | draw_hall(crd_x[dist], crd_x[dist+1], | ||
822 | crd_y[dist+1], false); | ||
823 | draw_hall_crnr(crd_x[dist], crd_y[dist], | ||
824 | crd_x[dist+1], crd_y[dist+1], false, gr, er); | ||
825 | } | ||
826 | |||
827 | draw_center_sq(crd_y[dist], crd_x[dist+1], crd_y[dist+1], | ||
828 | g, e, dist==0, (int)(at(y, x))); | ||
829 | draw_side_tri(crd_x[dist], crd_y[dist], | ||
830 | crd_x[dist+1], tan_n, tan_d, g, e); | ||
831 | |||
832 | copyumap(y + dy, x + dx, 0); /* ahead */ | ||
833 | copyumap(y, x, 1); /* here */ | ||
834 | copyumap(y - dx, x + dy, 0); /* left */ | ||
835 | copyumap(y + dx, x - dy, 0); /* right */ | ||
836 | if (!l) | ||
837 | copyumap(y - dx + dy, x + dy + dx, 0); /* lft ahead */ | ||
838 | if (!r) | ||
839 | copyumap(y + dx + dy, x - dy + dx, 0); /* rt ahead */ | ||
840 | } | ||
841 | if (compass) | ||
842 | draw_pointer(pdir, true); | ||
843 | } | ||
844 | |||
845 | void win(void) | ||
846 | { | ||
847 | /* | ||
848 | int i; | ||
849 | char amazed[8] = "amazing!"; | ||
850 | char newton; | ||
851 | |||
852 | for (i=0; i <= 8; i++) | ||
853 | { | ||
854 | newton = amazed[i]; | ||
855 | map_write(msg, 0, i + 31, newton); | ||
856 | } | ||
857 | */ | ||
858 | won++; | ||
859 | showmap(); | ||
860 | show_map = 1; | ||
861 | } | ||
862 | |||
863 | |||
864 | /* Try to move the player in the direction given */ | ||
865 | void trymove(enum dir dir) | ||
866 | { | ||
867 | int nx, ny; | ||
868 | |||
869 | ny = py + dirtab[(int)dir].y; | ||
870 | nx = px + dirtab[(int)dir].x; | ||
871 | |||
872 | if (at(ny, nx) == BLOCK) | ||
873 | { | ||
874 | graphic_view(); | ||
875 | return; | ||
876 | } | ||
877 | |||
878 | if (at(ny, nx) == GOAL) | ||
879 | win(); | ||
880 | |||
881 | mappmove(ny, nx, pdir); | ||
882 | if (remember_visited && punder == SPACE) | ||
883 | punder = VISITED; | ||
884 | graphic_view(); | ||
885 | } | ||
886 | |||
887 | void walkleft(void) | ||
888 | { | ||
889 | int a, l; | ||
890 | int dx, dy; | ||
891 | int owon = won; | ||
892 | |||
893 | while (1) | ||
894 | { | ||
895 | int input = pluginlib_getaction(TIMEOUT_NOBLOCK, plugin_contexts, | ||
896 | ARRAYLEN(plugin_contexts)); | ||
897 | if(input==PLA_CANCEL || input==PLA_EXIT) | ||
898 | { | ||
899 | return; | ||
900 | } | ||
901 | rb->lcd_update(); | ||
902 | if (won != owon) | ||
903 | { | ||
904 | break; | ||
905 | } | ||
906 | |||
907 | dx = dirtab[(int)pdir].x; | ||
908 | dy = dirtab[(int)pdir].y; | ||
909 | |||
910 | /* ahead */ | ||
911 | a = at(py + dy, px + dx) == BLOCK; | ||
912 | /* to the left */ | ||
913 | l = at(py - dx, px + dy) == BLOCK; | ||
914 | |||
915 | if (!l) | ||
916 | { | ||
917 | mappmove(py, px, LEFT_OF(pdir)); | ||
918 | graphic_view(); | ||
919 | rb->sleep(2); | ||
920 | trymove(pdir); | ||
921 | continue; | ||
922 | } | ||
923 | if (a) | ||
924 | { | ||
925 | mappmove(py, px, RIGHT_OF(pdir)); | ||
926 | graphic_view(); | ||
927 | continue; | ||
928 | } | ||
929 | trymove(pdir); | ||
930 | rb->yield(); | ||
931 | } | ||
932 | } | ||
933 | |||
934 | void draw_tile(int index, int x, int y) | ||
935 | { | ||
936 | if (use_large_tiles == 1) | ||
937 | rb->lcd_bitmap_part (amaze_tiles_large, 0, index * TILESIZE_LARGE, | ||
938 | TILESIZE_LARGE, x * TILESIZE_LARGE, y * TILESIZE_LARGE, | ||
939 | TILESIZE_LARGE, TILESIZE_LARGE); | ||
940 | else | ||
941 | rb->lcd_bitmap_part (amaze_tiles_small, 0, index * TILESIZE_SMALL, | ||
942 | TILESIZE_SMALL, x * TILESIZE_SMALL, y * TILESIZE_SMALL, | ||
943 | TILESIZE_SMALL, TILESIZE_SMALL); | ||
944 | } | ||
945 | |||
946 | void draw_tile_map(int xmin, int xmax, int ymin, int ymax) | ||
947 | { | ||
948 | int x,y; | ||
949 | char map_unit; | ||
950 | int tdex = 7; /* tile index */ | ||
951 | |||
952 | enum tile_index | ||
953 | { t_down=0, t_right=1, t_up=2, t_left=3, t_visited=4, | ||
954 | t_obspace=5, t_goal=6, t_block=7, t_space=8, t_start=9 }; | ||
955 | |||
956 | for(y = ymin; y <= ymax; y++) | ||
957 | for(x = xmin; x <= xmax; x++) | ||
958 | { | ||
959 | |||
960 | map_unit = map_read(umap, y, x); | ||
961 | |||
962 | switch (map_unit) | ||
963 | { | ||
964 | case VISITED: | ||
965 | case '0': case '1': case '2': case '3': | ||
966 | tdex = t_visited; | ||
967 | break; | ||
968 | case OBSPACE: | ||
969 | tdex = t_obspace; | ||
970 | break; | ||
971 | case START: | ||
972 | tdex = t_start; | ||
973 | break; | ||
974 | case GOAL: | ||
975 | tdex = t_goal; | ||
976 | break; | ||
977 | case SPACE: | ||
978 | tdex = t_space; | ||
979 | break; | ||
980 | case BLOCK: | ||
981 | tdex = t_block; | ||
982 | break; | ||
983 | } | ||
984 | draw_tile(tdex, x - xmin, y - ymin); | ||
985 | } | ||
986 | if(sx>=xmin && sx<=xmax && sy>=ymin && sy<=ymax) | ||
987 | { | ||
988 | x = sx; | ||
989 | y = sy; | ||
990 | draw_tile(t_start, x - xmin, y - ymin); | ||
991 | } | ||
992 | |||
993 | if(px>=xmin && px<=xmax && py>=ymin && py<=ymax) | ||
994 | { | ||
995 | x = px; | ||
996 | y = py; | ||
997 | draw_tile(pdir, x - xmin, y - ymin); | ||
998 | } | ||
999 | |||
1000 | rb->lcd_update(); | ||
1001 | } | ||
1002 | |||
1003 | void check_map_bounds(int *xmin, int *xmax, int *ymin, int *ymax) | ||
1004 | { | ||
1005 | int maxx, maxy; | ||
1006 | |||
1007 | getmaxyx(&maxy, &maxx); | ||
1008 | |||
1009 | /* bounds check x */ | ||
1010 | if(*xmin < 0) | ||
1011 | { | ||
1012 | *xmax = *xmax - *xmin; | ||
1013 | *xmin = 0; | ||
1014 | } | ||
1015 | if(*xmax >= maxx) | ||
1016 | { | ||
1017 | *xmin = *xmin - *xmax + maxx - 1; | ||
1018 | *xmax = maxx - 1; | ||
1019 | } | ||
1020 | |||
1021 | /* bounds check y */ | ||
1022 | if(*ymin < 0) | ||
1023 | { | ||
1024 | *ymax = *ymax - *ymin; | ||
1025 | *ymin = 0; | ||
1026 | } | ||
1027 | if(*ymax >= maxy) | ||
1028 | { | ||
1029 | *ymin = *ymin - *ymax + maxy - 1; | ||
1030 | *ymax = maxy - 1; | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | void calc_map_size(int *xmin, int *xmax, int *ymin, int *ymax) | ||
1035 | { | ||
1036 | int tile_size; /* runtime option */ | ||
1037 | int vx, vy; /* maxx, maxy of view */ | ||
1038 | int midx, midy; /* midpoint x, y of view */ | ||
1039 | int maxx, maxy; /* maxx, maxy of map */ | ||
1040 | |||
1041 | getmaxyx(&maxy, &maxx); | ||
1042 | |||
1043 | if (use_large_tiles == 1) | ||
1044 | tile_size = TILESIZE_LARGE; | ||
1045 | else | ||
1046 | tile_size = TILESIZE_SMALL; | ||
1047 | |||
1048 | vx = LCD_WIDTH / tile_size; | ||
1049 | if (vx > maxx) | ||
1050 | vx = maxx; | ||
1051 | vy = LCD_HEIGHT / tile_size; | ||
1052 | if (vy > maxy) | ||
1053 | vy = maxy; | ||
1054 | |||
1055 | midx = vx / 2; | ||
1056 | midy = vy / 2; | ||
1057 | |||
1058 | *xmin = px - midx; | ||
1059 | if(vx % 2 == 0) | ||
1060 | *xmax = px + midx - 1; | ||
1061 | else | ||
1062 | *xmax = px + midx; | ||
1063 | |||
1064 | *ymin = py - midy; | ||
1065 | if(vy % 2 == 0) | ||
1066 | *ymax = py + midy - 1; | ||
1067 | else | ||
1068 | *ymax = py + midy; | ||
1069 | |||
1070 | } | ||
1071 | |||
1072 | |||
1073 | void draw_portion_map(void) | ||
1074 | { | ||
1075 | int xmin, xmax, ymin, ymax; /* coords of map corners */ | ||
1076 | bool quit_map; | ||
1077 | int input; | ||
1078 | |||
1079 | clearscreen(); | ||
1080 | |||
1081 | calc_map_size(&xmin, &xmax, &ymin, &ymax); | ||
1082 | |||
1083 | quit_map = false; | ||
1084 | |||
1085 | while (!quit_map) | ||
1086 | { | ||
1087 | check_map_bounds(&xmin, &xmax, &ymin, &ymax); | ||
1088 | draw_tile_map(xmin, xmax, ymin, ymax); | ||
1089 | |||
1090 | input = pluginlib_getaction(TIMEOUT_BLOCK, plugin_contexts, | ||
1091 | ARRAYLEN(plugin_contexts)); | ||
1092 | |||
1093 | switch(input) | ||
1094 | { | ||
1095 | case PLA_CANCEL: | ||
1096 | case PLA_EXIT: | ||
1097 | quit_map = true; | ||
1098 | break; | ||
1099 | case PLA_UP: | ||
1100 | case PLA_UP_REPEAT: | ||
1101 | ymin--; | ||
1102 | ymax--; | ||
1103 | break; | ||
1104 | case PLA_DOWN: | ||
1105 | case PLA_DOWN_REPEAT: | ||
1106 | ymin++; | ||
1107 | ymax++; | ||
1108 | break; | ||
1109 | case PLA_LEFT: | ||
1110 | case PLA_LEFT_REPEAT: | ||
1111 | xmin--; | ||
1112 | xmax--; | ||
1113 | break; | ||
1114 | case PLA_RIGHT: | ||
1115 | case PLA_RIGHT_REPEAT: | ||
1116 | xmin++; | ||
1117 | xmax++; | ||
1118 | break; | ||
1119 | default: | ||
1120 | break; | ||
1121 | } | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | bool load_map(char *filename, char *amap) | ||
1126 | { | ||
1127 | int fd; | ||
1128 | int x,y; | ||
1129 | int maxxy; | ||
1130 | size_t n; | ||
1131 | char newton = BLOCK; | ||
1132 | char map_size[2]; | ||
1133 | |||
1134 | /* load a map */ | ||
1135 | fd = rb->open(filename, O_RDONLY); | ||
1136 | if (fd < 0) | ||
1137 | { | ||
1138 | LOGF("Invalid map file: %s\n", filename); | ||
1139 | return false; | ||
1140 | } | ||
1141 | |||
1142 | n = rb->read(fd, map_size, sizeof(map_size)); | ||
1143 | if (n <= 0) | ||
1144 | { | ||
1145 | LOGF("Invalid map size."); | ||
1146 | return false; | ||
1147 | } | ||
1148 | |||
1149 | maze_size = (int)map_size[0] - 48; | ||
1150 | maxxy = MAP_CONST * (maze_size + 1); | ||
1151 | char line[maxxy + 1]; | ||
1152 | |||
1153 | for(y=0; y < maxxy ; y++) | ||
1154 | { | ||
1155 | n = rb->read(fd, line, sizeof(line)); | ||
1156 | if (n <= 0) | ||
1157 | { | ||
1158 | return false; | ||
1159 | } | ||
1160 | for(x=0; x < maxxy+1; x++) | ||
1161 | { | ||
1162 | switch(line[x]) | ||
1163 | { | ||
1164 | case '\n': | ||
1165 | break; | ||
1166 | case '0': case '1': case '2': case '3': | ||
1167 | newton = line[x]; | ||
1168 | break; | ||
1169 | case START: | ||
1170 | sy = y; | ||
1171 | sx = x; | ||
1172 | newton = START; | ||
1173 | break; | ||
1174 | case SPACE: | ||
1175 | case BLOCK: | ||
1176 | case OBSPACE: | ||
1177 | newton = line[x]; | ||
1178 | break; | ||
1179 | case GOAL: | ||
1180 | newton = GOAL; | ||
1181 | gy = y; | ||
1182 | gx = x; | ||
1183 | break; | ||
1184 | case A_DOWN: case A_LEFT: case A_UP: case A_RIGHT: | ||
1185 | py = y; | ||
1186 | px = x; | ||
1187 | switch(line[x]) | ||
1188 | { | ||
1189 | case A_DOWN: | ||
1190 | pdir = DIR_DOWN; | ||
1191 | break; | ||
1192 | case A_LEFT: | ||
1193 | pdir = DIR_LEFT; | ||
1194 | break; | ||
1195 | case A_UP: | ||
1196 | pdir = DIR_UP; | ||
1197 | break; | ||
1198 | case A_RIGHT: | ||
1199 | pdir = DIR_RIGHT; | ||
1200 | break; | ||
1201 | } | ||
1202 | /* FALLTHROUGH */ | ||
1203 | case VISITED: | ||
1204 | newton = VISITED; | ||
1205 | break; | ||
1206 | } | ||
1207 | if (line[x] != '\n') | ||
1208 | map_write(amap, y, x, newton); | ||
1209 | } | ||
1210 | } | ||
1211 | rb->close(fd); | ||
1212 | rb->remove(filename); | ||
1213 | return true; | ||
1214 | } | ||
1215 | |||
1216 | bool load_game(void) | ||
1217 | { | ||
1218 | if (load_map(UMAP_FILE, umap) && load_map(MAP_FILE, map)) | ||
1219 | return true; | ||
1220 | else | ||
1221 | return false; | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | bool save_map(char *filename, char *amap) | ||
1226 | { | ||
1227 | int x,y; | ||
1228 | int maxy, maxx; | ||
1229 | char map_unit; | ||
1230 | int fd; | ||
1231 | int line_len = (maze_size + 1) * MAP_CONST + 1; | ||
1232 | char line[line_len]; | ||
1233 | char map_size[2] = | ||
1234 | {'0','\n'}; | ||
1235 | |||
1236 | line[line_len - 1] = '\n'; /* last cell is a linefeed */ | ||
1237 | map_size[0] = (char)(maze_size + 48); | ||
1238 | |||
1239 | if ((fd = rb->open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) | ||
1240 | return false; | ||
1241 | |||
1242 | rb->write(fd, map_size, 2); | ||
1243 | |||
1244 | getmaxyx(&maxy, &maxx); | ||
1245 | |||
1246 | for(y=0; y < maxy; y++) | ||
1247 | { | ||
1248 | for (x=0; x < maxx; x++) | ||
1249 | { | ||
1250 | map_unit = map_read(amap, y, x); | ||
1251 | |||
1252 | if(y == py && x == px) | ||
1253 | line[x] = ptab[_TOI(pdir)]; | ||
1254 | else if(y == sy && x == sx) | ||
1255 | line[x] = START; | ||
1256 | else | ||
1257 | line[x] = map_unit; | ||
1258 | } | ||
1259 | rb->write(fd, line, line_len); | ||
1260 | } | ||
1261 | rb->close(fd); | ||
1262 | |||
1263 | return true; | ||
1264 | } | ||
1265 | |||
1266 | bool save_game(void) | ||
1267 | { | ||
1268 | if (save_map(UMAP_FILE, umap) && save_map(MAP_FILE, map)) | ||
1269 | return true; | ||
1270 | else | ||
1271 | return false; | ||
1272 | } | ||
1273 | |||
1274 | |||
1275 | bool ingame; | ||
1276 | bool save_prefs(char *filename); | ||
1277 | |||
1278 | static int menu_cb(int action, const struct menu_item_ex *this_item, | ||
1279 | struct gui_synclist *this_list) | ||
1280 | { | ||
1281 | (void)this_list; | ||
1282 | |||
1283 | int idx=((intptr_t)this_item); | ||
1284 | if (action==ACTION_REQUEST_MENUITEM) { | ||
1285 | if (ingame) { | ||
1286 | if (idx==2) | ||
1287 | return ACTION_EXIT_MENUITEM; | ||
1288 | } | ||
1289 | else { /* !ingame */ | ||
1290 | if (idx==3 || idx==8) | ||
1291 | return ACTION_EXIT_MENUITEM; | ||
1292 | if (!loaded && (idx==0 || idx==9)) | ||
1293 | return ACTION_EXIT_MENUITEM; | ||
1294 | } | ||
1295 | } | ||
1296 | return action; | ||
1297 | } | ||
1298 | |||
1299 | int menu(void) | ||
1300 | { | ||
1301 | bool exit_menu = false; | ||
1302 | int selection = 0, result = 0, status = 1; | ||
1303 | |||
1304 | MENUITEM_STRINGLIST(menu, ID2P(LANG_AMAZE_MENU), menu_cb, | ||
1305 | ID2P(LANG_CHESSBOX_MENU_RESUME_GAME), | ||
1306 | ID2P(LANG_CHESSBOX_MENU_NEW_GAME), | ||
1307 | ID2P(LANG_SET_MAZE_SIZE), | ||
1308 | ID2P(LANG_VIEW_MAP), | ||
1309 | ID2P(LANG_SHOW_COMPASS), | ||
1310 | ID2P(LANG_SHOW_MAP), | ||
1311 | ID2P(LANG_REMEMBER_PATH), | ||
1312 | ID2P(LANG_USE_LARGE_TILES), | ||
1313 | ID2P(LANG_SHOW_SOLUTION), | ||
1314 | ID2P(LANG_QUIT_WITHOUT_SAVING), | ||
1315 | ID2P(LANG_MENU_QUIT) | ||
1316 | ); | ||
1317 | |||
1318 | clearscreen(); | ||
1319 | |||
1320 | while(!exit_menu) | ||
1321 | { | ||
1322 | result = rb->do_menu(&menu, &selection, NULL, false); | ||
1323 | switch(result) | ||
1324 | { | ||
1325 | case 0: /* resume */ | ||
1326 | exit_menu = true; | ||
1327 | if (!ingame) { | ||
1328 | save_prefs(PREF_FILE); | ||
1329 | } | ||
1330 | break; | ||
1331 | case 1: /* new game */ | ||
1332 | exit_menu = true; | ||
1333 | if (ingame) | ||
1334 | { | ||
1335 | rb->splash(0, ID2P(LANG_GENERATING_MAZE)); | ||
1336 | clearmap(umap); | ||
1337 | makemaze(); | ||
1338 | |||
1339 | /* Show where the goal is */ | ||
1340 | copyumap(gy, gx, 1); | ||
1341 | rb->lcd_update(); | ||
1342 | |||
1343 | mappmove(py, px, pdir); | ||
1344 | |||
1345 | if (remember_visited) | ||
1346 | punder = VISITED; | ||
1347 | else | ||
1348 | punder = SPACE; | ||
1349 | } | ||
1350 | else { /* !ingame */ | ||
1351 | loaded=false; | ||
1352 | save_prefs(PREF_FILE); | ||
1353 | } | ||
1354 | break; | ||
1355 | case 2: /* Set maze size */ | ||
1356 | { | ||
1357 | int old_size = maze_size; | ||
1358 | rb->set_option(rb->str(LANG_SET_MAZE_SIZE), &maze_size, RB_INT, | ||
1359 | mazesize_text, 4, NULL); | ||
1360 | if (maze_size != old_size) | ||
1361 | loaded = false; | ||
1362 | } | ||
1363 | break; | ||
1364 | case 3: /* View map */ | ||
1365 | exit_menu = true; | ||
1366 | draw_portion_map(); | ||
1367 | break; | ||
1368 | case 4: /* Show compass option */ | ||
1369 | rb->set_option(rb->str(LANG_SHOW_COMPASS), &compass, RB_BOOL, | ||
1370 | noyes_text, 2, NULL); | ||
1371 | break; | ||
1372 | case 5: /* Show Map option */ | ||
1373 | rb->set_option(rb->str(LANG_SHOW_MAP), &show_map, RB_BOOL, | ||
1374 | noyes_text, 2, NULL); | ||
1375 | break; | ||
1376 | case 6: /* Remember Path option */ | ||
1377 | rb->set_option(rb->str(LANG_REMEMBER_PATH), &remember_visited, RB_BOOL, | ||
1378 | noyes_text, 2, NULL); | ||
1379 | break; | ||
1380 | case 7: /* Tilesize option */ | ||
1381 | rb->set_option(rb->str(LANG_USE_LARGE_TILES), &use_large_tiles, RB_BOOL, | ||
1382 | noyes_text, 2, NULL); | ||
1383 | break; | ||
1384 | case 8: /* solver */ | ||
1385 | exit_menu = true; | ||
1386 | cheated++; | ||
1387 | walkleft(); | ||
1388 | break; | ||
1389 | case 9: /* quit w/o saving */ | ||
1390 | exit_menu = true; | ||
1391 | status = 0; | ||
1392 | break; | ||
1393 | case 10: /* save+quit */ | ||
1394 | exit_menu = true; | ||
1395 | if (ingame) { | ||
1396 | if (save_game()) | ||
1397 | status = 0; | ||
1398 | else | ||
1399 | rb->splash(HZ*3, ID2P(LANG_ERROR_WRITING_CONFIG)); | ||
1400 | } | ||
1401 | else { | ||
1402 | if(loaded) | ||
1403 | save_game(); | ||
1404 | status = 0; | ||
1405 | } | ||
1406 | break; | ||
1407 | } | ||
1408 | } | ||
1409 | return status; | ||
1410 | } | ||
1411 | |||
1412 | int amaze(void) | ||
1413 | { | ||
1414 | int quitting; | ||
1415 | int i; | ||
1416 | int input; | ||
1417 | |||
1418 | clearscreen(); | ||
1419 | rb->lcd_setfont(FONT_SYSFIXED); | ||
1420 | if(!loaded) | ||
1421 | rb->splash(0, ID2P(LANG_GENERATING_MAZE)); | ||
1422 | |||
1423 | crd_x[0] = LCD_WIDTH + 1; | ||
1424 | crd_y[0] = LCD_HEIGHT + 1; | ||
1425 | for (depth=1; depth < MAX_DEPTH + 1; depth++) | ||
1426 | { | ||
1427 | crd_x[depth] = crd_x[depth-1]*2/3; | ||
1428 | if(crd_x[depth] % 2 != 0) crd_x[depth]++; | ||
1429 | crd_y[depth] = crd_y[depth-1]*2/3; | ||
1430 | if(crd_y[depth] % 2 != 0) crd_y[depth]++; | ||
1431 | if (crd_x[depth]==crd_x[depth-1] || crd_y[depth]==crd_y[depth-1]) | ||
1432 | break; | ||
1433 | } | ||
1434 | --depth; | ||
1435 | |||
1436 | if (!loaded) | ||
1437 | { | ||
1438 | clearmap(umap); | ||
1439 | makemaze(); | ||
1440 | } | ||
1441 | |||
1442 | /* Show where the goal is */ | ||
1443 | |||
1444 | copyumap(gy, gx, 1); | ||
1445 | |||
1446 | rb->lcd_update(); | ||
1447 | |||
1448 | quitting = 0; | ||
1449 | |||
1450 | mappmove(py, px, pdir); | ||
1451 | |||
1452 | if (remember_visited) | ||
1453 | punder = VISITED; | ||
1454 | else | ||
1455 | punder = SPACE; | ||
1456 | |||
1457 | clearscreen(); | ||
1458 | graphic_view(); | ||
1459 | |||
1460 | while (!quitting && !won) | ||
1461 | { | ||
1462 | |||
1463 | rb->lcd_update(); | ||
1464 | |||
1465 | input = pluginlib_getaction(TIMEOUT_BLOCK, plugin_contexts, | ||
1466 | ARRAYLEN(plugin_contexts)); | ||
1467 | |||
1468 | switch (input) | ||
1469 | { | ||
1470 | case PLA_CANCEL: | ||
1471 | case PLA_EXIT: | ||
1472 | i = menu(); | ||
1473 | rb->lcd_setfont(FONT_SYSFIXED); | ||
1474 | clearscreen(); | ||
1475 | graphic_view(); | ||
1476 | |||
1477 | switch (i) | ||
1478 | { | ||
1479 | case 0: | ||
1480 | quitting = 1; | ||
1481 | break; | ||
1482 | case 1: | ||
1483 | break; | ||
1484 | case 2: | ||
1485 | return 0; | ||
1486 | break; | ||
1487 | } | ||
1488 | break; | ||
1489 | case PLA_UP: | ||
1490 | case PLA_UP_REPEAT: | ||
1491 | trymove(pdir); | ||
1492 | break; | ||
1493 | case PLA_DOWN: | ||
1494 | case PLA_DOWN_REPEAT: | ||
1495 | trymove(REVERSE_OF(pdir)); | ||
1496 | break; | ||
1497 | case PLA_LEFT: | ||
1498 | mappmove(py, px, LEFT_OF(pdir)); | ||
1499 | graphic_view(); | ||
1500 | break; | ||
1501 | case PLA_RIGHT: | ||
1502 | mappmove(py, px, RIGHT_OF(pdir)); | ||
1503 | graphic_view(); | ||
1504 | break; | ||
1505 | case PLA_SELECT: | ||
1506 | if (punder==SPACE || punder==VISITED) | ||
1507 | { /* mark ground */ | ||
1508 | punder = pdir + '0'; | ||
1509 | } | ||
1510 | else | ||
1511 | { /* clear mark */ | ||
1512 | if (remember_visited) | ||
1513 | punder = VISITED; | ||
1514 | else | ||
1515 | punder = SPACE; | ||
1516 | } | ||
1517 | graphic_view(); | ||
1518 | break; | ||
1519 | } | ||
1520 | } | ||
1521 | |||
1522 | rb->lcd_update(); | ||
1523 | //graphic_view(); | ||
1524 | if (won) | ||
1525 | { | ||
1526 | won = false; /* reset boolean */ | ||
1527 | if (cheated) | ||
1528 | { | ||
1529 | rb->splash(HZ*2, ID2P(LANG_YOU_CHEATED)); | ||
1530 | return 0; | ||
1531 | } | ||
1532 | rb->splash(HZ*2, ID2P(LANG_YOU_WIN)); | ||
1533 | return 1; | ||
1534 | } | ||
1535 | else | ||
1536 | { | ||
1537 | return 0; | ||
1538 | } | ||
1539 | } | ||
1540 | |||
1541 | bool save_prefs(char *filename) | ||
1542 | { | ||
1543 | int fd; | ||
1544 | char ms[2] = { (char)(maze_size) + '0', '\n' }; | ||
1545 | char sm[2] = { (char)(show_map) + '0', '\n' }; | ||
1546 | char rv[2] = { (char)(remember_visited) + '0', '\n' }; | ||
1547 | char lt[2] = { (char)(use_large_tiles) + '0', '\n' }; | ||
1548 | |||
1549 | fd = rb->open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); | ||
1550 | if(fd >= 0) | ||
1551 | { | ||
1552 | rb->write(fd, ms, 2); | ||
1553 | rb->write(fd, sm, 2); | ||
1554 | rb->write(fd, rv, 2); | ||
1555 | rb->write(fd, lt, 2); | ||
1556 | } | ||
1557 | else | ||
1558 | { | ||
1559 | rb->splash(HZ, ID2P(LANG_ERROR_WRITING_CONFIG)); | ||
1560 | return false; | ||
1561 | } | ||
1562 | rb->close(fd); | ||
1563 | return true; | ||
1564 | } | ||
1565 | |||
1566 | bool load_prefs(char *filename) | ||
1567 | { | ||
1568 | int fd; | ||
1569 | char instr[2]; | ||
1570 | |||
1571 | fd = rb->open(filename, O_RDONLY); | ||
1572 | if (fd < 0) | ||
1573 | { | ||
1574 | LOGF("Invalid preferences file: %s\n", filename); | ||
1575 | return false; | ||
1576 | } | ||
1577 | |||
1578 | rb->read(fd, instr, sizeof(instr)); | ||
1579 | maze_size = (int)(instr[0] - '0'); | ||
1580 | rb->read(fd, instr, sizeof(instr)); | ||
1581 | show_map = (bool)(instr[0] - '0'); | ||
1582 | rb->read(fd, instr, sizeof(instr)); | ||
1583 | remember_visited = (bool)(instr[0] - '0'); | ||
1584 | rb->read(fd, instr, sizeof(instr)); | ||
1585 | use_large_tiles = (bool)(instr[0] - '0'); | ||
1586 | rb->close(fd); | ||
1587 | |||
1588 | return true; | ||
1589 | } | ||
1590 | |||
1591 | enum plugin_status plugin_start(const void *parameter) | ||
1592 | { | ||
1593 | (void) parameter; | ||
1594 | int ret; | ||
1595 | |||
1596 | rb->srand(*rb->current_tick); | ||
1597 | |||
1598 | /* hard-code in program default options */ | ||
1599 | show_map=1; | ||
1600 | remember_visited=1; | ||
1601 | use_large_tiles=1; | ||
1602 | maze_size=1; | ||
1603 | |||
1604 | loaded=load_game(); | ||
1605 | |||
1606 | /* let's go, gentlemen, we have some work to do */ | ||
1607 | #if LCD_DEPTH > 1 | ||
1608 | rb->lcd_set_backdrop(NULL); | ||
1609 | #endif | ||
1610 | ingame = false; | ||
1611 | ret = menu(); | ||
1612 | if (ret) { | ||
1613 | ingame = true; | ||
1614 | amaze(); | ||
1615 | } | ||
1616 | |||
1617 | rb->lcd_setfont(FONT_UI); | ||
1618 | |||
1619 | return PLUGIN_OK; | ||
1620 | } | ||
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index 814845dc5b..cfc9ebcf6a 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES | |||
@@ -27,6 +27,44 @@ _2048_background.56x56x24.bmp | |||
27 | #endif | 27 | #endif |
28 | #undef MIN | 28 | #undef MIN |
29 | 29 | ||
30 | /* amaze */ | ||
31 | #if defined(HAVE_LCD_COLOR) | ||
32 | #if LCD_WIDTH >= 220 || LCD_HEIGHT >= 220 | ||
33 | amaze_tiles_9.9x9x16.bmp | ||
34 | amaze_tiles_7.7x7x16.bmp | ||
35 | #elif LCD_WIDTH >= 160 || LCD_HEIGHT >= 160 | ||
36 | amaze_tiles_7.7x7x16.bmp | ||
37 | amaze_tiles_5.5x5x16.bmp | ||
38 | #else | ||
39 | amaze_tiles_5.5x5x16.bmp | ||
40 | amaze_tiles_3.3x3x16.bmp | ||
41 | #endif | ||
42 | |||
43 | #elif LCD_DEPTH > 1 | ||
44 | #if LCD_WIDTH >= 220 || LCD_HEIGHT >= 220 | ||
45 | amaze_tiles_9.9x9x2.bmp | ||
46 | amaze_tiles_7.7x7x2.bmp | ||
47 | #elif LCD_WIDTH >= 160 || LCD_HEIGHT >= 160 | ||
48 | amaze_tiles_7.7x7x2.bmp | ||
49 | amaze_tiles_5.5x5x2.bmp | ||
50 | #else | ||
51 | amaze_tiles_5.5x5x2.bmp | ||
52 | amaze_tiles_3.3x3x2.bmp | ||
53 | #endif | ||
54 | |||
55 | #else /* mono */ | ||
56 | #if LCD_WIDTH >= 220 || LCD_HEIGHT >= 220 | ||
57 | amaze_tiles_9.9x9x1.bmp | ||
58 | amaze_tiles_7.7x7x1.bmp | ||
59 | #elif LCD_WIDTH >= 160 || LCD_HEIGHT >= 160 | ||
60 | amaze_tiles_7.7x7x1.bmp | ||
61 | amaze_tiles_5.5x5x1.bmp | ||
62 | #else | ||
63 | amaze_tiles_5.5x5x1.bmp | ||
64 | amaze_tiles_3.3x3x1.bmp | ||
65 | #endif | ||
66 | #endif /* amaze */ | ||
67 | |||
30 | /* Brickmania */ | 68 | /* Brickmania */ |
31 | #ifdef HAVE_LCD_COLOR | 69 | #ifdef HAVE_LCD_COLOR |
32 | #if LCD_WIDTH >= 112 | 70 | #if LCD_WIDTH >= 112 |
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x1.bmp b/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x1.bmp new file mode 100644 index 0000000000..66418779de --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x1.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x16.bmp b/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x16.bmp new file mode 100644 index 0000000000..930d4c62fc --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x16.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x2.bmp b/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x2.bmp new file mode 100644 index 0000000000..504525b7f4 --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_3.3x3x2.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x1.bmp b/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x1.bmp new file mode 100644 index 0000000000..d5973cfc5e --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x1.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x16.bmp b/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x16.bmp new file mode 100644 index 0000000000..7ec316df6a --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x16.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x2.bmp b/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x2.bmp new file mode 100644 index 0000000000..e06075310e --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_5.5x5x2.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x1.bmp b/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x1.bmp new file mode 100644 index 0000000000..820f5a873b --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x1.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x16.bmp b/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x16.bmp new file mode 100644 index 0000000000..e9d6bc5086 --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x16.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x2.bmp b/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x2.bmp new file mode 100644 index 0000000000..2e8e76593b --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_7.7x7x2.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x1.bmp b/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x1.bmp new file mode 100644 index 0000000000..0f2212e7e5 --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x1.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x16.bmp b/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x16.bmp new file mode 100644 index 0000000000..0188dd9726 --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x16.bmp | |||
Binary files differ | |||
diff --git a/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x2.bmp b/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x2.bmp new file mode 100644 index 0000000000..f095368d30 --- /dev/null +++ b/apps/plugins/bitmaps/native/amaze_tiles_9.9x9x2.bmp | |||
Binary files differ | |||