Overview
Comment: | Some corrections of custom level table, including initializing the schema properly; start a few more parts of its implementation too. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
66cf1d39adf231ef5edb8595344f2bab |
User & Date: | user on 2021-12-25 06:33:53 |
Other Links: | manifest | tags |
Context
2021-12-27
| ||
20:33 | More corrections, and more work on implementation, of custom level table definitions. check-in: 702847e470 user: user tags: trunk | |
2021-12-25
| ||
06:33 | Some corrections of custom level table, including initializing the schema properly; start a few more parts of its implementation too. check-in: 66cf1d39ad user: user tags: trunk | |
00:11 | Start to implement (LevelTable) definition (untested so far, and currently only the definition and not the implementation). check-in: 3b02288a18 user: user tags: trunk | |
Changes
Modified class.c from [da031da59b] to [64b3d009e0].
︙ | ︙ | |||
2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 | for(;;) { if(ptr>=0xFFFA) ParseError("Out of memory\n"); nxttok(); if(Tokenf(TF_MACRO)) ParseError("Unexpected macro\n"); if(tokent==TF_CLOSE) { ll_code[ptr++]=OP_RET; return ptr; } else if(Tokenf(TF_NAME)) { switch(tokenv) { case OP_IF: if(flowdepth==64) ParseError("Too much flow control nesting\n"); ll_code[ptr++]=OP_IF; flowptr[flowdepth++]=ptr++; break; | > > > > | 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 | for(;;) { if(ptr>=0xFFFA) ParseError("Out of memory\n"); nxttok(); if(Tokenf(TF_MACRO)) ParseError("Unexpected macro\n"); if(tokent==TF_CLOSE) { ll_code[ptr++]=OP_RET; return ptr; } else if(Tokenf(TF_INT)) { if(!(tokenv&~0xFFL)) ll_code[ptr++]=tokenv; else if(!(tokenv&~0xFFFFL)) ll_code[ptr++]=OP_INT16,ll_code[ptr++]=tokenv; else ll_code[ptr++]=OP_INT32,ll_code[ptr++]=OP_INT32,ll_code[ptr++]=tokenv>>16,ll_code[ptr++]=tokenv; } else if(Tokenf(TF_NAME)) { switch(tokenv) { case OP_IF: if(flowdepth==64) ParseError("Too much flow control nesting\n"); ll_code[ptr++]=OP_IF; flowptr[flowdepth++]=ptr++; break; |
︙ | ︙ | |||
2282 2283 2284 2285 2286 2287 2288 | if(!Tokenf(TF_NAME)) ParseError("Unexpected token in (LevelTable) block\n"); switch(tokenv) { case OP_LABEL: i=look_hash(hash,LOCAL_HASH_SIZE,0x100,0x13F,ll_ndata+0x100,"data columns")?:(ll_ndata++)+0x100; i-=0x100; if(datac[i].name) ParseError("Duplicate definition\n"); datac[i].name=strdup(tokenstr); | | | 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 | if(!Tokenf(TF_NAME)) ParseError("Unexpected token in (LevelTable) block\n"); switch(tokenv) { case OP_LABEL: i=look_hash(hash,LOCAL_HASH_SIZE,0x100,0x13F,ll_ndata+0x100,"data columns")?:(ll_ndata++)+0x100; i-=0x100; if(datac[i].name) ParseError("Duplicate definition\n"); datac[i].name=strdup(tokenstr); if(!datac[i].name) fatal("Allocation failed\n"); datac[i].ptr=ptr; ptr=level_table_code(ptr,hash); break; case OP_STRING: if(last) ParseError("Extra columns after fill column\n"); for(i=0;tokenstr[i];i++) if(!(tokenstr[i]&~31)) ParseError("Improper column heading\n"); strcpy(buf,tokenstr); |
︙ | ︙ |
Modified class.doc from [73da3ea9bc] to [9f8228ce84].
︙ | ︙ | |||
2587 2588 2589 2590 2591 2592 2593 | (<label> <code...>) Define a data column. The SQL name of the data column will be that of the label name, preceded by a underscore, and some characters will be stripped out. (<string> <label> <width> <format> <color>) Defines a display column. The <label> is the name of the data column. | | > > | | | | | | | | | | 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 | (<label> <code...>) Define a data column. The SQL name of the data column will be that of the label name, preceded by a underscore, and some characters will be stripped out. (<string> <label> <width> <format> <color>) Defines a display column. The <label> is the name of the data column. The <width> is a number 1 to 255 or it can be * for fill width; only the last column is allowed to be fill width (although it is also OK if no colums are fill width). The <format> is a string of exactly one or two characters; see the below list of possible formats. The <color> is the text colour, and is optional; it can be a number from 1 to 255, or it can be a sequence of parenthesized pairs of a number (-127 to +127) and colour, to mean use those colour if the value of this column is in range. It uses the colour for all values up to and including the specified number, so the numbers should be listed in ascending order, in order to work. The <string> is the heading; it is not allowed to include control characters, nor can it include graphic characters with code number less than 32. (<local> <type> <code...>) Defines a aggregate calculation. The <local> is the name of the aggregate to be referred by other blocks. The <type> is the type of aggregate, which can be one of: + for the sum, min for the least value (unsigned), max for the greatest value (unsigned), ,min for the least value (signed), and ,max for the greatest value (signed). |
︙ | ︙ |
Modified function.c from [29a1dbc515] to [3ae0a5eecb].
︙ | ︙ | |||
1180 1181 1182 1183 1184 1185 1186 1187 | .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) { if(levels_schema) goto declare; | > > < > | | > > > > > > > > > | > > > > > > > > > > > > > > < > > | > > > > > > > > | 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 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 | .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) { sqlite3_str*str; int c,i,j; if(levels_schema) goto declare; str=sqlite3_str_new(db); sqlite3_str_appendall(str,"CREATE TEMPORARY TABLE `LEVELS`" "(`ID` INTEGER PRIMARY KEY, `ORD` INT, `CODE` INT, `WIDTH` INT, `HEIGHT` INT, `TITLE` BLOB, `SOLVED` INT, `SOLVABLE` INT"); for(i=0;i<ll_ndata;i++) { sqlite3_str_append(str,",\"_",3); for(j=0;c=ll_data[i].name[j];j++) if(c>32 && c<127 && c!='"' && c!='[' && c!=']' && c!=';' && c!='`') sqlite3_str_appendchar(str,1,c); free(ll_data[i].name); ll_data[i].name=0; sqlite3_str_appendchar(str,1,'"'); } sqlite3_str_appendall(str,");"); levels_schema=sqlite3_str_finish(str); if(!levels_schema) fatal("Allocation failed\n"); declare: if(i=sqlite3_declare_vtab(db,levels_schema)) return i; *vt=sqlite3_malloc(sizeof(sqlite3_vtab)); return *vt?SQLITE_OK:SQLITE_NOMEM; } typedef struct { Value misc1,misc2,misc3; Uint8 x,y,dir,bizarro; Uint16 class; } ObjInfo; static void calculate_level_column(sqlite3_stmt*st,const unsigned char*lvl,long sz) { ObjInfo ob; ObjInfo mru[2]; mru[0].class=mru[1].class=0; ob.x=ob.y=ob.bizarro=0; } static int vt1_levels_open(sqlite3_vtab*vt,sqlite3_vtab_cursor**cur) { sqlite3_str*str; 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 table...\n"); if(sqlite3_exec(userdb,levels_schema,0,0,0)) { err: fatal("SQL error while loading LEVELS table: %s\n",sqlite3_errmsg(userdb)); } 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 str=sqlite3_str_new(userdb); sqlite3_str_appendall(str,"INSERT INTO `LEVELS` VALUES(?1,NULL,?2,?3,?4,?5,?6,?7"); for(i=0;i<ll_ndata;i++) sqlite3_str_appendf(str,",?%d",i+8); sqlite3_str_appendall(str,");"); p=sqlite3_str_finish(str); if(!p) fatal("Allocation failed\n"); if(sqlite3_prepare_v3(userdb,p,-1,SQLITE_PREPARE_NO_VTAB,&st2,0)) goto err; sqlite3_free(p); 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); calculate_level_column(st2,d,n); 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); for(i=0;i<ll_ndata;i++) sqlite3_bind_null(st2,i+8); } 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++) { |
︙ | ︙ |
Modified game.c from [de971fc52d] to [d6b8ec0435].
︙ | ︙ | |||
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 | i=strtol(v,0,10); j=(screen->w-16)/070; if(i<1) i=j; if(i>j) i=j; if(i>255) i=255; columns=i; } // ID, ORD, CODE, WIDTH, HEIGHT, TITLE, SOLVED, SOLVABLE, ... if(sqlite3_prepare_v2(userdb,"SELECT * FROM `LEVELS` WHERE `ORD` NOT NULL AND `ORD` >= ?1 ORDER BY `ORD`;",-1,&st,0)) { screen_message(sqlite3_errmsg(userdb)); return 0; } set_cursor(XC_arrow); redraw: if(sel<0) sel=0; if(sel>=level_nindex) sel=level_nindex-1; SDL_FillRect(screen,0,0x02); r.x=r.y=0; r.w=screen->w; r.h=24; SDL_FillRect(screen,&r,0xF7); SDL_LockSurface(screen); draw_text(0,0,"<LMB/\x18\x19\x1A\x1B> Select <MMB/SP> Title <RMB/RET> Play <0-9> Find <ESC> Cancel",0xF7,0xF0); draw_text(0,8,"<F1> Wide/Tall <F2> ID/Ord",0xF7,0xF0); sqlite3_reset(st); if(mo&1) { scrmax=level_nindex; | > | | | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 | i=strtol(v,0,10); j=(screen->w-16)/070; if(i<1) i=j; if(i>j) i=j; if(i>255) i=255; columns=i; } if(!ll_head) ll_head="\xB3W \xB3H \xB3 TITLE"; // ID, ORD, CODE, WIDTH, HEIGHT, TITLE, SOLVED, SOLVABLE, ... if(sqlite3_prepare_v2(userdb,"SELECT * FROM `LEVELS` WHERE `ORD` NOT NULL AND `ORD` >= ?1 ORDER BY `ORD`;",-1,&st,0)) { screen_message(sqlite3_errmsg(userdb)); return 0; } set_cursor(XC_arrow); redraw: if(sel<0) sel=0; if(sel>=level_nindex) sel=level_nindex-1; SDL_FillRect(screen,0,0x02); r.x=r.y=0; r.w=screen->w; r.h=24; SDL_FillRect(screen,&r,0xF7); SDL_LockSurface(screen); draw_text(0,0,"<LMB/\x18\x19\x1A\x1B> Select <MMB/SP> Title <RMB/RET> Play <0-9> Find <ESC> Cancel",0xF7,0xF0); draw_text(0,8,"<F1> Wide/Tall <F2> ID/Ord",0xF7,0xF0); sqlite3_reset(st); if(mo&1) { scrmax=level_nindex; draw_text(16+060,16,ll_head,0xF7,0xF1); draw_text(16,16,mo&2?"\xB3 ID ":"\xB3 ORD ",0xF7,0xF1); if(rescroll) { if(sel<scroll) scroll=sel; if(sel>=scroll+screen->h/8-3) scroll=sel+4-screen->h/8; rescroll=0; } sqlite3_bind_int(st,1,scroll+1); for(y=24;y<screen->h-7;y+=8) { |
︙ | ︙ |
Modified main.c from [3d54a4ff62] to [f3572b0f94].
︙ | ︙ | |||
1067 1068 1069 1070 1071 1072 1073 | set_stack_protection(); #endif if(main_options['c']) { load_classes(); return 0; } init_sql(); | < > | 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 | set_stack_protection(); #endif if(main_options['c']) { load_classes(); return 0; } init_sql(); init_screen(); if(main_options['p']) { run_picture_editor(); return 0; } if(main_options['z']) init_composite(); load_pictures(); if(main_options['T']) { printf("argv[0] = %s\n",argv[0]); test_mode(); return 0; } if(!main_options['z']) init_usercache(); if(main_options['n']) return 0; load_classes(); load_key_bindings(); load_level_index(); optionquery[1]=Q_maxObjects; max_objects=strtoll(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"",0,0)?:0xFFFF0000L; set_tracing(); annihilate(); optionquery[1]=Q_level; if(level_ord=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"",0,10)) { |
︙ | ︙ |