#include #include #include #include "world.h" using namespace std; Argument::~Argument(){} Instruction Instruction::make(ins_t op,vector args){ return {op,args}; } void Robot::load(int idx,const Script &scr){ banks[idx]=scr; } WorldAction Robot::tick(World &world){ if(active==0)return WorldAction::none; // TODO: check whether `waited` needs to be reset if(!ipInRange()){ ip.bank=ip.pos=0; assert(ipInRange()); } waited++; Instruction ins=resolve(world); int dur=calcDuration(ins); if(waitedactive; 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); // cout< dstvar(ins.args.size(),false); 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; } for(size_t i=0;i=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; ip.pos=ins.args[1].num-1; 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: 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: 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(){ 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*)); } World::~World(){ for(int y=0;yteam=team; board[y][x]->banks.resize(nbanks); board[y][x]->iset=iset; board[y][x]->mobile=mobile; board[y][x]->heading=heading%4; 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::removeRobot(const Robot *r){ *botptr(r)=nullptr; } void World::removeTeam(const Team *team){ for(int y=0;yteam==team){ board[y][x]=nullptr; } } } } void World::tick(){ for(int y=0;ytick(*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::botptr(const Robot *r){ for(int y=0;yheading%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]; } } } assert(false); } Robot* World::targetbot(const Robot *r){ return *targetbotptr(r); } void World::print(ScreenBuffer &sb) const { for(int y=0;yheading%4]; char c1=board[y][x]->active?c2:'X'; sb.printf("%c%c",c1,c2); } sb.printf(" "); } } } ostream& operator<<(ostream &os,const Argument &arg){ if(arg.remote){ switch(arg.type){ case arg_t::number: return os<