aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-03-01 17:23:43 +0100
committertomsmeding <tom.smeding@gmail.com>2017-03-01 17:23:43 +0100
commit0e7a419f55dfed12fd60a0cd41be324a398673f9 (patch)
treefc582be239eb94573dc3451c8cc01fa8e0db0d39
parentfe009c64ef688dc0342752e728c011c855daeaca (diff)
Execute some instructions!
-rw-r--r--main.cpp10
-rw-r--r--world.cpp163
-rw-r--r--world.h6
3 files changed, 145 insertions, 34 deletions
diff --git a/main.cpp b/main.cpp
index ce93d37..a4c8714 100644
--- a/main.cpp
+++ b/main.cpp
@@ -63,8 +63,13 @@ void lowercase(string &str){
Argument parseArgument(const string &str,const unordered_map<string,Location> &labels,Location ip){
if(str[0]=='#'||str[0]=='%'){
bool remote=str[0]=='%';
- if(isdigit(str[1]))return {arg_t::var,remote,atoi(str.data()+1),{}};
- else return {arg_t::name,remote,0,str.substr(1)};
+ if(isdigit(str[1])){
+ int num=atoi(str.data()+1);
+ assert(num>=1&&num<=20);
+ return {arg_t::var,remote,num,{}};
+ } else {
+ return {arg_t::name,remote,0,str.substr(1)};
+ }
} else if(str[0]=='@'){
if(labels.find(str.substr(1))==labels.end()){
return {arg_t::undeflabel,false,0,str.substr(1)};
@@ -220,6 +225,7 @@ int main(int argc,char **argv){
Robot &r=world.create(&t,2,t.banks.size(),false);
for(int i=0;i<(int)t.banks.size();i++){
r.load(i,t.banks[i]);
+ r.active=1;
}
}
diff --git a/world.cpp b/world.cpp
index 40c49ea..a77b242 100644
--- a/world.cpp
+++ b/world.cpp
@@ -19,6 +19,7 @@ void Robot::load(int idx,const Script &scr){
}
void Robot::tick(World &world){
+ if(active==0)return; // TODO: check whether `waited` needs to be reset
waited++;
Instruction ins=resolve(world);
int dur=calcDuration(ins);
@@ -27,28 +28,56 @@ void Robot::tick(World &world){
execute(ins,world);
}
+uint16_t* Robot::resolveVar(const Argument &arg,World &world){
+ cout<<"resolveVar("<<(int)arg.type<<","<<arg.remote<<","<<arg.num<<","<<arg.name<<")"<<endl;
+ if(arg.remote){
+ assert(arg.type==arg_t::name);
+ assert(arg.name=="active");
+ Robot *target=world.targetbot(this);
+ if(target)return &target->active;
+ 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);
- for(Argument &arg : ins.args){
+ 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){
+ assert(dstvar.size()>0);
+ dstvar[0]=true;
+ }
+ for(size_t i=0;i<ins.args.size();i++){
+ Argument &arg=ins.args[i];
+ if(dstvar[i]){
+ assert(arg.type==arg_t::var||arg.type==arg_t::name);
+ continue;
+ }
switch(arg.type){
case arg_t::number:
break;
- case arg_t::var:
- assert(!arg.remote);
+ case arg_t::var:{
+ uint16_t *v=resolveVar(arg,world);
+ if(v)arg.num=*v;
+ else arg.num=0;
arg.type=arg_t::number;
- arg.num=vars.at(arg.num-1);
break;
- case arg_t::name:
+ }
+ case arg_t::name:{
assert(arg.name=="active");
+ uint16_t *v=resolveVar(arg,world);
+ if(v)arg.num=*v;
+ else arg.num=0;
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:
@@ -65,23 +94,96 @@ int Robot::calcDuration(Instruction &ins){
}
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);
+ case ins_t::set: d+=base; break;
+ case ins_t::add: d+=base; break;
+ case ins_t::sub: d+=base; break;
+ case ins_t::comp: d+=base; break;
+ case ins_t::trans: d+=base+C::pen_transinstr*banks.at(ins.args[0].num-1).size(); break;
+ case ins_t::jump: d+=base; break;
+ case ins_t::bjump: d+=base; break;
+ case ins_t::die: d+=base; break;
+ case ins_t::move: d+=base; break;
+ case ins_t::turn: d+=base; break;
+ case ins_t::scan: d+=base; break;
+ 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); break;
default: assert(false);
}
return d;
}
+void Robot::execute(Instruction &ins,World &world){
+ cout<<"Executing "<<ins<<endl;
+ switch(ins.op){
+ case ins_t::set:{
+ uint16_t *v=resolveVar(ins.args[0],world);
+ if(v)*v=ins.args[1].num;
+ break;
+ }
+
+ case ins_t::add:{
+ uint16_t *v=resolveVar(ins.args[0],world);
+ if(v)*v+=ins.args[1].num;
+ break;
+ }
+
+ case ins_t::sub:{
+ uint16_t *v=resolveVar(ins.args[0],world);
+ if(v)*v-=ins.args[1].num;
+ break;
+ }
+
+ case ins_t::comp:
+ if(ins.args[0].num==ins.args[1].num){
+ advanceIP();
+ }
+ break;
+
+ 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());
+ 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;
+ break;
+
+ case ins_t::die:
+ case ins_t::move:
+ case ins_t::turn:
+ case ins_t::scan:
+ case ins_t::create:
+ assert(false);
+
+ default:
+ assert(false);
+ }
+
+ advanceIP();
+}
+
+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*));
@@ -122,13 +224,12 @@ void World::tick(){
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];
- }
+ 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];
}
}
}
diff --git a/world.h b/world.h
index ccbdbcf..162110d 100644
--- a/world.h
+++ b/world.h
@@ -49,11 +49,13 @@ class Robot{
Location ip={0,0};
int waited=0;
array<uint16_t,20> vars;
- uint16_t active;
+ uint16_t* resolveVar(const Argument &arg,World &world);
Instruction resolve(World &world);
int calcDuration(Instruction &ins);
void execute(Instruction &ins,World &world);
+ void advanceIP();
+ bool ipInRange() const;
public:
const Team *team;
@@ -61,6 +63,8 @@ public:
int iset;
bool mobile;
+ uint16_t active=0;
+
int heading;
void load(int idx,const Script &scr);