diff options
Diffstat (limited to 'world.cpp')
-rw-r--r-- | world.cpp | 163 |
1 files changed, 132 insertions, 31 deletions
@@ -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]; } } } |