Index: TODO ================================================================== --- TODO +++ TODO @@ -7,11 +7,10 @@ * Game engine features * Multiple connected objects moving as a unit * Bizarro world * Testing the deferred movement * String data (?) - * Array operations (CopyArray, ArraySlice, DotProduct) * A ,PopUp command to use a popup with arguments starting from a mark * Operations with marks (duplicate a list, length of a list, etc) * "Goto message" instruction * Class inheritance (abstract) * Case blocks Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -1069,10 +1069,14 @@ ArrayCell ( array row column -- array ) Make a reference to a single cell of an array. The new reference is treated as a reference to a 1x1 array, which aliases the original array. Coordinates are zero-based. +ArraySlice ( array start count -- array ) + Make a slice of an array. The new reference aliases the original array. + Coordinates are zero-based. + Assassinate ( -- ) ** Destroy this object without sending any messages. The object is marked as destroyed, but its variables are still accessible until the garbage collector runs (during the trigger step for combatible objects, and during the cleanup step for all objects). Assassination always succeeds, @@ -1146,10 +1150,13 @@ ,Coloc ( obj1 obj2 -- bool ) True if the two specified objects are in the same place, or false otherwise. Always false if the object is destroyed, or if one object is in the bizarro world and the other one isn't. +CopyArray ( src dest -- ) ** + Copy one array to another. It is OK if the two references overlap. + Create ( class x y image dir -- obj ) ** Creates a new object at the specified location, and returns it. The result is zero if the class is zero, the coordinates are out of range, the object cannot be created due to the CollisionLayers, or if the new object is destroyed before its CREATE message returns. @@ -1170,10 +1177,19 @@ the return value will be the result of this instruction, and if it is false then it is destroyed, and if true then the destruction fails. ,Destroy ( object -- value ) ** Destroy the specified object (as Destroy but for any object). + +DotProduct ( array array -- any ) + Compute the dot product of two arrays. Any nonzero number times a class, + message, or object will shortcut and return that class, message, or + object; zero can multiply by any value of any type to make zero; a class + by an object will return that object if the class is correct; an object + by a message will send that message to that object, and add the return + value to the running total, or stop and return that value if the return + value isn't a number. dup ( x -- x x ) eq ( in1 in2 -- bool ) Test if they are equal. Sounds cannot be compared, but you can compare Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -1281,10 +1281,66 @@ s=ar.u&0xFFFF; if(y>((ar.u>>16)&0x3FF) || x>((ar.u>>26)&0x3F)) Throw("Array index out of bounds"); s+=x+y+((ar.u>>26)&0x3F)*y; return UVALUE(s,TY_ARRAY); } + +static Value v_array_slice(Value ar,Uint32 x,Uint32 y) { + // Is this correct? I am not sure. + if(ar.t!=TY_ARRAY) Throw("Type mismatch"); + if((x|y)&~0xFFFF) Throw("Slice out of range"); + if(x+y>((ar.u>>16)&0x3FF)-1) Throw("Slice out of range"); + ar.u+=((ar.u>>26)&0x3F)*x-((x+y)<<16); + return ar; +} + +static void v_copy_array(Value a1,Value a2) { + Uint32 n; + if(!a2.t && !a2.u) return; + if(a1.t!=TY_ARRAY || a2.t!=TY_ARRAY) Throw("Type mismatch"); + if(a1.u==a2.u) return; + if((a1.u^a2.u)>>16) Throw("Dimension mismatch"); + n=((a1.u>>16)&0x3FF)+1; + n*=((a1.u>>26)&0x3F)+1; + memmove(array_data+(a2.u&0xFFFF),array_data+(a1.u&0xFFFF),n*sizeof(Value)); +} + +static Value v_dot_product(Value a1,Value a2) { + Uint32 r=0; + Uint32 s1,s2,n; + Value v1,v2; + if(a1.t!=TY_ARRAY || a2.t!=TY_ARRAY) Throw("Type mismatch"); + if((a1.u^a2.u)>>16) Throw("Dimension mismatch"); + s1=a1.u&0xFFFF; + s2=a2.u&0xFFFF; + n=((a1.u>>16)&0x3FF)+1; + n*=((a1.u>>26)&0x3F)+1; + while(n--) { + v1=array_data[s1++]; + v2=array_data[s2++]; + if((v1.t==TY_NUMBER && !v1.u) || (v2.t==TY_NUMBER && !v2.u)) continue; + if(v1.t==TY_NUMBER && v2.t==TY_NUMBER) { + r+=v1.u*v2.u; + } else if(v1.t==TY_NUMBER && (v2.t==TY_CLASS || v2.t==TY_MESSAGE || v2.t>TY_MAXTYPE)) { + return v2; + } else if(v2.t==TY_NUMBER && (v1.t==TY_CLASS || v1.t==TY_MESSAGE || v1.t>TY_MAXTYPE)) { + return v1; + } else if(v1.t==TY_MESSAGE && v2.t>TY_MAXTYPE) { + v1=send_message(VOIDLINK,v_object(v2),v1.u,NVALUE(0),NVALUE(0),NVALUE(0)); + mess: + if(v1.t==TY_SOUND || v1.t==TY_USOUND) Throw("Type mismatch"); + if(v1.t!=TY_NUMBER) return v1; + r+=v1.u; + } else if(v2.t==TY_MESSAGE && v1.t>TY_MAXTYPE) { + v1=send_message(VOIDLINK,v_object(v1),v2.u,NVALUE(0),NVALUE(0),NVALUE(0)); + goto mess; + } else { + Throw("Type mismatch"); + } + } + return NVALUE(r); +} static void v_set_popup(Uint32 from,int argc) { const unsigned char*t; const unsigned char*u; sqlite3_str*s; @@ -1829,10 +1885,11 @@ case OP_ARG2: StackReq(0,1); Push(msgvars.arg2); break; case OP_ARG2_E: StackReq(1,0); msgvars.arg2=Pop(); break; case OP_ARG3: StackReq(0,1); Push(msgvars.arg3); break; case OP_ARG3_E: StackReq(1,0); msgvars.arg3=Pop(); break; case OP_ARRAYCELL: StackReq(3,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); t1=Pop(); Push(v_array_cell(t1,t2.u,t3.u)); break; + case OP_ARRAYSLICE: StackReq(3,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); t1=Pop(); Push(v_array_slice(t1,t2.u,t3.u)); break; case OP_ARRIVALS: StackReq(0,1); Push(NVALUE(o->arrivals&0x1FFFFFF)); break; case OP_ARRIVALS_C: StackReq(1,1); Push(GetVariableOrAttributeOf(arrivals&0x1FFFFFF,NVALUE)); break; case OP_ARRIVALS_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->arrivals=t1.u; break; case OP_ARRIVALS_EC: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->arrivals=t1.u; break; case OP_ARRIVED: StackReq(0,1); Push(NVALUE(o->arrived&0x1FFFFFF)); break; @@ -1872,10 +1929,11 @@ 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_COPYARRAY: NoIgnore(); StackReq(2,0); t2=Pop(); t1=Pop(); v_copy_array(t1,t2); 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_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; case OP_DENSITY: StackReq(0,1); Push(NVALUE(o->density)); break; @@ -1911,10 +1969,11 @@ case OP_DIV_C: StackReq(2,1); t2=Pop(); DivideBy(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.s/t2.s)); break; case OP_DONE: StackReq(0,1); if(o->oflags&OF_DONE) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_DONE_C: StackReq(1,1); GetFlagOf(OF_DONE); break; case OP_DONE_E: StackReq(1,0); if(v_bool(Pop())) o->oflags|=OF_DONE; else o->oflags&=~OF_DONE; break; case OP_DONE_EC: StackReq(2,0); SetFlagOf(OF_DONE); break; + case OP_DOTPRODUCT: StackReq(2,1); t2=Pop(); t1=Pop(); Push(v_dot_product(t1,t2)); break; case OP_DROP: StackReq(1,0); Pop(); break; case OP_DROP_D: StackReq(2,0); Pop(); Pop(); break; case OP_DUP: StackReq(1,2); t1=Pop(); Push(t1); Push(t1); break; case OP_EQ: StackReq(2,1); t2=Pop(); t1=Pop(); Push(NVALUE(v_equal(t1,t2)?1:0)); break; case OP_EQ2: StackReq(4,1); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(NVALUE(v_equal(t1,t3)?(v_equal(t2,t4)?1:0):0)); break; Index: instruc ================================================================== --- instruc +++ instruc @@ -277,10 +277,13 @@ -Array GetArray InitArray SetArray ArrayCell +ArraySlice +CopyArray +DotProduct ; Pattern matching -,=Pattern "P" -,=PatternS "P*" -Four Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -405,29 +405,32 @@ #define OP_ARRAY 32969 #define OP_GETARRAY 32970 #define OP_INITARRAY 32971 #define OP_SETARRAY 32972 #define OP_ARRAYCELL 32973 -#define OP_PATTERN 32974 -#define OP_PATTERN_C 35022 -#define OP_PATTERN_E 37070 -#define OP_PATTERN_EC 39118 -#define OP_PATTERNS 32975 -#define OP_PATTERNS_C 35023 -#define OP_PATTERNS_E 37071 -#define OP_PATTERNS_EC 39119 -#define OP_FOUR 32976 -#define OP_EIGHT 32977 -#define OP_CUT 32978 -#define OP_FUNCTION 32979 -#define OP_LOCAL 32980 -#define OP_LABEL 32981 -#define OP_STRING 32982 -#define OP_INT16 32983 -#define OP_INT32 32984 -#define OP_DISPATCH 32985 -#define OP_USERFLAG 32986 +#define OP_ARRAYSLICE 32974 +#define OP_COPYARRAY 32975 +#define OP_DOTPRODUCT 32976 +#define OP_PATTERN 32977 +#define OP_PATTERN_C 35025 +#define OP_PATTERN_E 37073 +#define OP_PATTERN_EC 39121 +#define OP_PATTERNS 32978 +#define OP_PATTERNS_C 35026 +#define OP_PATTERNS_E 37074 +#define OP_PATTERNS_EC 39122 +#define OP_FOUR 32979 +#define OP_EIGHT 32980 +#define OP_CUT 32981 +#define OP_FUNCTION 32982 +#define OP_LOCAL 32983 +#define OP_LABEL 32984 +#define OP_STRING 32985 +#define OP_INT16 32986 +#define OP_INT32 32987 +#define OP_DISPATCH 32988 +#define OP_USERFLAG 32989 #ifdef HEROMESH_CLASS static const Op_Names op_names[]={ {"*",8486937}, {"+",8421399}, {"+Move",10584230}, @@ -443,10 +446,11 @@ {"Arg1",8552569}, {"Arg2",8552570}, {"Arg3",8552571}, {"Array",8683721}, {"ArrayCell",8421581}, +{"ArraySlice",8421582}, {"Arrivals",8618086}, {"Arrived",8618084}, {"Assassinate",8487050}, {"B",9437196}, {"BANG",8389380}, @@ -479,10 +483,11 @@ {"Class",8486970}, {"Climb",9142350}, {"CollisionLayers",8487029}, {"Coloc",8487058}, {"Compatible",8487028}, +{"CopyArray",8421583}, {"Create",10518675}, {"DEEP_POP",8389417}, {"DEPARTED",8389125}, {"DESTROY",8389122}, {"DESTROYED",8389136}, @@ -499,23 +504,24 @@ {"Destroy",10584214}, {"Destroyed",8487026}, {"Dir",8618048}, {"Distance",9142340}, {"Done",8618097}, +{"DotProduct",8421584}, {"E",9437184}, {"END_TURN",8389139}, {"EditorHelp",8683654}, -{"Eight",8683729}, +{"Eight",8683732}, {"F",9437192}, {"FAROUT",8389421}, {"FFFFTT",8389399}, {"FLOATED",8389132}, {"FROG",8389383}, {"Finished",8552575}, {"FlushClass",8421527}, {"FlushObj",8487064}, -{"Four",8683728}, +{"Four",8683731}, {"From",8421496}, {"GLASS",8389379}, {"GLISSANT",8389419}, {"GetArray",8421578}, {"GetInventory",8421529}, @@ -589,12 +595,12 @@ {"ObjClassAt",8421550}, {"ObjDir",8487087}, {"ObjLayerAt",8421552}, {"ObjMovingTo",8421553}, {"ObjTopAt",8421554}, -{"P",8880334}, -{"P*",8880335}, +{"P",8880337}, +{"P*",8880338}, {"PLAYERMOVING",8389133}, {"POSTINIT",8389138}, {"POUR",8389377}, {"POWER",8389386}, {"Player",8487027}, @@ -698,11 +704,11 @@ {"bnot",8421412}, {"bor",8421410}, {"bxor",8421411}, {"c?",8421427}, {"chain",8421520}, -{"cut",8683730}, +{"cut",8683733}, {"cz?",8421428}, {"dup",8421377}, {"el",8683532}, {"else",8683530}, {"eq",8421418}, @@ -746,7 +752,7 @@ {"tmark",8421572}, {"tuck",8421380}, {"until",8683535}, {"while",8683536}, }; -#define N_OP_NAMES 319 +#define N_OP_NAMES 322 #endif