aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--world.cpp99
-rw-r--r--world.h13
2 files changed, 94 insertions, 18 deletions
diff --git a/world.cpp b/world.cpp
index a77b242..982b2cd 100644
--- a/world.cpp
+++ b/world.cpp
@@ -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){
diff --git a/world.h b/world.h
index 162110d..2e392c2 100644
--- a/world.h
+++ b/world.h
@@ -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);