9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
#include "smallxrm.h"
#include "heromesh.h"
Uint32 generation_number;
Object*objects;
Uint32 nobjects;
Value globals[0x800];
static jmp_buf my_env;
static int my_error;
int execute_turn(int key) {
if(setjmp(my_env)) return my_error;
return 0;
}
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
#include "smallxrm.h"
#include "heromesh.h"
Uint32 generation_number;
Object**objects;
Uint32 nobjects;
Value globals[0x800];
Uint32 firstobj=VOIDLINK;
Uint32 lastobj=VOIDLINK;
Uint32 playfield[64*64];
typedef struct {
Uint16 msg;
Uint32 from;
Value arg1,arg2,arg3;
} MessageVars;
static jmp_buf my_env;
static const char*my_error;
static MessageVars msgvars;
static char lastimage_processing;
#define Throw(x) (my_error=(x),longjmp(my_env,1))
#define StackReq(x,y)
void pfunlink(Uint32 n) {
Object*o=objects[n];
if(o->down==VOIDLINK) playfield[o->x+o->y*64-65]=o->up;
else objects[o->down]->up=o->up;
if(o->up!=VOIDLINK) objects[o->up]->down=o->down;
o->down=o->up=VOIDLINK;
}
void pflink(Uint32 n) {
Object*o=objects[n];
int p=o->x+o->y*64-65;
if(p<0) return;
if(playfield[p]==VOIDLINK) {
playfield[p]=n;
} else {
Sint32 d=o->density;
Uint32 m=playfield[p];
Uint32 t=VOIDLINK;
while(m!=VOIDLINK && objects[m]->density>=d) t=m,m=objects[m]->up;
o->down=t;
o->up=m;
if(t!=VOIDLINK) objects[t]->up=n; else playfield[p]=n;
if(m!=VOIDLINK) objects[m]->down=n;
}
}
#define OBJECT_ARRAY_BLOCK 256
Uint32 objalloc(Uint16 c) {
// c must be a valid (nonzero) class number, and not a class with CF_GROUP, CF_NOCLASS1, or CF_NOCLASS2 flags.
Uint32 n;
Class*cl=classes[c];
Object*o=calloc(1,sizeof(Object)+cl->uservars*sizeof(Value));
if(!o) fatal("Allocation failed\n");
o->class=c;
o->generation=generation_number;
#define C(x) o->x=cl->x;
C(height) C(weight) C(climb) C(density) C(volume) C(strength) C(arrivals) C(departures) C(temperature)
C(shape) C(shovable) C(oflags)
C(sharp[0]) C(sharp[1]) C(sharp[2]) C(sharp[3])
C(hard[0]) C(hard[1]) C(hard[2]) C(hard[3])
#undef C
o->misc4=NVALUE(cl->misc4);
o->misc5=NVALUE(cl->misc5);
o->misc6=NVALUE(cl->misc6);
o->misc7=NVALUE(cl->misc7);
if(nobjects) for(n=nobjects-1;;n--) {
if(!objects[n]) goto found;
if(!n) break;
}
if(nobjects>=0xFFFF0000L) fatal("Too many objects\n");
objects=realloc(objects,(nobjects+OBJECT_ARRAY_BLOCK)*sizeof(Object*));
if(!objects) fatal("Allocation failed\n");
for(n=nobjects;n<nobjects+OBJECT_ARRAY_BLOCK;n++) objects[n]=0;
n=nobjects;
nobjects+=OBJECT_ARRAY_BLOCK;
found:
o->up=o->down=o->prev=o->next=VOIDLINK;
if(cl->nmsg || classes[0]->nmsg) {
o->prev=lastobj;
if(lastobj!=VOIDLINK) objects[lastobj]->next=n;
lastobj=n;
if(firstobj==VOIDLINK) firstobj=n;
}
objects[n]=o;
return n;
}
static void execute_program(Uint16*code,int ptr,Uint32 obj) {
Object*o=objects[obj];
if(StackProtection()) Throw("Call stack overflow");
for(;;) switch(code[ptr++]) {
case OP_GOTO: ptr=code[ptr]; break;
case OP_CALLSUB: execute_program(code,code[ptr++],obj); break;
case OP_RET: return;
default: Throw("Internal error: Unrecognized opcode");
}
}
static Value send_message(Uint32 from,Uint32 to,Uint16 msg,Value arg1,Value arg2,Value arg3) {
MessageVars saved=msgvars;
Uint16 c=classes[objects[to]->class];
Uint16 p=get_message_ptr(c,msg);
Uint16*code;
if(p==0xFFFF) {
p=get_message_ptr(0,msg);
if(!p) return NVALUE(0);
code=classes[0]->codes;
} else {
code=classes[c]->codes;
}
msgvars={msg,from,arg1,arg2,arg3};
execute_program(code,p,to);
msgvars=saved;
}
void annihilate(void) {
Uint32 i;
if(!objects) return;
for(i=0;i<nobjects;i++) free(objects[i]);
nobjects=0;
free(objects);
objects=0;
firstobj=lastobj=VOIDLINK;
for(i=0;i<64*64;i++) playfield[i]=VOIDLINK;
}
const char*execute_turn(int key) {
if(setjmp(my_env)) return my_error;
lastimage_processing=0;
return 0;
}
|