diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-03-01 15:53:02 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-03-01 15:53:02 +0100 |
commit | fd56574a4d60e553c610615660198f0a84bcb7a1 (patch) | |
tree | bd9e1dd576fa4494187a5176099772f22aeb360c /world.cpp |
Initial
Diffstat (limited to 'world.cpp')
-rw-r--r-- | world.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/world.cpp b/world.cpp new file mode 100644 index 0000000..e99ce97 --- /dev/null +++ b/world.cpp @@ -0,0 +1,199 @@ +#include <cstdlib> +#include <cassert> +#include "world.h" + +using namespace std; + + +Argument::~Argument(){} + + +Instruction Instruction::make(ins_t op,vector<Argument> args){ + return {op,args}; +} + + +void Robot::load(int idx,const Script &scr){ + banks[idx]=scr; +} + +void Robot::tick(World &world){ + waited++; + Instruction ins=resolve(world); + int dur=calcDuration(ins); + if(dur<waited)return; + waited=0; + execute(ins,world); +} + +Instruction Robot::resolve(World &world){ + Instruction ins=banks.at(ip.bank).at(ip.pos); + for(Argument &arg : ins.args){ + switch(arg.type){ + case arg_t::number: + break; + case arg_t::var: + assert(!arg.remote); + arg.type=arg_t::number; + arg.num=vars.at(arg.num-1); + break; + case arg_t::name: + assert(arg.name=="active"); + 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: + assert(false); + } + } + return ins; +} + +int Robot::calcDuration(Instruction &ins){ + int d=0; + for(const Argument &arg : ins.args){ + if(arg.remote)d+=C::pen_remote; + } + 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); + default: assert(false); + } + return d; +} + + +World::World(){ + memset(&board[0][0],0,SIZE*SIZE*sizeof(Robot*)); +} + +World::~World(){ + for(int y=0;y<SIZE;y++){ + for(int x=0;x<SIZE;x++){ + if(board[y][x])delete board[y][x]; + } + } +} + +Robot& World::create(const Team *team,int iset,int nbanks,bool mobile){ + int x,y; + while(true){ + x=rand()%SIZE; + y=rand()%SIZE; + if(!board[y][x])break; + } + board[y][x]=new Robot(); + board[y][x]->team=team; + board[y][x]->banks.resize(nbanks); + board[y][x]->iset=iset; + board[y][x]->mobile=mobile; + board[y][x]->heading=rand()%4; + return *board[y][x]; +} + +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); + } + } +} + +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]; + } + } + } + } + assert(false); +} + + +ostream& operator<<(ostream &os,const Argument &arg){ + if(arg.remote){ + switch(arg.type){ + case arg_t::number: return os<<arg.num; + case arg_t::var: assert(false); + case arg_t::name: return os<<'%'<<arg.name; + case arg_t::constant: assert(false); + case arg_t::undeflabel: return os<<"\x1B[31;43mUNDEFLABEL\x1B[0m"; + } + } else { + switch(arg.type){ + case arg_t::number: return os<<arg.num; + case arg_t::var: return os<<'#'<<arg.num; + case arg_t::name: return os<<'#'<<arg.name; + case arg_t::constant: return os<<'$'<<arg.name; + case arg_t::undeflabel: return os<<"\x1B[31;43mUNDEFLABEL\x1B[0m"; + } + } +} + +ostream& operator<<(ostream &os,const ins_t &type){ + switch(type){ + case ins_t::set: return os<<"set"; + case ins_t::add: return os<<"add"; + case ins_t::sub: return os<<"sub"; + case ins_t::comp: return os<<"comp"; + case ins_t::trans: return os<<"trans"; + case ins_t::jump: return os<<"jump"; + case ins_t::bjump: return os<<"bjump"; + case ins_t::die: return os<<"die"; + case ins_t::move: return os<<"move"; + case ins_t::turn: return os<<"turn"; + case ins_t::scan: return os<<"scan"; + case ins_t::create: return os<<"create"; + default: assert(false); + } +} + +ostream& operator<<(ostream &os,const Instruction &ins){ + os<<ins.op; + bool first=true; + for(const Argument &arg : ins.args){ + if(first)os<<' '; + else os<<", "; + first=false; + os<<arg; + } + return os; +} + +ostream& operator<<(ostream &os,const Team &team){ + os<<"TEAM: "<<team.name<<endl; + int bank=0; + for(const Script &scr : team.banks){ + os<<"Bank "<<bank<<endl; + for(const Instruction &ins : scr){ + os<<'\t'<<ins<<endl; + } + bank++; + } + return os; +} |