ccdevnet / openc2e

openc2e

This URL has Read+Write access

openc2e / bytecode.h
100644 178 lines (160 sloc) 3.747 kb
1
2
3
4
5
6
7
8
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#ifndef BYTECODE_H
#define BYTECODE_H 1
 
#include "caosVM.h"
#include "lexutil.h"
#include "cmddata.h"
 
class script;
 
typedef void (caosVM::*ophandler)();
class caosOp {
public:
virtual void execute(caosVM *vm) {
vm->timeslice -= evalcost;
vm->nip = successor;
}
void setSuccessor(caosOp *succ) {
successor = succ;
}
void setCost(int cost) {
evalcost = cost;
}
caosOp() : evalcost(1), successor(NULL), owned(false), yyline(lex_lineno) {}
virtual ~caosOp() {};
int getlineno() const { return yyline; }
protected:
int yyline; // HORRIBLE HACK
int evalcost;
caosOp *successor;
bool owned; // if it's been addOp()ed
friend void script::addOp(caosOp *op);
};
 
class caosNoop : public caosOp {
public:
caosNoop() { evalcost = 0; }
};
 
class simpleCaosOp : public caosOp {
protected:
ophandler handler;
int idx;
public:
simpleCaosOp(ophandler h, int i) : handler(h), idx(i) {}
void execute(caosVM *vm) {
caosOp::execute(vm);
int stackc = vm->valueStack.size();
(vm->*handler)();
int delta = vm->valueStack.size() - stackc;
if (!vm->result.isNull())
delta++;
if (cmds[idx].retc != -1 &&
delta != cmds[idx].retc - cmds[idx].argc) {
std::cerr << "Warning: return count mismatch for op "
<< cmds[idx].fullname << ", delta=" << delta
<< std::endl;
}
}
};
 
class caosREPS : public caosOp {
protected:
caosOp *exit;
public:
caosREPS(caosOp *exit_) : exit(exit_) {}
void execute(caosVM *vm) {
caosOp::execute(vm);
VM_PARAM_INTEGER(i)
caos_assert(i >= 0);
if (i == 0) {
vm->nip = exit;
return;
}
vm->result.setInt(i - 1);
}
};
 
class caosGSUB : public caosOp {
protected:
caosOp *targ;
public:
caosGSUB(caosOp *targ_) : targ(targ_) {}
void execute(caosVM *vm) {
caosOp::execute(vm);
callStackItem i;
i.valueStack = vm->valueStack; // XXX: a bit slow?
i.nip = vm->nip;
vm->callStack.push_back(i);
vm->valueStack.clear();
vm->nip = targ;
}
};
 
// Condition classes
#define CEQ 1
#define CLT 2
#define CGT 4
#define CLE (CEQ | CLT)
#define CGE (CEQ | CGT)
#define CNE (CLT | CGT)
 
class caosCond : public caosOp {
protected:
int cond;
caosOp *branch;
public:
caosCond(int condition, caosOp *br)
: cond(condition), branch(br) {}
void execute(caosVM *vm) {
caosOp::execute(vm);
 
VM_PARAM_VALUE(arg2);
VM_PARAM_VALUE(arg1);
 
int cres;
if (arg2.hasString() && arg1.hasString()) {
std::string str1 = arg1.getString();
std::string str2 = arg2.getString();
 
if (str1 < str2)
cres = CLT;
else if (str1 > str2)
cres = CGT;
else
cres = CEQ;
} else if (arg2.hasDecimal() && arg1.hasDecimal()) {
float val1 = arg1.getFloat();
float val2 = arg2.getFloat();
 
if (val1 < val2)
cres = CLT;
else if (val1 > val2)
cres = CGT;
else
cres = CEQ;
} else if (arg2.hasAgent() && arg1.hasAgent()) {
if (cond != CEQ && cond != CNE)
throw creaturesException("invalid comparison for agents");
Agent *a1, *a2;
a1 = arg1.getAgent();
a2 = arg2.getAgent();
if (a1 == a2)
cres = CEQ;
else
cres = CNE;
// the next bit is needed for some missing GAME etc
} else cres = CNE;
 
if (cres & cond)
vm->nip = branch;
}
};
 
class caosENUM_POP : public caosOp {
protected:
caosOp *exit;
public:
caosENUM_POP(caosOp *exit_) : exit(exit_) {}
void execute(caosVM *vm) {
caosOp::execute(vm);
VM_PARAM_VALUE(v);
if (v.isNull()) { // no more values
vm->nip = exit;
vm->targ = vm->owner;
return;
}
if (v.getAgent() == NULL) { // killed?
vm->nip = vm->cip;
return;
}
vm->setTarg(v.getAgent());
}
};
 
#endif
 
/* vim: set noet: */