aboutsummaryrefslogtreecommitdiff
path: root/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'world.cpp')
-rw-r--r--world.cpp163
1 files changed, 132 insertions, 31 deletions
diff --git a/world.cpp b/world.cpp
index 40c49ea..a77b242 100644
--- a/world.cpp
+++ b/world.cpp
@@ -19,6 +19,7 @@ void Robot::load(int idx,const Script &scr){
}
void Robot::tick(World &world){
+ if(active==0)return; // TODO: check whether `waited` needs to be reset
waited++;
Instruction ins=resolve(world);
int dur=calcDuration(ins);
@@ -27,28 +28,56 @@ void Robot::tick(World &world){
execute(ins,world);
}
+uint16_t* Robot::resolveVar(const Argument &arg,World &world){
+ cout<<"resolveVar("<<(int)arg.type<<","<<arg.remote<<","<<arg.num<<","<<arg.name<<")"<<endl;
+ if(arg.remote){
+ assert(arg.type==arg_t::name);
+ assert(arg.name=="active");
+ Robot *target=world.targetbot(this);
+ if(target)return &target->active;
+ else return nullptr;
+ } else {
+ if(arg.type==arg_t::var){
+ return &vars.at(arg.num-1);
+ } else if(arg.type==arg_t::name){
+ assert(arg.name=="active");
+ return &active;
+ } else assert(false);
+ }
+}
+
Instruction Robot::resolve(World &world){
Instruction ins=banks.at(ip.bank).at(ip.pos);
- for(Argument &arg : ins.args){
+ cout<<"Resolving "<<ins<<endl;
+ vector<bool> dstvar(ins.args.size(),false);
+ if(ins.op==ins_t::set||ins.op==ins_t::add||ins.op==ins_t::sub){
+ assert(dstvar.size()>0);
+ dstvar[0]=true;
+ }
+ for(size_t i=0;i<ins.args.size();i++){
+ Argument &arg=ins.args[i];
+ if(dstvar[i]){
+ assert(arg.type==arg_t::var||arg.type==arg_t::name);
+ continue;
+ }
switch(arg.type){
case arg_t::number:
break;
- case arg_t::var:
- assert(!arg.remote);
+ case arg_t::var:{
+ uint16_t *v=resolveVar(arg,world);
+ if(v)arg.num=*v;
+ else arg.num=0;
arg.type=arg_t::number;
- arg.num=vars.at(arg.num-1);
break;
- case arg_t::name:
+ }
+ case arg_t::name:{
assert(arg.name=="active");
+ uint16_t *v=resolveVar(arg,world);
+ if(v)arg.num=*v;
+ else arg.num=0;
arg.type=arg_t::number;
- if(!arg.remote){
- arg.num=active;
- } else {
- Robot *target=world.targetbot(this);
- if(target)arg.num=target->active;
- else arg.num=0;
- }
break;
+ }
case arg_t::constant:
assert(false);
default:
@@ -65,23 +94,96 @@ int Robot::calcDuration(Instruction &ins){
}
int base=C::baseDuration[(int)ins.op];
switch(ins.op){
- case ins_t::set: d+=base;
- case ins_t::add: d+=base;
- case ins_t::sub: d+=base;
- case ins_t::comp: d+=base;
- case ins_t::trans: d+=base+C::pen_transinstr*banks.at(ins.args[0].num).size();
- case ins_t::jump: d+=base;
- case ins_t::bjump: d+=base;
- case ins_t::die: d+=base;
- case ins_t::move: d+=base;
- case ins_t::turn: d+=base;
- case ins_t::scan: d+=base;
- case ins_t::create: d+=(base+C::pen_createbank*ins.args[1].num)*C::pen_createmobilemult+C::pen_createmobile*ins.args[2].num+C::pen_createiset1*(ins.args[0].num==1)+C::pen_createiset2*(ins.args[0].num==2);
+ case ins_t::set: d+=base; break;
+ case ins_t::add: d+=base; break;
+ case ins_t::sub: d+=base; break;
+ case ins_t::comp: d+=base; break;
+ case ins_t::trans: d+=base+C::pen_transinstr*banks.at(ins.args[0].num-1).size(); break;
+ case ins_t::jump: d+=base; break;
+ case ins_t::bjump: d+=base; break;
+ case ins_t::die: d+=base; break;
+ case ins_t::move: d+=base; break;
+ case ins_t::turn: d+=base; break;
+ case ins_t::scan: d+=base; break;
+ case ins_t::create: d+=(base+C::pen_createbank*ins.args[1].num)*C::pen_createmobilemult+C::pen_createmobile*ins.args[2].num+C::pen_createiset1*(ins.args[0].num==1)+C::pen_createiset2*(ins.args[0].num==2); break;
default: assert(false);
}
return d;
}
+void Robot::execute(Instruction &ins,World &world){
+ cout<<"Executing "<<ins<<endl;
+ switch(ins.op){
+ case ins_t::set:{
+ uint16_t *v=resolveVar(ins.args[0],world);
+ if(v)*v=ins.args[1].num;
+ break;
+ }
+
+ case ins_t::add:{
+ uint16_t *v=resolveVar(ins.args[0],world);
+ if(v)*v+=ins.args[1].num;
+ break;
+ }
+
+ case ins_t::sub:{
+ uint16_t *v=resolveVar(ins.args[0],world);
+ if(v)*v-=ins.args[1].num;
+ break;
+ }
+
+ case ins_t::comp:
+ if(ins.args[0].num==ins.args[1].num){
+ advanceIP();
+ }
+ break;
+
+ case ins_t::trans:{
+ Robot *r=world.targetbot(this);
+ if(r){
+ assert(ins.args[0].num<1&&ins.args[0].num>(int)banks.size()&&
+ ins.args[1].num<1&&ins.args[1].num>(int)r->banks.size());
+ r->banks[ins.args[1].num-1]=banks[ins.args[0].num-1];
+ }
+ break;
+ }
+
+ case ins_t::jump:
+ ip.pos+=ins.args[0].num-1;
+ break;
+
+ case ins_t::bjump:
+ ip.bank=ins.args[0].num-1;
+ break;
+
+ case ins_t::die:
+ case ins_t::move:
+ case ins_t::turn:
+ case ins_t::scan:
+ case ins_t::create:
+ assert(false);
+
+ default:
+ assert(false);
+ }
+
+ advanceIP();
+}
+
+void Robot::advanceIP(){
+ ip.pos++;
+ if(!ipInRange()){
+ ip.bank=ip.pos=0;
+ assert(ipInRange());
+ }
+}
+
+bool Robot::ipInRange() const {
+ if(ip.bank<0||ip.bank>=(int)banks.size())return false;
+ if(ip.pos<0||ip.pos>=(int)banks[ip.bank].size())return false;
+ return true;
+}
+
World::World(){
memset(&board[0][0],0,SIZE*SIZE*sizeof(Robot*));
@@ -122,13 +224,12 @@ void World::tick(){
Robot* World::targetbot(const Robot *r){
for(int y=0;y<SIZE;y++){
for(int x=0;x<SIZE;x++){
- if(board[y][x]==r){
- switch(r->heading){
- case 0: return board[y][(x+1)%SIZE];
- case 1: return board[(y+SIZE-1)%SIZE][x];
- case 2: return board[y][(x+SIZE-1)%SIZE];
- case 3: return board[(y+1)%SIZE][x];
- }
+ if(board[y][x]!=r)continue;
+ switch(r->heading%4){
+ case 0: return board[(y+SIZE-1)%SIZE][x];
+ case 1: return board[y][(x+1)%SIZE];
+ case 2: return board[(y+1)%SIZE][x];
+ case 3: return board[y][(x+SIZE-1)%SIZE];
}
}
}