aboutsummaryrefslogtreecommitdiff
path: root/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'world.cpp')
-rw-r--r--world.cpp199
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;
+}