Free Hero Mesh

Check-in [c0f558d8e6]
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 the other kinds of pattern matching (=P) (P*) (,P*) (=P*) but it is untested so far.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c0f558d8e6b1e1cefa89cecab350a335f61481fe
User & Date: user on 2021-04-25 02:39:17
Other Links: manifest | tags
Context
2021-04-25
19:54
Remove the "el ... if" block, which wasn't working. (Later, I may add a case block instead.) check-in: 932a5231ed user: user tags: trunk
02:39
Implement the other kinds of pattern matching (=P) (P*) (,P*) (=P*) but it is untested so far. check-in: c0f558d8e6 user: user tags: trunk
2021-04-24
19:09
Implement BroadcastAnd and BroadcastList instructions. check-in: a833709837 user: user tags: trunk
Changes

Modified class.doc from [f8fa26ffcf] to [dda42baf1a].

2109
2110
2111
2112
2113
2114
2115

2116



2117



2118


2119












2120
2121
2122
2123
2124
2125
2126
object as the origin of the movement, and that object's direction as the
direction of movement.


=== Pattern matching ===

Where an instruction is expected, you can have pattern matching. This can

be (P <pattern...>) or (,P <pattern...>) where the first one uses the



current location, and the second kind uses the position and direction of



the specified object as the matching. It pushes the found object to the


stack, or pushes zero if the pattern does not match.













<class>
  Match an object of the specified class.

<dir>
  Move in the specified direction. (This does not move any objects; it
  only moves the cursor for pattern matching.) The direction can be







>
|
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>







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
2147
object as the origin of the movement, and that object's direction as the
direction of movement.


=== Pattern matching ===

Where an instruction is expected, you can have pattern matching. This can
be (<operator> <pattern...>) where the operator can be one of:

P
  Find starting at the current location, with the current object's
  direction. Pushes the found object, or zero if not found.

,P
  Find starting at the specified object's location and direction. Pushes
  the found object, or zero if not found.

=P
  Searches everywhere. Pushes the found object, or zero if not found.

P*
  Like P but push all found objects, or pushes nothing if not found.

,P*
  Like ,P but push all found objects, or pushes nothing if not found.

=P*
  Like =P but push all found objects, or pushes nothing if not found.

Inside the pattern, the following commands are allowed (although the
commands that push stuff to the stack should not be used in the patterns
with P* or ,P* or =P*):

<class>
  Match an object of the specified class.

<dir>
  Move in the specified direction. (This does not move any objects; it
  only moves the cursor for pattern matching.) The direction can be

Modified exec.c from [6dbd0b402f] to [834664aa2d].

1784
1785
1786
1787
1788
1789
1790






1791


1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808

1809
1810

1811
1812
1813
1814
1815
1816
1817
1818
1819













1820
1821
1822
1823
1824
1825
1826
    case OP_OBJBOTTOMAT:
      n=obj_bottom_at(x,y);
      break;
    case OP_OBJTOPAT:
      n=obj_top_at(x,y);
      break;
    case OP_RET:






      return n==VOIDLINK?obj_bottom_at(x,y):n;


    case OP_SUB:
      if(vstackptr>=VSTACKSIZE-1) Throw("Stack overflow");
      Push(NVALUE(0));
      break;
    case OP_THEN:
      // This opcode does nothing
      break;
    case OP_TRACE:
      if(main_options['t']) {
        printf("ptr=%d cpi=%d x=%d y=%d dir=%d obj=%lu ",ptr,cpi,x,y,d,(long)n);
        printf("[ptr=%d x=%d y=%d dir=%d]\n",cp[cpi].ptr,cp[cpi].x,cp[cpi].y,cp[cpi].dir);
      }
      break;
    default: Throw("Unimplemented opcode in pattern");
  }
  goto again;
  fail:

  if(vstackptr<cp->depth) Throw("Stack underflow in pattern matching");
  vstackptr=cp[cpi].depth;

  if(!cpi) return VOIDLINK;
  x=cp[cpi].x;
  y=cp[cpi].y;
  d=cp[cpi].dir;
  ptr=cp[cpi].ptr;
  n=VOIDLINK;
  cpi--;
  goto again;
}














// Here is where the execution of a Free Hero Mesh bytecode subroutine is executed.
#define NoIgnore() do{ changed=1; }while(0)
#define GetVariableOf(a,b) (i=v_object(Pop()),i==VOIDLINK?NVALUE(0):b(objects[i]->a))
#define GetVariableOrAttributeOf(a,b) (t2=Pop(),t2.t==TY_CLASS?NVALUE(classes[t2.u]->a):(i=v_object(t2),i==VOIDLINK?NVALUE(0):b(objects[i]->a)))
#define Numeric(a) do{ if((a).t!=TY_NUMBER) Throw("Type mismatch"); }while(0)
#define DivideBy(a) do{ Numeric(a); if(!(a).u) Throw("Division by zero"); }while(0)







>
>
>
>
>
>
|
>
>

















>
|
|
>









>
>
>
>
>
>
>
>
>
>
>
>
>







1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
    case OP_OBJBOTTOMAT:
      n=obj_bottom_at(x,y);
      break;
    case OP_OBJTOPAT:
      n=obj_top_at(x,y);
      break;
    case OP_RET:
      if(all) {
        if(vstackptr>=VSTACKSIZE-1) Throw("Stack overflow");
        if(n==VOIDLINK) n=obj_bottom_at(x,y);
        Push(OVALUE(n));
        goto fail;
      } else {
        return n==VOIDLINK?obj_bottom_at(x,y):n;
      }
      break;
    case OP_SUB:
      if(vstackptr>=VSTACKSIZE-1) Throw("Stack overflow");
      Push(NVALUE(0));
      break;
    case OP_THEN:
      // This opcode does nothing
      break;
    case OP_TRACE:
      if(main_options['t']) {
        printf("ptr=%d cpi=%d x=%d y=%d dir=%d obj=%lu ",ptr,cpi,x,y,d,(long)n);
        printf("[ptr=%d x=%d y=%d dir=%d]\n",cp[cpi].ptr,cp[cpi].x,cp[cpi].y,cp[cpi].dir);
      }
      break;
    default: Throw("Unimplemented opcode in pattern");
  }
  goto again;
  fail:
  if(!all) {
    if(vstackptr<cp->depth) Throw("Stack underflow in pattern matching");
    vstackptr=cp[cpi].depth;
  }
  if(!cpi) return VOIDLINK;
  x=cp[cpi].x;
  y=cp[cpi].y;
  d=cp[cpi].dir;
  ptr=cp[cpi].ptr;
  n=VOIDLINK;
  cpi--;
  goto again;
}

static Uint32 v_pattern_anywhere(Uint16*code,int ptr,char all) {
  int i;
  Uint32 n;
  for(i=0;i<pfheight*64;i++) {
    n=playfield[i];
    if(n!=VOIDLINK) {
      n=v_pattern(code,ptr,n,all);
      if(n!=VOIDLINK && !all) return n;
    }
  }
  return VOIDLINK;
}

// Here is where the execution of a Free Hero Mesh bytecode subroutine is executed.
#define NoIgnore() do{ changed=1; }while(0)
#define GetVariableOf(a,b) (i=v_object(Pop()),i==VOIDLINK?NVALUE(0):b(objects[i]->a))
#define GetVariableOrAttributeOf(a,b) (t2=Pop(),t2.t==TY_CLASS?NVALUE(classes[t2.u]->a):(i=v_object(t2),i==VOIDLINK?NVALUE(0):b(objects[i]->a)))
#define Numeric(a) do{ if((a).t!=TY_NUMBER) Throw("Type mismatch"); }while(0)
#define DivideBy(a) do{ Numeric(a); if(!(a).u) Throw("Division by zero"); }while(0)
2112
2113
2114
2115
2116
2117
2118




2119
2120
2121
2122
2123
2124
2125
    case OP_OBJDIR_C: StackReq(2,1); t2=Pop(); Numeric(t2); i=obj_dir(v_object(Pop()),t2.u); Push(OVALUE(i)); break;
    case OP_OBJLAYERAT: StackReq(3,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); i=obj_layer_at(t1.u,t2.u,t3.u); Push(OVALUE(i)); break;
    case OP_OBJMOVINGTO: StackReq(2,0); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); v_obj_moving_to(t1.u,t2.u); break;
    case OP_OBJTOPAT: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); i=obj_top_at(t1.u,t2.u); Push(OVALUE(i)); break;
    case OP_OVER: StackReq(2,3); t2=Pop(); t1=Pop(); Push(t1); Push(t2); Push(t1); break;
    case OP_PATTERN: StackReq(0,1); i=code[ptr++]; j=v_pattern(code,ptr,obj,0); ptr=i; Push(OVALUE(j)); break;
    case OP_PATTERN_C: StackReq(1,1); i=code[ptr++]; j=v_object(Pop()); if(j!=VOIDLINK) j=v_pattern(code,ptr,j,0); ptr=i; Push(OVALUE(j)); break;




    case OP_PICK: StackReq(0,1); t1=Pop(); Numeric(t1); if(t1.u>=vstackptr) Throw("Stack index out of range"); t1=vstack[vstackptr-t1.u-1]; Push(t1); break;
    case OP_PLAYER: StackReq(0,1); if(classes[o->class]->cflags&CF_PLAYER) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_PLAYER_C: StackReq(1,1); GetClassFlagOf(CF_PLAYER); break;
    case OP_PLUSMOVE: StackReq(1,1); t1=Pop(); Numeric(t1); i=defer_move(obj,t1.u,1); Push(NVALUE(i)); break;
    case OP_PLUSMOVE_C: StackReq(2,1); t1=Pop(); Numeric(t1); i=v_object(Pop()); i=defer_move(i,t1.u,1); Push(NVALUE(i)); break;
    case OP_PLUSMOVE_D: StackReq(1,0); t1=Pop(); Numeric(t1); defer_move(obj,t1.u,1); break;
    case OP_PLUSMOVE_CD: StackReq(2,1); t1=Pop(); Numeric(t1); i=v_object(Pop()); defer_move(i,t1.u,1); break;







>
>
>
>







2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
    case OP_OBJDIR_C: StackReq(2,1); t2=Pop(); Numeric(t2); i=obj_dir(v_object(Pop()),t2.u); Push(OVALUE(i)); break;
    case OP_OBJLAYERAT: StackReq(3,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); i=obj_layer_at(t1.u,t2.u,t3.u); Push(OVALUE(i)); break;
    case OP_OBJMOVINGTO: StackReq(2,0); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); v_obj_moving_to(t1.u,t2.u); break;
    case OP_OBJTOPAT: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); i=obj_top_at(t1.u,t2.u); Push(OVALUE(i)); break;
    case OP_OVER: StackReq(2,3); t2=Pop(); t1=Pop(); Push(t1); Push(t2); Push(t1); break;
    case OP_PATTERN: StackReq(0,1); i=code[ptr++]; j=v_pattern(code,ptr,obj,0); ptr=i; Push(OVALUE(j)); break;
    case OP_PATTERN_C: StackReq(1,1); i=code[ptr++]; j=v_object(Pop()); if(j!=VOIDLINK) j=v_pattern(code,ptr,j,0); ptr=i; Push(OVALUE(j)); break;
    case OP_PATTERN_E: StackReq(0,1); i=code[ptr++]; j=v_pattern_anywhere(code,ptr,0); ptr=i; Push(OVALUE(j)); break;
    case OP_PATTERNS: StackReq(0,1); i=code[ptr++]; v_pattern(code,ptr,obj,1); ptr=i; break;
    case OP_PATTERNS_C: StackReq(1,1); i=code[ptr++]; j=v_object(Pop()); if(j!=VOIDLINK) v_pattern(code,ptr,j,1); ptr=i; break;
    case OP_PATTERNS_E: StackReq(0,1); i=code[ptr++]; v_pattern_anywhere(code,ptr,1); ptr=i; break;
    case OP_PICK: StackReq(0,1); t1=Pop(); Numeric(t1); if(t1.u>=vstackptr) Throw("Stack index out of range"); t1=vstack[vstackptr-t1.u-1]; Push(t1); break;
    case OP_PLAYER: StackReq(0,1); if(classes[o->class]->cflags&CF_PLAYER) Push(NVALUE(1)); else Push(NVALUE(0)); break;
    case OP_PLAYER_C: StackReq(1,1); GetClassFlagOf(CF_PLAYER); break;
    case OP_PLUSMOVE: StackReq(1,1); t1=Pop(); Numeric(t1); i=defer_move(obj,t1.u,1); Push(NVALUE(i)); break;
    case OP_PLUSMOVE_C: StackReq(2,1); t1=Pop(); Numeric(t1); i=v_object(Pop()); i=defer_move(i,t1.u,1); Push(NVALUE(i)); break;
    case OP_PLUSMOVE_D: StackReq(1,0); t1=Pop(); Numeric(t1); defer_move(obj,t1.u,1); break;
    case OP_PLUSMOVE_CD: StackReq(2,1); t1=Pop(); Numeric(t1); i=v_object(Pop()); defer_move(i,t1.u,1); break;