diff options
-rw-r--r-- | world.cpp | 99 | ||||
-rw-r--r-- | world.h | 13 |
2 files changed, 94 insertions, 18 deletions
@@ -18,14 +18,14 @@ void Robot::load(int idx,const Script &scr){ banks[idx]=scr; } -void Robot::tick(World &world){ - if(active==0)return; // TODO: check whether `waited` needs to be reset +WorldAction Robot::tick(World &world){ + if(active==0)return WorldAction::none; // TODO: check whether `waited` needs to be reset waited++; Instruction ins=resolve(world); int dur=calcDuration(ins); - if(dur<waited)return; + if(dur<waited)return WorldAction::none; waited=0; - execute(ins,world); + return execute(ins,world); } uint16_t* Robot::resolveVar(const Argument &arg,World &world){ @@ -50,7 +50,7 @@ Instruction Robot::resolve(World &world){ Instruction ins=banks.at(ip.bank).at(ip.pos); 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){ + if(ins.op==ins_t::set||ins.op==ins_t::add||ins.op==ins_t::sub||ins.op==ins_t::scan){ assert(dstvar.size()>0); dstvar[0]=true; } @@ -111,8 +111,9 @@ int Robot::calcDuration(Instruction &ins){ return d; } -void Robot::execute(Instruction &ins,World &world){ +WorldAction Robot::execute(Instruction &ins,World &world){ cout<<"Executing "<<ins<<endl; + WorldAction action=WorldAction::none; switch(ins.op){ case ins_t::set:{ uint16_t *v=resolveVar(ins.args[0],world); @@ -141,8 +142,8 @@ void Robot::execute(Instruction &ins,World &world){ 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()); + 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; @@ -157,17 +158,46 @@ void Robot::execute(Instruction &ins,World &world){ break; case ins_t::die: + return WorldAction::die; + case ins_t::move: + if(world.targetbot(this)==nullptr){ + action=WorldAction::move; + } + break; + case ins_t::turn: - case ins_t::scan: + if(ins.args[0].num==0)heading=(heading+3)%4; + else heading=(heading+1)%4; + break; + + case ins_t::scan:{ + Robot *r=world.targetbot(this); + uint16_t *v=resolveVar(ins.args[0],world); + if(!v)break; + if(r){ + if(r->team==team)*v=2; + else *v=1; + } else { + *v=0; + } + break; + } + case ins_t::create: - assert(false); + if(world.targetbot(this)!=nullptr)break; + assert(ins.args[0].num>=0&&ins.args[0].num<=2); + assert(ins.args[1].num>=0); + assert((bool)ins.args[2].num==ins.args[2].num); + world.createInFront(this,this->team,ins.args[0].num,ins.args[1].num,ins.args[2].num); + break; default: assert(false); } advanceIP(); + return action; } void Robot::advanceIP(){ @@ -213,29 +243,66 @@ Robot& World::create(const Team *team,int iset,int nbanks,bool mobile){ return *board[y][x]; } +Robot& World::createInFront(const Robot *caller,const Team *team,int iset,int nbanks,bool mobile){ + Robot **ptr=targetbotptr(caller); + Robot *r=new Robot(); + r->team=team; + r->banks.resize(nbanks); + r->iset=iset; + r->mobile=mobile; + r->heading=caller->heading; + *ptr=r; + return *r; +} + void World::tick(){ for(int y=0;y<SIZE;y++){ for(int x=0;x<SIZE;x++){ - if(board[y][x])board[y][x]->tick(*this); + if(!board[y][x])continue; + switch(board[y][x]->tick(*this)){ + case WorldAction::none: break; + + case WorldAction::die: + delete board[y][x]; + board[y][x]=nullptr; + break; + + case WorldAction::move:{ + Robot** ptr=nullptr; + switch(board[y][x]->heading%4){ + case 0: ptr=&board[(y+SIZE-1)%SIZE][x]; break; + case 1: ptr=&board[y][(x+1)%SIZE]; break; + case 2: ptr=&board[(y+1)%SIZE][x]; break; + case 3: ptr=&board[y][(x+SIZE-1)%SIZE]; break; + } + *ptr=board[y][x]; + board[y][x]=nullptr; + break; + } + } } } } -Robot* World::targetbot(const Robot *r){ +Robot** World::targetbotptr(const Robot *r){ for(int y=0;y<SIZE;y++){ for(int x=0;x<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]; + 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]; } } } assert(false); } +Robot* World::targetbot(const Robot *r){ + return *targetbotptr(r); +} + ostream& operator<<(ostream &os,const Argument &arg){ if(arg.remote){ @@ -45,6 +45,12 @@ using Script = vector<Instruction>; class Team; class World; +enum class WorldAction{ + none, + die, + move, +}; + class Robot{ Location ip={0,0}; int waited=0; @@ -53,7 +59,7 @@ class Robot{ uint16_t* resolveVar(const Argument &arg,World &world); Instruction resolve(World &world); int calcDuration(Instruction &ins); - void execute(Instruction &ins,World &world); + WorldAction execute(Instruction &ins,World &world); void advanceIP(); bool ipInRange() const; @@ -69,7 +75,7 @@ public: void load(int idx,const Script &scr); - void tick(World &world); + WorldAction tick(World &world); }; class Team{ @@ -79,6 +85,8 @@ public: }; class World{ + Robot** targetbotptr(const Robot *r); + public: Robot *board[SIZE][SIZE]; @@ -86,6 +94,7 @@ public: ~World(); Robot& create(const Team *team,int iset,int nbanks,bool mobile); + Robot& createInFront(const Robot *caller,const Team *team,int iset,int nbanks,bool mobile); void tick(); Robot* targetbot(const Robot *r); |