Overview
Comment: | Start to implement the LEVELS table. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c4208ea17976e568bdd6c9eb1cc036f9 |
User & Date: | user on 2021-12-14 06:54:52 |
Other Links: | manifest | tags |
Context
2021-12-15
| ||
07:12 | Auto-update the LEVELS table when it is appropriate to do so. check-in: 656b937843 user: user tags: trunk | |
2021-12-14
| ||
06:54 | Start to implement the LEVELS table. check-in: c4208ea179 user: user tags: trunk | |
2021-12-10
| ||
00:00 | Implement the (Control) block to define a global control object. check-in: 665dcd24be user: user tags: trunk | |
Changes
Modified TODO from [8cd629c2b8] to [6e5666c132].
︙ | ︙ | |||
12 13 14 15 16 17 18 | * "Goto message" instruction (?) * Returning a class from COLLIDE/COLLIDEBY to transform * Coordinate input (may be suitable for some kind of games) * Possibility to define auto-generation levels mode * Editor * Mouse dragging * Level index editor | | | > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | * "Goto message" instruction (?) * Returning a class from COLLIDE/COLLIDEBY to transform * Coordinate input (may be suitable for some kind of games) * Possibility to define auto-generation levels mode * Editor * Mouse dragging * Level index editor * Table of contents for levels (partially implemented) * Can define your own columns * Update SOLVED (and SOLVABLE) column during playing * Cache invalidation in editor * Can be divisions by sections * Deal better with allowing to skip past corrupted levels * Picture editor/loading * Allowing more altimages * Batch insert multiple dependent image lumps * Puzzle set catalog format (using with internet; a separate program) * Inventory/replay hybrid view * Bookmarks |
︙ | ︙ |
Modified default.heromeshrc from [8008201b1c] to [cf39f14a84].
︙ | ︙ | |||
132 133 134 135 136 137 138 139 140 141 142 143 144 145 | ?.gameKey.alt.G: ^g ?.gameKey.alt.P: ^p ?.gameKey.alt.X: ^x ?.gameKey.alt.leftbracket: select 'rs',-5; ?.gameKey.alt.rightbracket: select 'rs',+5; ?.gameKey.delete: ^- ?.gameKey.insert: ^+ ! Editor key bindings ?.editKey.1: select 'mr',0; ?.editKey.2: select 'mr',1; ?.editKey.3: select 'mr',2; ?.editKey.4: select 'mr',3; ?.editKey.5: select 'mr',4; | > > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | ?.gameKey.alt.G: ^g ?.gameKey.alt.P: ^p ?.gameKey.alt.X: ^x ?.gameKey.alt.leftbracket: select 'rs',-5; ?.gameKey.alt.rightbracket: select 'rs',+5; ?.gameKey.delete: ^- ?.gameKey.insert: ^+ ?.gameKey.alt.kp_minus: select 'go',-ord from levels where ord<$level and not solved order by ord desc limit 1; ?.gameKey.alt.kp_plus: select 'go',-ord from levels where ord>$level and not solved order by ord asc limit 1; ! Editor key bindings ?.editKey.1: select 'mr',0; ?.editKey.2: select 'mr',1; ?.editKey.3: select 'mr',2; ?.editKey.4: select 'mr',3; ?.editKey.5: select 'mr',4; |
︙ | ︙ |
Modified function.c from [6d93dbc609] to [77ed877244].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #if 0 gcc ${CFLAGS:--s -O2} -c -fplan9-extensions function.c `sdl-config --cflags` exit #endif #include "SDL.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "smallxrm.h" #include "heromesh.h" typedef struct { struct sqlite3_vtab_cursor; sqlite3_int64 rowid; char unique,eof; Uint16 arg[4]; } Cursor; static void*bizarro_vtab; static void find_first_usable_image(const Class*cl,sqlite3_context*cxt) { int i; if(cl->cflags&CF_GROUP) return; if(!cl->images) return; for(i=0;i<cl->nimages;i++) { if(cl->images[i]&0x8000) { | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #if 0 gcc ${CFLAGS:--s -O2} -c -fplan9-extensions function.c `sdl-config --cflags` exit #endif #include "SDL.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "smallxrm.h" #include "heromesh.h" #include "cursorshapes.h" typedef struct { struct sqlite3_vtab_cursor; sqlite3_int64 rowid; char unique,eof; Uint16 arg[4]; } Cursor; static void*bizarro_vtab; static char*levels_schema; static void find_first_usable_image(const Class*cl,sqlite3_context*cxt) { int i; if(cl->cflags&CF_GROUP) return; if(!cl->images) return; for(i=0;i<cl->nimages;i++) { if(cl->images[i]&0x8000) { |
︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 | Module(vt_playfield, .xBestIndex=vt1_playfield_index, .xColumn=vt1_playfield_column, .xFilter=vt1_playfield_filter, .xNext=vt1_playfield_next, ); void init_sql_functions(sqlite3_int64*ptr0,sqlite3_int64*ptr1) { sqlite3_create_function(userdb,"BASENAME",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_basename,0,0); sqlite3_create_function(userdb,"BCAT",-1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_bcat,0,0); sqlite3_create_function(userdb,"BYTE",-1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_byte,0,0); sqlite3_create_function(userdb,"CL",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_cl,0,0); sqlite3_create_function(userdb,"CLASS_DATA",2,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_class_data,0,0); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 | Module(vt_playfield, .xBestIndex=vt1_playfield_index, .xColumn=vt1_playfield_column, .xFilter=vt1_playfield_filter, .xNext=vt1_playfield_next, ); static int vt1_levels_connect(sqlite3*db,void*aux,int argc,const char*const*argv,sqlite3_vtab**vt,char**err) { //TODO: Add columns specific to a puzzle set. levels_schema=sqlite3_mprintf("CREATE TEMPORARY TABLE `LEVELS`" "(`ID` INTEGER PRIMARY KEY, `ORD` INT, `CODE` INT, `WIDTH` INT, `HEIGHT` INT, `TITLE` BLOB, `SOLVED` INT, `SOLVABLE` INT);"); if(!levels_schema) fatal("Allocation failed\n"); sqlite3_declare_vtab(db,levels_schema); *vt=sqlite3_malloc(sizeof(sqlite3_vtab)); return *vt?SQLITE_OK:SQLITE_NOMEM; } static int vt1_levels_open(sqlite3_vtab*vt,sqlite3_vtab_cursor**cur) { //TODO: Add columns specific to a puzzle set. sqlite3_stmt*st1; sqlite3_stmt*st2; const unsigned char*d; unsigned char*p; int i,j; long n; int txn=sqlite3_get_autocommit(userdb)?sqlite3_exec(userdb,"BEGIN;",0,0,0):1; if(!levels_schema) return SQLITE_CORRUPT_VTAB; if(screen) set_cursor(XC_coffee_mug); fprintf(stderr,"Loading level index...\n"); if(sqlite3_exec(userdb,levels_schema,0,0,0)) { err: fatal("SQL error while loading LEVELS table: %s\n",sqlite3_errmsg(userdb)); } sqlite3_free(levels_schema); levels_schema=0; if(sqlite3_prepare_v2(userdb,"SELECT `LEVEL`, IFNULL(`DATA`,READ_LUMP_AT(`OFFSET`,?1)), `USERSTATE` FROM `USERCACHEDATA`" " WHERE `FILE` = LEVEL_CACHEID() AND `LEVEL` NOT NULL AND `LEVEL` >= 0 ORDER BY `LEVEL`;",-1,&st1,0)) goto err; // ?1=ID, ?2=CODE, ?3=WIDTH, ?4=HEIGHT, ?5=TITLE, ?6=SOLVED, ?7=SOLVABLE if(sqlite3_prepare_v3(userdb,"INSERT INTO `LEVELS` VALUES(?1,NULL,?2,?3,?4,?5,?6,?7);",-1,SQLITE_PREPARE_NO_VTAB,&st2,0)) goto err; sqlite3_bind_pointer(st1,1,levelfp,"http://zzo38computer.org/fossil/heromesh.ui#FILE_ptr",0); while((i=sqlite3_step(st1))==SQLITE_ROW) { sqlite3_reset(st2); sqlite3_bind_int(st2,1,sqlite3_column_int(st1,0)); d=sqlite3_column_blob(st1,1); n=sqlite3_column_bytes(st1,1); if(n<7 || !d) continue; sqlite3_bind_int(st2,2,d[2]|(d[3]<<8)); sqlite3_bind_int(st2,3,(d[4]&63)+1); sqlite3_bind_int(st2,4,(d[5]&63)+1); for(i=6;i<n && d[i];i++); j=d[0]|(d[1]<<8); sqlite3_bind_blob(st2,5,d+6,i-6,0); p=read_lump(FIL_SOLUTION,sqlite3_column_int(st1,0),&n); if(p) { sqlite3_bind_int(st2,7,(n>2 && d[0]==p[0] && d[1]==p[1])); free(p); } else { sqlite3_bind_int(st2,7,0); } d=sqlite3_column_blob(st1,2); n=sqlite3_column_bytes(st1,2); sqlite3_bind_int(st2,6,(d && n>5 && n-(d[n-2]<<8)-d[n-1]>3 && (d[n-4]<<8)+d[n-3]==j)); while((i=sqlite3_step(st2))==SQLITE_ROW); if(i!=SQLITE_DONE) goto err; sqlite3_bind_null(st2,5); } if(i!=SQLITE_DONE) goto err; sqlite3_finalize(st1); sqlite3_finalize(st2); if(sqlite3_prepare_v3(userdb,"UPDATE `LEVELS` SET `ORD` = ?1 WHERE `ID` = ?2;",-1,SQLITE_PREPARE_NO_VTAB,&st2,0)) goto err; for(j=0;j<level_nindex;j++) { sqlite3_reset(st2); sqlite3_bind_int(st2,1,j+1); sqlite3_bind_int(st2,2,level_index[j]); while((i=sqlite3_step(st2))==SQLITE_ROW); if(i!=SQLITE_DONE) goto err; } sqlite3_finalize(st2); if(!txn) sqlite3_exec(userdb,"COMMIT;",0,0,0); fprintf(stderr,"Done\n"); if(screen) set_cursor(XC_arrow); return SQLITE_SCHEMA; } Module(vt_levels, .xConnect=vt1_levels_connect, .xOpen=vt1_levels_open, ); void init_sql_functions(sqlite3_int64*ptr0,sqlite3_int64*ptr1) { sqlite3_create_function(userdb,"BASENAME",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_basename,0,0); sqlite3_create_function(userdb,"BCAT",-1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_bcat,0,0); sqlite3_create_function(userdb,"BYTE",-1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_byte,0,0); sqlite3_create_function(userdb,"CL",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_cl,0,0); sqlite3_create_function(userdb,"CLASS_DATA",2,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_class_data,0,0); |
︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 1235 | sqlite3_create_module(userdb,"MESSAGES",&vt_messages,"CREATE TABLE `MESSAGES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `TRACE` INT);"); sqlite3_create_module(userdb,"OBJECTS",&vt_objects,"CREATE TABLE `OBJECTS`(`ID` INTEGER PRIMARY KEY, `CLASS` INT, `MISC1` INT, `MISC2` INT, `MISC3` INT," "`IMAGE` INT, `DIR` INT, `X` INT, `Y` INT, `UP` INT, `DOWN` INT, `DENSITY` INT HIDDEN, `BIZARRO` INT HIDDEN);"); sqlite3_create_module(userdb,"BIZARRO_OBJECTS",&vt_objects,"CREATE TABLE `OBJECTS`(`ID` INTEGER PRIMARY KEY, `CLASS` INT, `MISC1` INT, `MISC2` INT, `MISC3` INT," "`IMAGE` INT, `DIR` INT, `X` INT, `Y` INT, `UP` INT, `DOWN` INT, `DENSITY` INT HIDDEN, `BIZARRO` INT HIDDEN);"); sqlite3_create_module(userdb,"INVENTORY",&vt_inventory,"CREATE TABLE `INVENTORY`(`ID` INTEGER PRIMARY KEY, `CLASS` INT, `IMAGE` INT, `VALUE` INT);"); sqlite3_create_module(userdb,"PLAYFIELD",&vt_playfield,"CREATE TABLE `PLAYFIELD`(`X` INT, `Y` INT, `OBJ` INT, `BIZARRO_OBJ` INT);"); } | > | 1312 1313 1314 1315 1316 1317 1318 1319 1320 | sqlite3_create_module(userdb,"MESSAGES",&vt_messages,"CREATE TABLE `MESSAGES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `TRACE` INT);"); sqlite3_create_module(userdb,"OBJECTS",&vt_objects,"CREATE TABLE `OBJECTS`(`ID` INTEGER PRIMARY KEY, `CLASS` INT, `MISC1` INT, `MISC2` INT, `MISC3` INT," "`IMAGE` INT, `DIR` INT, `X` INT, `Y` INT, `UP` INT, `DOWN` INT, `DENSITY` INT HIDDEN, `BIZARRO` INT HIDDEN);"); sqlite3_create_module(userdb,"BIZARRO_OBJECTS",&vt_objects,"CREATE TABLE `OBJECTS`(`ID` INTEGER PRIMARY KEY, `CLASS` INT, `MISC1` INT, `MISC2` INT, `MISC3` INT," "`IMAGE` INT, `DIR` INT, `X` INT, `Y` INT, `UP` INT, `DOWN` INT, `DENSITY` INT HIDDEN, `BIZARRO` INT HIDDEN);"); sqlite3_create_module(userdb,"INVENTORY",&vt_inventory,"CREATE TABLE `INVENTORY`(`ID` INTEGER PRIMARY KEY, `CLASS` INT, `IMAGE` INT, `VALUE` INT);"); sqlite3_create_module(userdb,"PLAYFIELD",&vt_playfield,"CREATE TABLE `PLAYFIELD`(`X` INT, `Y` INT, `OBJ` INT, `BIZARRO_OBJ` INT);"); sqlite3_create_module(userdb,"LEVELS",&vt_levels,0); } |
Modified game.doc from [fc79222cb9] to [9d856ff616].
︙ | ︙ | |||
135 136 137 138 139 140 141 142 143 144 145 146 147 148 | F9 Flash player position F10 SQL queries ESC Restart level TAB Toggle inventory/replay display KP ENTER Restart level KP + Next level KP - Previous level SHIFT+KP + Last level SHIFT+KP - First level ALT+G Inspect globals ALT+P Begin slow replay ALT+[ Increase slow replay speed ALT+] Decrease slow replay speed INS Toggle insertion mode | > > | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | F9 Flash player position F10 SQL queries ESC Restart level TAB Toggle inventory/replay display KP ENTER Restart level KP + Next level KP - Previous level ALT+KP + Next unsolved level ALT+KP - Previous unsolved level SHIFT+KP + Last level SHIFT+KP - First level ALT+G Inspect globals ALT+P Begin slow replay ALT+[ Increase slow replay speed ALT+] Decrease slow replay speed INS Toggle insertion mode |
︙ | ︙ |
Modified heromesh.h from [390cfc3e4a] to [94459dbf11].
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | extern char main_options[128]; extern Uint8 message_trace[0x4100/8]; extern Uint16 level_id,level_ord,level_version,level_code; extern unsigned char*level_title; extern Uint16*level_index; extern int level_nindex; extern char level_changed; // 1 if solution is potentially invalidated by edits #ifdef __GNUC__ extern char stack_protect_mode; extern void*stack_protect_mark; extern void*stack_protect_low; extern void*stack_protect_high; #define StackProtection() (stack_protect_mode && ( \ | > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | extern char main_options[128]; extern Uint8 message_trace[0x4100/8]; extern Uint16 level_id,level_ord,level_version,level_code; extern unsigned char*level_title; extern Uint16*level_index; extern int level_nindex; extern char level_changed; // 1 if solution is potentially invalidated by edits extern FILE*levelfp; extern FILE*solutionfp; #ifdef __GNUC__ extern char stack_protect_mode; extern void*stack_protect_mark; extern void*stack_protect_low; extern void*stack_protect_high; #define StackProtection() (stack_protect_mode && ( \ |
︙ | ︙ |
Modified main.c from [d4c1330f51] to [3d54a4ff62].
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | char main_options[128]; Uint8 message_trace[0x4100/8]; Uint16 level_id,level_ord,level_version,level_code; unsigned char*level_title; Uint16*level_index; int level_nindex; char level_changed; #ifdef __GNUC__ char stack_protect_mode=0; void*stack_protect_mark; void*stack_protect_low; void*stack_protect_high; #endif static const char*globalclassname; static SDL_Cursor*cursor[77]; | > > < < | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | char main_options[128]; Uint8 message_trace[0x4100/8]; Uint16 level_id,level_ord,level_version,level_code; unsigned char*level_title; Uint16*level_index; int level_nindex; char level_changed; FILE*levelfp; FILE*solutionfp; #ifdef __GNUC__ char stack_protect_mode=0; void*stack_protect_mark; void*stack_protect_low; void*stack_protect_high; #endif static const char*globalclassname; static SDL_Cursor*cursor[77]; static FILE*compositefp; static sqlite3_int64 leveluc,solutionuc; static sqlite3_stmt*readusercachest; static char*hpath; typedef struct { FILE*fp; |
︙ | ︙ |
Modified sql.doc from [4e9feff88b] to [556de4a794].
︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | Zero extends a 32-bit number to 64-bits. Same as NVALUE. === Tables === Asterisks denote virtual tables. (The only disk tables are USERCACHEDATA and USERCACHEINDEX; all others are eiter temporary or virtual.) CREATE TABLE "CLASSES"("ID" INTEGER PRIMARY KEY, "NAME" TEXT, "EDITORHELP" TEXT, "HELP" TEXT, "INPUT" INT, "QUIZ" INT, "TRACEIN" INT, "TRACEOUT" INT, "GROUP" TEXT, "PLAYER" INT); * A list of classes in the current puzzle set; mostly read-only. Only QUIZ, TRACEIN, and TRACEOUT are writable. If TRACEIN is true then it will trace messages received by this class (if tracing is enabled). If TRACEOUT is true then it will trace messages sent by this class (if tracing is enabled). CREATE TABLE "INVENTORY"("ID" INTEGER PRIMARY KEY, "CLASS" INT, "IMAGE" INT, "VALUE" INT); * This table contains the current inventory, and is read-only. It is not meaningful in the editor. CREATE TABLE "MESSAGES"("ID" INTEGER PRIMARY KEY, "NAME" TEXT, "TRACE" INT); * The list of messages in the current puzzle set; mostly read-only. Only TRACE is writable; if true, this message will be traced. CREATE TABLE "OBJECTS"("ID" INTEGER PRIMARY KEY, "CLASS" INT, "MISC1" INT, | > > > > > > > > > > > > > > > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | Zero extends a 32-bit number to 64-bits. Same as NVALUE. === Tables === Asterisks denote virtual tables. (The only disk tables are USERCACHEDATA and USERCACHEINDEX; all others are eiter temporary or virtual.) CREATE TABLE "BIZARRO_OBJECTS"("ID" INTEGER PRIMARY KEY, "CLASS" INT, "MISC1" INT, "MISC2" INT, "MISC3" INT, "IMAGE" INT, "DIR" INT, "X" INT, "Y" INT, "UP" INT, "DOWN" INT, "DENSITY" INT HIDDEN); * See OBJECTS; this is for the bizarro world only. CREATE TABLE "CLASSES"("ID" INTEGER PRIMARY KEY, "NAME" TEXT, "EDITORHELP" TEXT, "HELP" TEXT, "INPUT" INT, "QUIZ" INT, "TRACEIN" INT, "TRACEOUT" INT, "GROUP" TEXT, "PLAYER" INT); * A list of classes in the current puzzle set; mostly read-only. Only QUIZ, TRACEIN, and TRACEOUT are writable. If TRACEIN is true then it will trace messages received by this class (if tracing is enabled). If TRACEOUT is true then it will trace messages sent by this class (if tracing is enabled). CREATE TABLE "INVENTORY"("ID" INTEGER PRIMARY KEY, "CLASS" INT, "IMAGE" INT, "VALUE" INT); * This table contains the current inventory, and is read-only. It is not meaningful in the editor. CREATE TEMPORARY TABLE "LEVELS"("ID" INTEGER PRIMARY KEY, "ORD" INT, "CODE" INT, "WIDTH" INT, "HEIGHT" INT, "TITLE" BLOB, "SOLVED" INT, "SOLVABLE" INT); * This table contains a list of the levels in the current puzzle set. The SOLVED column is 1 if the current user has solved the level or 0 otherwise; the SOLVABLE column is 1 if a solution is stored for this level or 0 otherwise (it doesn't validate the solution; to do that, use the -a switch instead). Although you can write to this table after it has been read once (this table uses lazy loading), you should not do so, since the changes will not be saved. CREATE TABLE "MESSAGES"("ID" INTEGER PRIMARY KEY, "NAME" TEXT, "TRACE" INT); * The list of messages in the current puzzle set; mostly read-only. Only TRACE is writable; if true, this message will be traced. CREATE TABLE "OBJECTS"("ID" INTEGER PRIMARY KEY, "CLASS" INT, "MISC1" INT, |
︙ | ︙ |