Free Hero Mesh

Diff
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.

Differences From Artifact [484f44c508]:

To Artifact [d3751950c5]:


55
56
57
58
59
60
61

62
63
64
65
66
67
68
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69







+







static Uint8 lastimage_processing,changed,all_flushed;
static Value vstack[VSTACKSIZE];
static int vstackptr;
static const char*traceprefix;
static Uint8 current_key;
static Value quiz_obj;
static Value traced_obj;
static Uint32 control_obj=VOIDLINK;

#define Throw(x) (my_error=(x),longjmp(my_env,1))
#define StackReq(x,y) do{ if(vstackptr<(x)) Throw("Stack underflow"); if(vstackptr-(x)+(y)>=VSTACKSIZE) Throw("Stack overflow"); }while(0)
#define Push(x) (vstack[vstackptr++]=(x))
#define Pop() (vstack[--vstackptr])

// For arrival/departure masks
531
532
533
534
535
536
537




538
539
540
541
542
543
544
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549







+
+
+
+







  if(!((o->oflags|p->oflags)&(OF_VISUALONLY|OF_DESTROYED))) send_message(y,x,MSG_SUNK,NVALUE(0),NVALUE(0),v);
}

static void change_density(Uint32 n,Sint32 v) {
  Object*o=objects[n];
  Uint32 i;
  if(o->oflags&OF_BIZARRO) return;
  if(n==control_obj) {
    o->density=v;
    return;
  }
  if(v<o->density) {
    o->density=v;
    for(;;) {
      i=o->up;
      if(i==VOIDLINK || objects[i]->density<=v) return;
      sink(i,n);
    }
793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812







-
+







static Uint32 create(Uint32 from,Uint16 c,Uint32 x,Uint32 y,Uint32 im,Uint32 d) {
  Uint32 m,n;
  int i,xx,yy;
  Object*o;
  Object*p;
  Value v;
  if(d>7) d=0;
  if(x<1 || y<1 || x>pfwidth || y>pfheight) return VOIDLINK;
  if(x<1 || y<1 || x>pfwidth || y>pfheight || c==control_class) return VOIDLINK;
  if(!(classes[c]->oflags&OF_BIZARRO) && (i=classes[c]->collisionLayers) && (xx=collisions_at(x,y)&i)) {
    if(collide_with(xx,VOIDLINK,x,y,c)&0x01) return VOIDLINK;
  }
  n=objalloc(c);
  if(n==VOIDLINK) Throw("Error creating object");
  o=objects[n];
  o->x=x;
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857







-
+







}

static Value destroy(Uint32 from,Uint32 to,Uint32 why) {
  Object*o;
  Value v;
  int i,x,y,xx,yy;
  Uint32 n;
  if(to==VOIDLINK) return NVALUE(0);
  if(to==VOIDLINK || to==control_obj) return NVALUE(0);
  o=objects[to];
  // EKS Hero Mesh doesn't check if it already destroyed.
  v=why==8?NVALUE(0):send_message(from,to,MSG_DESTROY,NVALUE(0),NVALUE(0),NVALUE(why));
  if(!v_bool(v)) {
    if(!(o->oflags&OF_DESTROYED)) {
      if(firstobj==to) firstobj=o->next;
      if(lastobj==to) lastobj=o->prev;
875
876
877
878
879
880
881
882

883
884
885
886
887
888
889
880
881
882
883
884
885
886

887
888
889
890
891
892
893
894







-
+








static int move_to(Uint32 from,Uint32 n,Uint32 x,Uint32 y) {
  Uint32 m;
  int i,xx,yy;
  Object*o;
  Object*p;
  Value v;
  if(n==VOIDLINK || (objects[n]->oflags&OF_DESTROYED)) return 0;
  if(n==VOIDLINK || (objects[n]->oflags&OF_DESTROYED) || n==control_obj) return 0;
  o=objects[n];
  if(lastimage_processing) Throw("Can't move during animation processing");
  if(x<1 || y<1 || x>pfwidth || y>pfheight) return 0;
  if(v_bool(send_message(from,n,MSG_MOVING,NVALUE(x),NVALUE(y),NVALUE(0)))) return 0;
  if(classes[o->class]->cflags&CF_PLAYER) {
    m=lastobj;
    while(m!=VOIDLINK) {
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1201
1202
1203
1204
1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
1215







-
+








static int defer_move(Uint32 obj,Uint32 dir,Uint8 plus) {
  Object*o;
  Object*q;
  Uint32 n;
  Value v;
  if(StackProtection()) Throw("Call stack overflow during movement");
  if(obj==VOIDLINK) return 0;
  if(obj==VOIDLINK || obj==control_obj) return 0;
  o=objects[obj];
  if(o->oflags&(OF_DESTROYED|OF_BIZARRO)) return 0;
  dir=resolve_dir(obj,dir);
  if(plus) {
    if(o->oflags&OF_MOVING) {
      if(o->dir==dir) return 1;
      v=send_message(VOIDLINK,obj,MSG_CONFLICT,NVALUE(dir),NVALUE(0),NVALUE(0));
1280
1281
1282
1283
1284
1285
1286
1287

1288
1289
1290
1291
1292
1293
1294
1285
1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296
1297
1298
1299







-
+







  if(current_key) all_flushed=255;
  flush_class(0);
}

static void set_bizarro(Uint32 n,Uint32 v) {
  Object*o;
  Uint8 b;
  if(n==VOIDLINK) return;
  if(n==VOIDLINK || n==control_obj) return;
  o=objects[n];
  if(o->oflags&OF_DESTROYED) return;
  if(v) {
    if(o->oflags&OF_BIZARRO) return;
    pfunlink(n);
    o->oflags|=OF_BIZARRO;
    pflink(n);
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879







+







  Uint8 d=objects[obj]->dir;
  Uint32 n=VOIDLINK;
  Uint32 m;
  Uint16 g;
  Value v;
  static ChoicePoint cp[MAXCHOICE];
  Uint8 cpi=0;
  if(!x) return VOIDLINK;
  cp->depth=vstackptr;
  again: switch(code[ptr++]) {
    case 0 ... 7:
      n=VOIDLINK;
      x+=x_delta[code[ptr-1]];
      y+=y_delta[code[ptr-1]];
      if(x<1 || x>pfwidth || y<1 || y>pfheight) goto fail;
1909
1910
1911
1912
1913
1914
1915

1916
1917
1918
1919
1920
1921
1922
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929







+







          if(v.u==1) goto fail;
          else if(v.u==2) break;
          else if(v.u) Throw("Invalid return value from message in pattern matching");
        } else if(v.t>TY_MAXTYPE) {
          n=v_object(v);
          x=objects[n]->x;
          y=objects[n]->y;
          if(!x) return VOIDLINK;
        } else {
          Throw("Type mismatch");
        }
        m=objects[m]->up;
      }
      break;
    case OP_ADD:
1993
1994
1995
1996
1997
1998
1999

2000
2001
2002
2003
2004
2005
2006
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014







+







        d=v.u&7;
      } else if(v.t==TY_MARK) {
        goto fail;
      } else if(v.t>TY_MAXTYPE) {
        n=v_object(v);
        x=objects[n]->x;
        y=objects[n]->y;
        if(!x) return VOIDLINK;
      } else {
        Throw("Type mismatch");
      }
      break;
    case OP_HEIGHT:
      if(playfield[x+y*64-65]==VOIDLINK || height_at(x,y)<=objects[obj]->climb) goto fail;
      break;
2468
2469
2470
2471
2472
2473
2474

2475
2476
2477
2478
2479
2480
2481
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490







+







    case OP_CLIMB_EC16: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) o->climb=t1.u&0xFFFF; break;
    case OP_COLLISIONLAYERS: StackReq(0,1); Push(NVALUE(classes[o->class]->collisionLayers)); break;
    case OP_COLLISIONLAYERS_C: StackReq(1,1); i=v_object(Pop()); if(i==VOIDLINK) Push(NVALUE(0)); else Push(NVALUE(classes[objects[i]->class]->collisionLayers)); break;
    case OP_COLOC: StackReq(1,1); t1=Pop(); i=colocation(obj,v_object(t1)); Push(NVALUE(i)); break;
    case OP_COLOC_C: StackReq(2,1); t1=Pop(); t2=Pop(); i=colocation(v_object(t1),v_object(t2)); Push(NVALUE(i)); break;
    case OP_COMPATIBLE: StackReq(0,1); if(classes[o->class]->cflags&CF_COMPATIBLE) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_COMPATIBLE_C: StackReq(1,1); GetClassFlagOf(CF_COMPATIBLE); break;
    case OP_CONTROL: StackReq(0,1); Push(OVALUE(control_obj)); break;
    case OP_COPYARRAY: NoIgnore(); StackReq(2,0); t2=Pop(); t1=Pop(); v_copy_array(t1,t2); break;
    case OP_COUNT: StackReq(1,2); i=v_count(); Push(NVALUE(i)); break;
    case OP_CREATE: NoIgnore(); StackReq(5,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_create(obj,t1,t2,t3,t4,t5)); break;
    case OP_CREATE_D: NoIgnore(); StackReq(5,0); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_create(obj,t1,t2,t3,t4,t5); break;
    case OP_DATA: StackReq(2,1); t2=Pop(); t1=Pop(); v_data(t1,t2); break;
    case OP_DELINVENTORY: StackReq(2,0); t2=Pop(); t1=Pop(); v_delete_inventory(t1,t2); break;
    case OP_DELTA: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u>t2.u?t1.u-t2.u:t2.u-t1.u)); break;
2913
2914
2915
2916
2917
2918
2919

2920
2921
2922
2923
2924
2925
2926
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936







+







  gameover=0;
  clear_inventory();
  for(i=0;i<nlevelstrings;i++) free(levelstrings[i]);
  nlevelstrings=0;
  free(deadanim);
  deadanim=0;
  ndeadanim=0;
  control_obj=VOIDLINK;
}

static inline int try_sharp(Uint32 n1,Uint32 n2) {
  Object*o=objects[n1];
  Object*p=objects[n2];
  if((o->oflags|p->oflags)&OF_DESTROYED) return 0;
  if(o->dir&1) return 0;
3301
3302
3303
3304
3305
3306
3307




3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331







+
+
+
+










  changed=0;
  key_ignored=0;
  all_flushed=0;
  lastimage_processing=0;
  vstackptr=0;
  move_number=0;
  current_key=0;
  if(control_class) {
    control_obj=objalloc(control_class);
    if(control_obj==VOIDLINK) Throw("Error creating object");
  }
  n=lastobj;
  while(n!=VOIDLINK && !(objects[n]->oflags&OF_ORDERED)) {
    send_message(VOIDLINK,n,MSG_INIT,NVALUE(0),NVALUE(0),NVALUE(0));
    if(classes[objects[n]->class]->order && !(objects[n]->oflags&OF_DESTROYED)) set_order(n);
    n=objects[n]->prev;
  }
  broadcast(VOIDLINK,0,MSG_POSTINIT,NVALUE(0),NVALUE(0),NVALUE(0),0);
  if(gameover) return 0;
  return execute_turn(0);
}