Free Hero Mesh

Check-in [cb281b5818]
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.
Overview
Comment:Enhancements to (PopUp) to use arrays; new Quiz and ,Quiz commands to set quiz_obj; bug fix for the case where quiz_obj has been destroyed.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cb281b5818331244dd39877fc9c2ef030414d44f
User & Date: user on 2022-09-01 21:59:44
Other Links: manifest | tags
Context
2022-09-08
05:15
TODO features; not implemented yet check-in: ba571cb343 user: user tags: trunk
2022-09-01
21:59
Enhancements to (PopUp) to use arrays; new Quiz and ,Quiz commands to set quiz_obj; bug fix for the case where quiz_obj has been destroyed. check-in: cb281b5818 user: user tags: trunk
2022-08-31
23:24
Implement the conditional blocks in (PopUp) texts. check-in: 88913b5804 user: user tags: trunk
Changes

Modified class.doc from [fcbb96f739] to [b11e8f2620].

1630
1631
1632
1633
1634
1635
1636




1637
1638
1639
1640
1641
1642
1643
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647







+
+
+
+







  As ,MoveTo but sends JUMPED message to that object after it has been
  successfully teleported.

Key  ( -- number )
  During the input phase, the key input. During other phases, zero. During
  the input phase of coordinate input, this value will be 1.

,Key  ( -- number true | false )
  If the key (as for Key command) is '1 to '9 or 'A to 'Z then it will be
  the corresponding array index (as for %Q) and true, otherwise false.

land  ( in1 in2 -- out )
  Logical AND.

le  ( in1 in2 -- bool )
  Test if first input is less or equal to second input (unsigned).

,le  ( in1 in2 -- bool )
1890
1891
1892
1893
1894
1895
1896












1897
1898
1899
1900
1901
1902
1903
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919







+
+
+
+
+
+
+
+
+
+
+
+







(PopUp <number>)  ( string args... -- )
  Displays a popup message, like PopUp does. However, this one allows the
  string to contain substitution codes; see the section below about what
  substitution codes are allowed in popup messages. Each substitution code
  consumes some number of arguments, from bottom to top. The number of
  arguments must be 0 to 32.

Quiz  ( -- ) **
  If used after PopUp, makes dismissing the popup message to send a KEY
  message to this object instead of any other one.

,Quiz  ( any -- ) **
  If used after PopUp, makes dismissing the popup message to send a KEY
  message to the specified object instead of any other one. If you specify
  a class, then it will create an object of that class and use that one.
  If you specify a message, then it will send that message to the Control
  object, similar to specifying the Control object itself but will use the
  specified message instead of KEY.

Rel  ( dir -- dir )
  Resolves a relative direction to an absolute direction.

,Rel  ( obj dir -- dir )
  Resolves a relative direction to an absolute direction, using the
  direction of the specified object as the base. If zero is specified
  instead of a valid object, then the result is the same as the input.
2240
2241
2242
2243
2244
2245
2246





2247
2248
2249
2250
2251
2252
2253
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274







+
+
+
+
+








%i
  Display a picture. Consumes two arguments, being first a class and then
  the image number. If either argument is not valid, displays nothing. The
  picture may take up multiple lines of space; the lines will be moved
  farther apart to make room if necessary.

%Q
  Display a quiz button from 1 to 9 or A to Z, depending on the current
  array index. This is only valid inside of a %[ ... %] block, and it does
  not itself consume any argument.

%R
  Display a roman number.

%s
  Display a string. If the value is not a string, it will display it as
  whatever type it is.

2277
2278
2279
2280
2281
2282
2283












2284
2285
2286
2287
2288
2289
2290
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323







+
+
+
+
+
+
+
+
+
+
+
+








%<
  Unconsume one argument. (Does not produce any output.)

%>
  Skip one argument. (Does not produce any output.)

%[
  Consumes one argument, which must be an array; no further arguments can
  be accessible in this case. If it is not an array then all further output
  is suppressed (even past the end of this block, too). This cannot occur
  more than once. The second dimension is the number of records, and the
  first is the fields within that record; all further data accessed by the
  substitution codes are the data within the array.

%]
  End of an array block; if there are any more records in the array then it
  will access the next record and go back to the beginning of this block.


=== Messages ===

This section describes when the various standard messages are sent to
objects, and what return values are expected. (Do not confuse CREATE with
CREATED, or DESTROY with DESTROYED, or COLLIDE with COLLIDING; they have
different purposes.)

Modified exec.c from [39d6976b93] to [70385a14e1].

1982
1983
1984
1985
1986
1987
1988



1989
1990
1991
1992
1993
1994
1995
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998







+
+
+








static void v_set_popup(Uint32 from,int argc) {
  const unsigned char*t;
  const unsigned char*u;
  sqlite3_str*s;
  Value v;
  int argi=1;
  const unsigned char*at=0;
  int ax;
  Value av;
  if(argc>32 || argc<0) Throw("Too many arguments");
  vstackptr-=argc;
  v=Pop();
  if(quiz_text) return;
  if(argc) {
    argc++;
    if(v.t!=TY_STRING && v.t!=TY_LEVELSTRING) Throw("Type mismatch");
2026
2027
2028
2029
2030
2031
2032





2033
2034
2035
2036
2037
2038
2039
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047







+
+
+
+
+







            if(vstack[vstackptr+argi].t==TY_CLASS && vstack[vstackptr+argi+1].t==TY_NUMBER) {
              Class*c=classes[vstack[vstackptr+argi].u];
              int n=vstack[vstackptr+argi+1].u&255;
              if(n<c->nimages) sqlite3_str_appendf(s,"\x0E\x07:%d\\",c->images[n]&0x7FFF);
            }
            argi+=2;
            break;
          case 'Q':
            if(!at) break;
            sqlite3_str_appendchar(s,1,16);
            sqlite3_str_appendchar(s,1,ax<10?ax+'0':ax+'A'-10);
            break;
          case 'R':
            if(argi==argc) break;
            v=vstack[vstackptr+argi++];
            if(v.t==TY_NUMBER) {
              static const char*const r1000[10]={"","M","MM","MMM","MMMM","MMMMM","MMMMMM","MMMMMMM","MMMMMMMM","MMMMMMMMM"};
              static const char*const r100[10]={"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
              static const char*const r10[10]={"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
2093
2094
2095
2096
2097
2098
2099





















2100
2101
2102
2103
2104
2105
2106
2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+







            // no effect
            break;
          case '<':
            if(argi>0) --argi;
            break;
          case '>':
            if(argi<argc) ++argi;
            break;
          case '[':
            if(at) break;
            ax=0;
            if(argi==argc) break;
            av=vstack[vstackptr+argi++];
            if(av.t!=TY_ARRAY) goto end;
            argc=((av.u>>26)&0x3F)+1;
            if(vstackptr+argc>=VSTACKSIZE) {
              sqlite3_free(sqlite3_str_finish(s));
              Throw("Stack overflow");
            }
            at=t;
            // fall through
          case ']':
            if(!at) break;
            if(ax>((av.u>>16)&0x3FF)) break;
            for(argi=0;argi<argc;argi++) vstack[vstackptr+argi]=array_data[(av.u&0xFFFF)+argi+ax+((av.u>>26)&0x3F)*ax];
            t=at;
            argi=0;
            ax++;
            break;
          default:
            if(main_options['t'] || main_options['v']) fprintf(stderr,"Unrecognized %% code in (PopUp)\n");
            break;
        }
      } else {
        sqlite3_str_appendall(s,t);
        break;
      }
    }
    end:
    sqlite3_str_appendchar(s,1,0);
    quiz_text=sqlite3_str_finish(s);
  } else {
    switch(v.t) {
      case TY_STRING: case TY_LEVELSTRING:
        quiz_text=sqlite3_mprintf("%s",value_string_ptr(v));
        break;
2133
2134
2135
2136
2137
2138
2139











2140
2141
2142
2143
2144
2145
2146
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187







+
+
+
+
+
+
+
+
+
+
+







    if(*t==16) {
      quiz_obj.t=objects[from]->generation?:1;
      quiz_obj.u=from;
    }
    if(*t==31 && t[1]) t+=2; else t+=1;
  }
}

static void v_set_quiz(Uint32 from,Value v) {
  if(v.t==TY_CLASS) {
    from=create(from,v.u,objects[from]->x?:1,objects[from]->y?:1,0,objects[from]->dir);
    if(from==VOIDLINK) Throw("Error creating object");
    quiz_obj=OVALUE(from);
  } else {
    if(v.t!=TY_MESSAGE) v_object(v);
    quiz_obj=v;
  }
}

static int v_dispatch(const Uint16*code) {
  int i=msgvars.arg1.u;
  if(msgvars.arg1.t!=TY_NUMBER) Throw("Type mismatch");
  if(!i || (msgvars.arg1.u&~0xFF) || !code[i]) {
    StackReq(0,1);
    if(!code[256]) Push(msgvars.arg2);
3159
3160
3161
3162
3163
3164
3165

3166
3167
3168
3169
3170
3171
3172
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214







+







    case OP_INVISIBLE_EC: NoIgnore(); StackReq(2,0); SetFlagOf(OF_INVISIBLE); break;
    case OP_IS: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_is(t1,t2))); break;
    case OP_JUMPTO: NoIgnore(); StackReq(2,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); Push(NVALUE(jump_to(obj,obj,t2.u,t3.u))); break;
    case OP_JUMPTO_C: NoIgnore(); StackReq(3,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); i=v_object(Pop()); Push(NVALUE(jump_to(obj,i,t2.u,t3.u))); break;
    case OP_JUMPTO_D: NoIgnore(); StackReq(2,0); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); jump_to(obj,obj,t2.u,t3.u); break;
    case OP_JUMPTO_CD: NoIgnore(); StackReq(3,0); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); i=v_object(Pop()); jump_to(obj,i,t2.u,t3.u); break;
    case OP_KEY: StackReq(0,1); Push(NVALUE(current_key)); break;
    case OP_KEY_C: StackReq(0,2); i=current_key; if((i>='1' && i<='9') || (i>='A' && i<='Z')) Push(NVALUE(i&64?i+9-'A':i-'1')),Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_KEYCLEARED: StackReq(0,1); if(o->oflags&OF_KEYCLEARED) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_KEYCLEARED_C: StackReq(1,1); GetFlagOf(OF_KEYCLEARED); break;
    case OP_KEYCLEARED_E: StackReq(1,0); if(v_bool(Pop())) o->oflags|=OF_KEYCLEARED; else o->oflags&=~OF_KEYCLEARED; break;
    case OP_KEYCLEARED_EC: StackReq(2,0); SetFlagOf(OF_KEYCLEARED); break;
    case OP_LAND: StackReq(2,1); t1=Pop(); t2=Pop(); if(v_bool(t1) && v_bool(t2)) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_LE: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_unsigned_greater(t1,t2)?0:1)); break;
    case OP_LE_C: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_signed_greater(t1,t2)?0:1)); break;
3265
3266
3267
3268
3269
3270
3271


3272
3273
3274
3275
3276
3277
3278
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322







+
+







    case OP_QCZ: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t==TY_CLASS || (t1.t==TY_NUMBER && !t1.u)) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_QM: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t==TY_MESSAGE) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_QN: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t==TY_NUMBER) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_QO: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t>TY_MAXTYPE) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_QOZ: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t>TY_MAXTYPE || (t1.t==TY_NUMBER && !t1.u)) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_QS: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t==TY_STRING || t1.t==TY_LEVELSTRING) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_QUEEN: StackReq(0,1); Numeric(msgvars.arg1); i="\x06\x01\x07\x05\x03\x04\x02\x00"[msgvars.arg1.u&7]; Push(NVALUE(i)); break;
    case OP_QUIZ: NoIgnore(); if(quiz_text) quiz_obj=OVALUE(obj); break;
    case OP_QUIZ_C: NoIgnore(); StackReq(1,0); t1=Pop(); if(quiz_text) v_set_quiz(obj,t1); break;
    case OP_REL: StackReq(1,1); t1=Pop(); Numeric(t1); i=resolve_dir(obj,t1.u); Push(NVALUE(i)); break;
    case OP_REL_C: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); i=v_object(t1); i=(i==VOIDLINK?t2.u:resolve_dir(i,t2.u)); Push(NVALUE(i)); break;
    case OP_REPLACE: NoIgnore(); StackReq(5,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_replace(obj,t1,t2,t3,t4,t5)); break;
    case OP_REPLACE_D: NoIgnore(); StackReq(5,0); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_replace(obj,t1,t2,t3,t4,t5); break;
    case OP_RET: return;
    case OP_RETNZ: StackReq(1,1); t1=Pop(); if(v_bool(t1)) { Push(t1); return; } break;
    case OP_RETZ: StackReq(1,1); t1=Pop(); if(!v_bool(t1)) { Push(t1); return; } break;
3747
3748
3749
3750
3751
3752
3753




3754
3755
3756
3757
3758
3759








3760
3761
3762
3763
3764
3765
3766
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803




3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818







+
+
+
+


-
-
-
-
+
+
+
+
+
+
+
+







      n=lastobj;
      while(n!=VOIDLINK) {
        i=classes[objects[n]->class]->cflags;
        if(i&CF_INPUT) v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),v,NVALUE(0));
        if(i&CF_PLAYER) m=n;
        n=objects[n]->prev;
      }
    } else if(quiz_obj.t==TY_MESSAGE) {
      n=quiz_obj.u;
      quiz_obj=NVALUE(0);
      if(control_obj!=VOIDLINK) v=send_message(VOIDLINK,control_obj,n,NVALUE(key),NVALUE(0),NVALUE(1));
    } else {
      n=quiz_obj.u;
      if(objects[n]->generation!=quiz_obj.t) n=VOIDLINK;
      quiz_obj=NVALUE(0);
      if(classes[objects[n]->class]->cflags&CF_COMPATIBLE) all_flushed=1;
      v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),NVALUE(0),NVALUE(1));
      if(!objects[n] || objects[n]->generation!=quiz_obj.t) {
        quiz_obj=NVALUE(0);
        all_flushed=1;
      } else {
        quiz_obj=NVALUE(0);
        if(classes[objects[n]->class]->cflags&CF_COMPATIBLE) all_flushed=1;
        v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),NVALUE(0),NVALUE(1));
      }
    }
  } else if(has_xy_input && key>=0x8000 && key<=0x8FFF) {
    x=((key>>6)&63)+1; y=(key&63)+1;
    if(x>pfwidth || y>pfheight) return "Illegal move";
    current_key=KEY_XY;
    if(control_obj!=VOIDLINK) {
      quiz_obj=NVALUE(0);

Modified instruc from [5c44374bcc] to [ea8898a518].

198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225







-
+












-
+







Msg
From
=Arg1
=Arg2
=Arg3
=MoveNumber
Level
Key
,Key
=Finished

; Top level definitions
-Background
-CodePage
-Order
Control
-LevelTable
-InputXY

; Class definitions
-Input
-Quiz
,Quiz
-InPlace
-DefaultImage
-Help
-EditorHelp
-Others
-SUBS

Modified instruc.h from [1fa409a8df] to [62a01ab909].

296
297
298
299
300
301
302

303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321







+










+







#define OP_ARG2_E 36997
#define OP_ARG3 32902
#define OP_ARG3_E 36998
#define OP_MOVENUMBER 32903
#define OP_MOVENUMBER_E 36999
#define OP_LEVEL 32904
#define OP_KEY 32905
#define OP_KEY_C 34953
#define OP_FINISHED 32906
#define OP_FINISHED_E 37002
#define OP_BACKGROUND 32907
#define OP_CODEPAGE 32908
#define OP_ORDER 32909
#define OP_CONTROL 32910
#define OP_LEVELTABLE 32911
#define OP_INPUTXY 32912
#define OP_INPUT 32913
#define OP_QUIZ 32914
#define OP_QUIZ_C 34962
#define OP_INPLACE 32915
#define OP_DEFAULTIMAGE 32916
#define OP_HELP 32917
#define OP_EDITORHELP 32918
#define OP_OTHERS 32919
#define OP_SUBS 32920
#define OP_ANIMATE 32921
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654







-
+







{"JAYAYAYNG",8389415},
{"JUMPED",8389128},
{"JumpTo",10584247},
{"KEWEL",8389421},
{"KEY",8389129},
{"KLECK",8389387},
{"KLINKK",8389385},
{"Key",8421513},
{"Key",8487049},
{"KeyCleared",8618099},
{"L",9437194},
{"LASTIMAGE",8389126},
{"LB",9437195},
{"LF",9437193},
{"LOCK",8389407},
{"LOOP",8388610},
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
702
703
704
705
706
707
708

709
710
711
712
713
714
715
716







-
+







{"PLAYERMOVING",8389133},
{"POSTINIT",8389138},
{"POUR",8389377},
{"POWER",8389386},
{"Player",8487037},
{"PopUp",8421582},
{"Queen",8683772},
{"Quiz",8683666},
{"Quiz",8487058},
{"R",9437198},
{"RATCHET1",8389417},
{"RATCHET2",8389411},
{"RATTLE",8389402},
{"RB",9437197},
{"RF",9437199},
{"Rel",8487120},