27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
+
|
Uint32 firstobj=VOIDLINK;
Uint32 lastobj=VOIDLINK;
Uint32 playfield[64*64]; // bottom-most object per cell
Uint8 pfwidth,pfheight;
Sint8 gameover,key_ignored;
Uint8 generation_number_inc;
Uint32 move_number;
unsigned char*quiz_text;
typedef struct {
Uint16 msg;
Uint32 from;
Value arg1,arg2,arg3;
} MessageVars;
|
909
910
911
912
913
914
915
916
917
918
919
920
921
922
|
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
return send_message(from,v_object(to),msg.u,arg1,arg2,arg3);
}
static inline Value v_send_self(Uint32 from,Value msg,Value arg1,Value arg2,Value arg3) {
if(msg.t!=TY_MESSAGE) Throw("Type mismatch");
return send_message(from,from,msg.u,arg1,arg2,arg3);
}
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;
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");
s=sqlite3_str_new(userdb);
t=value_string_ptr(v);
while(*t) {
if(u=strchr(t,'%')) {
sqlite3_str_append(s,t,u-t);
t=u+2;
switch(u[1]) {
case 0:
t=u+1;
break;
case 'c':
if(argi==argc) break;
v=vstack[vstackptr+argi++];
if(v.t==TY_NUMBER) {
sqlite3_str_appendchar(s,1,31);
sqlite3_str_appendchar(s,1,v.u&255?:255);
}
break;
case 'd':
if(argi==argc) break;
v=vstack[vstackptr+argi++];
if(v.t==TY_NUMBER) sqlite3_str_appendf(s,"%d",(signed int)v.s);
break;
case 'i':
if(argi>=argc-1) break;
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 's':
if(argi==argc) break;
v=vstack[vstackptr+argi++];
switch(v.t) {
case TY_STRING: case TY_LEVELSTRING:
sqlite3_str_appendf(s,"%s",value_string_ptr(v));
break;
case TY_NUMBER:
sqlite3_str_appendf(s,"%llu",(sqlite3_int64)v.u);
break;
case TY_CLASS:
sqlite3_str_appendf(s,"%s",classes[v.u]->name);
break;
default:
Throw("Type mismatch");
}
break;
case 'u':
if(argi==argc) break;
v=vstack[vstackptr+argi++];
if(v.t==TY_NUMBER) sqlite3_str_appendf(s,"%u",(unsigned int)v.u);
break;
case 'x':
if(argi==argc) break;
v=vstack[vstackptr+argi++];
if(v.t==TY_NUMBER) sqlite3_str_appendf(s,"%x",(unsigned int)v.u);
break;
case 'X':
if(argi==argc) break;
v=vstack[vstackptr+argi++];
if(v.t==TY_NUMBER) sqlite3_str_appendf(s,"%X",(unsigned int)v.u);
break;
case '%':
sqlite3_str_appendchar(s,1,'%');
break;
}
} else {
sqlite3_str_appendall(s,t);
break;
}
}
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;
case TY_NUMBER:
quiz_text=sqlite3_mprintf("%llu",(sqlite3_int64)v.u);
break;
case TY_CLASS:
quiz_text=sqlite3_mprintf("%s",classes[v.u]->name);
break;
default:
Throw("Type mismatch");
}
}
if(!quiz_text) fatal("Allocation failed\n");
t=quiz_text;
while(*t) {
if(*t==16) {
quiz_obj.t=objects[from]->generation?:1;
quiz_obj.u=from;
}
if(*t==31 && t[1]) t+=2; else t+=1;
}
}
// 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)
|
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
|
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
|
+
+
|
case OP_OBJCLASSAT: StackReq(3,1); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_obj_class_at(t1,t2,t3)); break;
case OP_OBJDIR: StackReq(1,1); t2=Pop(); Numeric(t2); i=obj_dir(obj,t2.u); Push(OVALUE(i)); break;
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_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_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_POPUP: StackReq(1,0); v_set_popup(obj,0); break;
case OP_POPUPARGS: i=code[ptr++]; StackReq(i+1,0); v_set_popup(obj,i); break;
case OP_RET: return;
case OP_ROT: StackReq(3,3); t3=Pop(); t2=Pop(); t1=Pop(); Push(t2); Push(t3); Push(t1); break;
case OP_ROTBACK: StackReq(3,3); t3=Pop(); t2=Pop(); t1=Pop(); Push(t3); Push(t1); Push(t2); break;
case OP_RSH: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t2.u&~31?0:t1.u>>t2.u)); break;
case OP_RSH_C: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t2.u&~31?(t1.s<0?-1:0):t1.s>>t2.u)); break;
case OP_SELF: StackReq(0,1); Push(OVALUE(obj)); break;
case OP_SEND: StackReq(3,1); t4=Pop(); t3=Pop(); t2=Pop(); Push(v_send_self(obj,t2,t3,t4,NVALUE(0))); break;
|
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
|
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
|
+
|
case OP_STEALTHY_EC: NoIgnore(); StackReq(2,0); SetFlagOf(OF_STEALTHY); break;
case OP_STRENGTH: StackReq(0,1); Push(NVALUE(o->strength)); break;
case OP_STRENGTH_C: StackReq(1,1); Push(GetVariableOrAttributeOf(strength,NVALUE)); break;
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) o->strength=t1.u; break;
case OP_STRENGTH_EC16: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) o->strength=t1.u; 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_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_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;
|
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
|
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
|
+
+
+
+
+
|
if(key_ignored) {
quiz_obj=NVALUE(0);
return changed?"Invalid use of IgnoreKey":0;
}
move_number++;
// Beginning phase
if(!all_flushed) broadcast(m,0,MSG_BEGIN_TURN,m==VOIDLINK?NVALUE(objects[m]->x):NVALUE(0),m==VOIDLINK?NVALUE(objects[m]->y):NVALUE(0),v,0);
// Trigger phase
// Ending phase
// Animation phase
// Cleanup phase
for(n=0;n<nobjects;n++) if(objects[n] && (objects[n]->oflags&OF_DESTROYED)) objtrash(n);
if(generation_number<=TY_MAXTYPE) return "Too many generations of objects";
return 0;
}
|