Free Hero Mesh

Check-in [757d440f6b]
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:Implement subclassing. (Only partially tested so far)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 757d440f6b114d20b9b784e864862a295f3b81e0
User & Date: user on 2021-04-27 23:08:50
Other Links: manifest | tags
Context
2021-04-28
17:10
Implement the (Others) block check-in: 1750e878e8 user: user tags: trunk
2021-04-27
23:08
Implement subclassing. (Only partially tested so far) check-in: 757d440f6b user: user tags: trunk
2021-04-26
04:05
Implement more operations with marks. check-in: e742adc13a user: user tags: trunk
Changes

Modified class.c from [73ca03c751] to [849ea4a56a].

1183
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197







-
+







#define AddInstF(x,y) (cl->codes[ptr++]=(x),prflag=(y))
#define ChangeInst(x) (cl->codes[ptr-1]x,prflag=0)
#define InstFlag(x) (peep<ptr && (prflag&(x)))
#define Inst7bit() (peep<ptr && cl->codes[ptr-1]<0x0080)
#define Inst8bit() (peep<ptr && cl->codes[ptr-1]<0x0100)
#define AbbrevOp(x,y) case x: if(Inst7bit()) ChangeInst(+=0x1000|((y)<<4)); else AddInstF(x,tokent); break
#define FlowPush(x) do{ if(flowdepth==64) ParseError("Too much flow control nesting\n"); flowop[flowdepth]=x; flowptr[flowdepth++]=ptr; }while(0)
#define FlowPop(x) do{ if(!flowdepth || flowop[--flowdepth]!=(x)) ParseError("Flow control mismatch\n"); }while(0)
#define FlowPop(x) do{ if(!flowdepth || flowop[--flowdepth]!=(x)) ParseError("Flow control mismatch\n"); prflag=0; }while(0)
static int parse_instructions(int cla,int ptr,Hash*hash,int compat) {
  int peep=ptr;
  int prflag=0;
  Class*cl=classes[cla];
  int flowdepth=0;
  Uint16 flowop[64];
  Uint16 flowptr[64];
1355
1356
1357
1358
1359
1360
1361





1362
1363
1364
1365
1366
1367
1368
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373







+
+
+
+
+







            AddInst(y+0x0800);
            AddInst(0x1F00|(x&0x1F));
          } else {
            AddInst(y);
            AddInst(0x1F00|(x&0x1F));
          }
          break;
        case OP_SUPER:
        case OP_SUPER_C:
          if(!ptr || cl->codes[0]!=OP_SUPER) ParseError("Use of Super in a class with no parent class\n");
          AddInst(tokenv);
          break;
        default:
          if(Tokenf(TF_ABNORMAL)) ParseError("Invalid instruction token\n");
          if(compat && Tokenf(TF_COMPAT) && Tokenf(TF_EQUAL)) ++tokenv;
          AddInstF(tokenv,tokent);
      }
    } else if(Tokenf(TF_FUNCTION)) {
      AddInst2(OP_FUNCTION,tokenv&0x3FFF);
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439







+







    } else {
      ParseError("Invalid instruction token\n");
    }
    if(ptr>=0xFFEF) ParseError("Out of code space\n");
  }
  if(flowdepth) ParseError("Unterminated flow control blocks (%d levels)\n",flowdepth);
  cl->codes=realloc(cl->codes,ptr*sizeof(Uint16))?:cl->codes;
  if(!ptr) cl->codes=0;
  return ptr;
}

static void dump_class(int cla,int endptr,const Hash*hash) {
  const Class*cl=classes[cla];
  int i,j;
  if(!cl) return;
1680
1681
1682
1683
1684
1685
1686







































1687
1688
1689
1690
1691
1692
1693
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738







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







  if(!x) ParseError("User flag ^%s not defined\n",tokenstr);
  if(x<0x1020) cl->misc4|=1L<<(x&0x1F);
  else if(x<0x1040) cl->misc5|=1L<<(x&0x1F);
  else if(x<0x1060) cl->misc6|=1L<<(x&0x1F);
  else if(x<0x1080) cl->misc7|=1L<<(x&0x1F);
  else cl->collisionLayers|=1<<(x&0x1F);
}

static void set_super_class(Class*cl,int ptr) {
  Class*su=classes[tokenv&0x3FFF];
  int i;
  if(ptr || cl->nmsg) ParseError("Cannot specify superclasses before program blocks\n");
  if(!su || !(su->cflags&CF_GROUP)) ParseError("Cannot inherit from non-abstract class\n");
  cl->codes=malloc(8);
  if(!cl->codes) fatal("Allocation failed\n");
  cl->codes[0]=OP_SUPER;
  cl->codes[1]=tokenv&0x3FFF;
  cl->height=su->height;
  cl->weight=su->weight;
  cl->climb=su->climb;
  cl->density=su->density;
  cl->volume=su->volume;
  cl->strength=su->strength;
  cl->arrivals|=su->arrivals;
  cl->departures|=su->departures;
  cl->temperature=su->temperature;
  cl->misc4|=su->misc4;
  cl->misc5|=su->misc5;
  cl->misc6|=su->misc6;
  cl->misc7|=su->misc7;
  cl->uservars+=su->uservars;
  cl->oflags|=su->oflags;
  for(i=0;i<4;i++) {
    cl->sharp[i]=su->sharp[i];
    cl->hard[i]=su->hard[i];
  }
  cl->cflags|=su->cflags&(CF_PLAYER|CF_INPUT|CF_COMPATIBLE|CF_QUIZ);
  cl->shape=su->shape;
  cl->shovable=su->shovable;
  cl->collisionLayers|=su->collisionLayers;
  if(cl->nmsg=su->nmsg) {
    cl->messages=malloc(cl->nmsg*sizeof(Uint16));
    if(!cl->messages) fatal("Allocation failed\n");
    for(i=0;i<cl->nmsg;i++) cl->messages[i]=(su->messages[i]==0xFFFF)?0xFFFF:0x0000;
  }
}

static void class_definition(int cla,sqlite3_stmt*vst) {
  Hash*hash=calloc(LOCAL_HASH_SIZE,sizeof(Hash));
  Class*cl=classes[cla];
  int ptr=0;
  int compat=0;
  int i;
1828
1829
1830
1831
1832
1833
1834


1835
1836
1837
1838
1839
1840
1841
1842
1843
1844

1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859



1860
1861
1862
1863
1864
1865
1866
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890

1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916







+
+









-
+















+
+
+







        case OP_QUIZ: cl->cflags|=CF_QUIZ; break;
        case OP_INVISIBLE: cl->oflags|=OF_INVISIBLE; break;
        case OP_VISUALONLY: cl->oflags|=OF_VISUALONLY; break;
        case OP_STEALTHY: cl->oflags|=OF_STEALTHY; break;
        case OP_USERSTATE: cl->oflags|=OF_USERSTATE; break;
        case OP_SHOVABLE: cl->shovable=0x55; break;
        case OP_USERFLAG: class_user_flag(cl); break;
        case OP_ABSTRACT: cl->cflags|=CF_GROUP; break;
        case 0x4000 ... 0x7FFF: set_super_class(cl,ptr); ptr=2; break;
        default: ParseError("Invalid directly inside of a class definition\n");
      }
    } else if(Tokenf(TF_CLOSE)) {
      break;
    } else {
      ParseError("Invalid directly inside of a class definition\n");
    }
  }
  end_label_stack(cl->codes,hash);
  if(!cl->nimages) cl->oflags|=OF_INVISIBLE;
  if(!cl->nimages && !(cl->cflags&CF_GROUP)) cl->oflags|=OF_INVISIBLE;
  if(main_options['C']) dump_class(cla,ptr,hash);
  if(main_options['H']) {
    for(i=0;i<LOCAL_HASH_SIZE;i++) if(hash[i].id) printf(" \"%s\": %04X\n",hash[i].txt,hash[i].id);
  }
  for(i=0;i<LOCAL_HASH_SIZE;i++) {
    if(vst && hash[i].id>=0x2000 && hash[i].id<0x2800) {
      sqlite3_reset(vst);
      sqlite3_bind_int(vst,1,(hash[i].id&0x07FF)|(cla<<16));
      sqlite3_bind_text(vst,2,hash[i].txt,-1,free);
      while(sqlite3_step(vst)==SQLITE_ROW);
    } else {
      free(hash[i].txt);
    }
  }
  free(hash);
  if(cl->cflags&CF_GROUP) {
    if(cl->edithelp || cl->gamehelp || cl->nimages) ParseError("Invalid in abstract classes");
  }
}

static void load_class_numbers(void) {
  int i,n;
  long size=0;
  unsigned char*data=read_lump(FIL_LEVEL,LUMP_CLASS_DEF,&size);
  unsigned char*p;

Modified class.doc from [edbc4954f8] to [8d1dd82683].

267
268
269
270
271
272
273









274
275
276
277
278
279
280



281
282
283
284
285
286
287
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
296
297
298







+
+
+
+
+
+
+
+
+






-
+
+
+







Within a class definition, the following definitions can be used. See also
the section about variables; many of these definitions are used to specify
the initial value for variables of objects of this class.

Outside of code blocks, named constants are not normally interchangeable
with the numbers having the same value.

<class>
  Inherit the specified class, which must have been previously declared as
  an abstract class. Flags and message codes are inherited unless they are
  overridden. Multiple inheritance is not allowed. If inheritance is used,
  it must be specified before any blocks with program instructions, and
  any user-defined variables defined in the superclass are not accessible
  by the code specific to this class; you can define another variable with
  the same name but it will be a new variable with the same name.

<userflag>
  Set a user flag bit in the definition of Misc4, Misc5, Misc6, Misc7, or
  CollisionLayers of this class. You must previously define this user flag
  as a global definition.

Abstract
  (Not implemented yet.)
  Disallows creating objects of this class, but allows other classes to
  subclass this one. The (Image), (DefaultImage), (Help), and (EditorHelp)
  blocks are not allowed in abstract classes.

(Arrivals InPlace)
  This is an abbreviation for (Arrivals 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
  0 0 0 0 0 0 0 0).

(Arrivals <numbers...>)
  Define the Arrivals variable for this class. This is twenty-five numbers
1640
1641
1642
1643
1644
1645
1646








1647
1648
1649
1650
1651
1652
1653
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672







+
+
+
+
+
+
+
+







  are always unsigned 16-bit numbers.

Sound  ( sound interruptflag -- )
  Play a sound; if the interrupt flag is zero then it does not interrupt
  existing sounds but otherwise it does. It is not an error if the values
  of the arguments are not valid.

Super  ( ? -- ? )
  Only allowed in a class which is a subclass of another class. This
  causes the current code to stop being executed and to instead execute
  the code of the class it is inheriting.

,Super  ( ? -- ? )
  Same as Super but return to this code after it is finished.

swap  ( x y -- y x )

Synchronize  ( slot startimage -- ) **
  Start a synchronized animation. Give the slot number of the animation,
  and the starting image number. The length and speed are defined in a
  global definition, and the animation is always a non-oscillating loop.

Modified exec.c from [b1c3ec4693] to [e91c1e1c82].

420
421
422
423
424
425
426











427
428
429
430
431
432
433
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444







+
+
+
+
+
+
+
+
+
+
+







  return VOIDLINK;
}

static Uint32 obj_class_at(Uint32 c,Uint32 x,Uint32 y) {
  Uint32 i;
  if(x<1 || x>pfwidth || y<1 || y>pfheight) return VOIDLINK;
  i=playfield[x+y*64-65];
  if(c && (classes[c]->cflags&CF_GROUP)) {
    Uint16 k;
    while(i!=VOIDLINK) {
      if(!(objects[i]->oflags&OF_DESTROYED)) {
        k=objects[i]->class;
        while(k!=c && classes[k]->codes && classes[k]->codes[0]==OP_SUPER) k=classes[k]->codes[1];
      }
      i=objects[i]->up;
    }
    return VOIDLINK;
  }
  while(i!=VOIDLINK) {
    if(objects[i]->class==c && !(objects[i]->oflags&OF_DESTROYED)) return i;
    i=objects[i]->up;
  }
  return VOIDLINK;
}

563
564
565
566
567
568
569





570
571
572
573
574





575
576

577
578
579
580
581
582
583
574
575
576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603







+
+
+
+
+

-



+
+
+
+
+

-
+








static Uint32 v_is(Value x,Value y) {
  Uint32 n;
  if(x.t==TY_NUMBER && !x.u) {
    return 0;
  } else if(x.t>TY_MAXTYPE && y.t==TY_CLASS) {
    n=v_object(x);
    if(classes[y.u]->cflags&CF_GROUP) {
      n=objects[n]->class;
      while(n!=y.u && classes[n]->codes && classes[n]->codes[0]==OP_SUPER) n=classes[n]->codes[1];
      return (n==y.u)?1:0;
    }
    return (objects[n]->class==y.u)?1:0;
    //TODO: subclassing (using CF_GROUP)
  } else if((x.t>TY_MAXTYPE || x.t==TY_CLASS) && y.t==TY_NUMBER && !y.u) {
    return 1;
  } else if(x.t==TY_CLASS && y.t==TY_CLASS) {
    if(classes[y.u]->cflags&CF_GROUP) {
      n=x.u;
      while(n!=y.u && classes[n]->codes && classes[n]->codes[0]==OP_SUPER) n=classes[n]->codes[1];
      return (n==y.u)?1:0;
    }
    return (x.u==y.u)?1:0;
    //TODO: subclassing (using CF_GROUP)
    //TODO: CF_GROUP
  } else {
    Throw("Type mismatch");
  }
}

static Uint32 v_destroyed(Value v) {
  if(v.t==TY_NUMBER) {
2273
2274
2275
2276
2277
2278
2279


2280
2281
2282
2283
2284
2285
2286
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308







+
+







    case OP_STRENGTH_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->strength=t1.u; break;
    case OP_STRENGTH_E16: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->strength=t1.u&0xFFFF; break;
    case OP_STRENGTH_EC: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->strength=t1.u; break;
    case OP_STRENGTH_EC16: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->strength=t1.u&0xFFFF; break;
    case OP_STRING: StackReq(0,1); Push(UVALUE(code[ptr++],TY_STRING)); break;
    case OP_SOUND: StackReq(2,0); t2=Pop(); t1=Pop(); break; // Sound not implemented at this time
    case OP_SUB: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u-t2.u)); break;
    case OP_SUPER: i=code[1]; code=classes[i]->codes; ptr=get_message_ptr(i,msgvars.msg); if(ptr==0xFFFF) break; break;
    case OP_SUPER_C: i=code[1]; j=get_message_ptr(i,msgvars.msg); if(j!=0xFFFF) execute_program(classes[i]->codes,j,obj); break;
    case OP_SWAP: StackReq(2,2); t1=Pop(); t2=Pop(); Push(t1); Push(t2); break;
    case OP_SYNCHRONIZE: StackReq(2,0); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); animate_sync(obj,t1.u,t2.u); break;
    case OP_TARGET: StackReq(0,1); Push(NVALUE(v_target(obj)?1:0)); break;
    case OP_TARGET_C: StackReq(1,1); i=v_object(Pop()); Push(NVALUE(v_target(i)?1:0)); break;
    case OP_TEMPERATURE: StackReq(0,1); Push(NVALUE(o->temperature)); break;
    case OP_TEMPERATURE_C: StackReq(1,1); Push(GetVariableOrAttributeOf(temperature,NVALUE)); break;
    case OP_TEMPERATURE_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->temperature=t1.u; break;
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431







+







  Uint32 t=0;
  Uint32 n;
  Object*o;
  Value v;
  if(s==2) t=0xFFFFFFFFULL;
  if(lastobj==VOIDLINK) return t;
  n=lastobj;
  if(c && (classes[c]->cflags&CF_GROUP)) Throw("Broadcast for abstract classes is not implemented yet");
  while(o=objects[n]) {
    if(!c || o->class==c) {
      v=send_message(from,n,msg,arg1,arg2,arg3);
      switch(s) {
        case 0:
          t++;
          break;

Modified heromesh.h from [ca9d66727e] to [24cc8e373b].

143
144
145
146
147
148
149
150
151


152
153
154
155
156
157
158
143
144
145
146
147
148
149


150
151
152
153
154
155
156
157
158







-
-
+
+







#define OF_MOVED2 0x0800
#define OF_MOVING 0x1000

typedef struct {
  const char*name;
  const char*edithelp; // not present if CF_GROUP
  const char*gamehelp; // not present if CF_GROUP
  Uint16*codes; // if this is CF_GROUP, then instead a zero-terminated list of classes
  Uint16*messages; // use 0xFFFF if no such message block; not present if CF_GROUP
  Uint16*codes;
  Uint16*messages; // use 0xFFFF if no such message block
  Uint16*images; // high bit is set if available to editor; not present if CF_GROUP
  Sint32 height,weight,climb,density,volume,strength,arrivals,departures;
  Sint32 temperature,misc4,misc5,misc6,misc7;
  Uint16 uservars,oflags,nmsg;
  Uint16 sharp[4];
  Uint16 hard[4];
  Uint8 cflags,shape,shovable,collisionLayers,nimages;

Modified instruc from [a45a286a1e] to [09554d80ca].

293
294
295
296
297
298
299




300
301
302
303
304
305
306
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310







+
+
+
+








; Pattern matching
-,=Pattern "P"
-,=PatternS "P*"
-Four
-Eight
-cut

; Inheritance
-Abstract
,Super

; Specials
*Function
*Local
*Label
*String
*Int16

Modified instruc.h from [92a9619b30] to [b1532be7cf].

425
426
427
428
429
430
431



432
433
434
435
436
437
438
439








440
441
442
443
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
425
426
427
428
429
430
431
432
433
434








435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462







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












+







#define OP_PATTERNS 32986
#define OP_PATTERNS_C 35034
#define OP_PATTERNS_E 37082
#define OP_PATTERNS_EC 39130
#define OP_FOUR 32987
#define OP_EIGHT 32988
#define OP_CUT 32989
#define OP_ABSTRACT 32990
#define OP_SUPER 32991
#define OP_SUPER_C 35039
#define OP_FUNCTION 32990
#define OP_LOCAL 32991
#define OP_LABEL 32992
#define OP_STRING 32993
#define OP_INT16 32994
#define OP_INT32 32995
#define OP_DISPATCH 32996
#define OP_USERFLAG 32997
#define OP_FUNCTION 32992
#define OP_LOCAL 32993
#define OP_LABEL 32994
#define OP_STRING 32995
#define OP_INT16 32996
#define OP_INT32 32997
#define OP_DISPATCH 32998
#define OP_USERFLAG 32999
#ifdef HEROMESH_CLASS
static const Op_Names op_names[]={
{"*",8486937},
{"+",8421399},
{"+Move",10584235},
{"-",8421400},
{"-Move",10584236},
{"-rot",8421382},
{".",10518528},
{"/",8486938},
{"ANHH",8389394},
{"ARRIVED",8389124},
{"Abstract",8683742},
{"Animate",8421513},
{"AnimateDead",8421514},
{"Arg1",8552569},
{"Arg2",8552570},
{"Arg3",8552571},
{"Array",8683729},
{"ArrayCell",8421589},
644
645
646
647
648
649
650

651
652
653
654
655
656
657
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662







+







{"Shape",8618045},
{"ShapeDir",8618068},
{"Sharp",8618067},
{"Shovable",8618069},
{"Sound",8421567},
{"Stealthy",8618094},
{"Strength",9142352},
{"Super",8487135},
{"Synchronize",8421568},
{"TAHTASHH",8389409},
{"THMP_thmp",8389405},
{"THWIT",8389384},
{"TICK",8389391},
{"Target",8487105},
{"Temperature",9142331},
766
767
768
769
770
771
772
773

774
771
772
773
774
775
776
777

778
779







-
+

{"then",8683531},
{"tmark",8421577},
{"tuck",8421380},
{"uniq",8421584},
{"until",8683534},
{"while",8683535},
};
#define N_OP_NAMES 330
#define N_OP_NAMES 332
#endif