|
@@ -22,7 +22,7 @@ Position Simulator::calcPosition(Position position, Direction direction, int32_t
|
|
|
void Simulator::loadProgram(QColor color, size_t x, size_t y) {
|
|
void Simulator::loadProgram(QColor color, size_t x, size_t y) {
|
|
|
shared_ptr<Team> team = make_shared<Team>(color);
|
|
shared_ptr<Team> team = make_shared<Team>(color);
|
|
|
|
|
|
|
|
- programs.push_back(Program(team, Position{x, y}, 2, 50, 1));
|
|
|
|
|
|
|
+ programs.push_back(Program(team, Right, Position{x, y}, 2, 50, 1));
|
|
|
|
|
|
|
|
programs.back().banks[0] = make_shared<Bank>(team, vector<Instruction>{
|
|
programs.back().banks[0] = make_shared<Bank>(team, vector<Instruction>{
|
|
|
Instruction(BJUMP, LL, 1, 0)
|
|
Instruction(BJUMP, LL, 1, 0)
|
|
@@ -48,8 +48,278 @@ Program* Simulator::findProgram(Position position) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+void Simulator::removeErroneousPrograms() {
|
|
|
|
|
+ auto it = std::remove_if(programs.begin(), programs.end(), [](const Program& program){ return program.error != NoError; });
|
|
|
|
|
+ programs.erase(it, programs.end());
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
void Simulator::simulate() {
|
|
void Simulator::simulate() {
|
|
|
|
|
+ removeErroneousPrograms();
|
|
|
|
|
+
|
|
|
|
|
+ for (auto& program : programs) {
|
|
|
|
|
+ auto& taskIndex = program.taskIndex;
|
|
|
|
|
+
|
|
|
|
|
+ // error if no active task exists
|
|
|
|
|
+ if(find_if(program.tasks.begin(), program.tasks.end(), [](const Task& task){ return !task.paused; }) == program.tasks.end()) {
|
|
|
|
|
+ program.error = Unemployment;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // switch to next unpasued task
|
|
|
|
|
+ do {
|
|
|
|
|
+ taskIndex = (taskIndex + 1) % program.tasks.size();
|
|
|
|
|
+ } while(program.tasks[taskIndex].paused);
|
|
|
|
|
+
|
|
|
|
|
+ // check if we are still executing an instruction
|
|
|
|
|
+ auto& task = program.tasks[taskIndex];
|
|
|
|
|
+ if(task.remainingCycles > 0) {
|
|
|
|
|
+ --task.remainingCycles;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ endInstruction(program, task);
|
|
|
|
|
+ beginInstruction(program, task);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ++cycle;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Simulator::beginInstruction(Program& program, Task& task) {
|
|
|
|
|
+ // handle invalid bank number
|
|
|
|
|
+ if(program.banks.empty() || task.bankIndex >= program.banks.size()) {
|
|
|
|
|
+ program.error = InvalidBankNumber;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // handle autoreset to bank 0,0 if instructionIndex is out of banks bound or bank is empty
|
|
|
|
|
+ if(!program.banks[task.bankIndex] || task.instIndex >= program.banks[task.bankIndex]->instructions.size()) {
|
|
|
|
|
+ task.bankIndex = 0;
|
|
|
|
|
+ task.instIndex = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // handle data hunger
|
|
|
|
|
+ if(task.bankIndex == 0 && !program.banks[0]) {
|
|
|
|
|
+ program.error = DataHunger;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ task.execBank = program.banks[task.bankIndex];
|
|
|
|
|
+
|
|
|
|
|
+ task.remainingCycles = 10;
|
|
|
|
|
+
|
|
|
|
|
+ auto& inst = program.banks[task.bankIndex]->instructions[task.instIndex];
|
|
|
|
|
+ task.a = inst.a;
|
|
|
|
|
+ task.b = inst.b;
|
|
|
|
|
+ task.c = inst.c;
|
|
|
|
|
+
|
|
|
|
|
+ //@todo: remove dummy!
|
|
|
|
|
+ task.var_a = &task.a;
|
|
|
|
|
+ task.var_b = &task.b;
|
|
|
|
|
+ task.var_c = &task.c;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Simulator::endInstruction(Program& program, Task& task) {
|
|
|
|
|
+ // we are not executing yet
|
|
|
|
|
+ if(!task.execBank) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // check if bank is overwritten, skip execution of current command and begin new bank at instruction 0
|
|
|
|
|
+ if(task.execBank != program.banks[task.bankIndex]) {
|
|
|
|
|
+ task.instIndex = 0;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // execute command
|
|
|
|
|
+ auto& instruction = task.execBank->instructions[task.instIndex];
|
|
|
|
|
+ switch(instruction.command) {
|
|
|
|
|
+ case CREATE: {
|
|
|
|
|
+ auto remotePosition = calcPosition(program.position, task.direction, 1);
|
|
|
|
|
+ auto remoteProgram = findProgram(remotePosition);
|
|
|
|
|
+ if(!remoteProgram) {
|
|
|
|
|
+ programs.push_back(Program(program.team, task.direction, remotePosition, task.a, task.b, task.c));
|
|
|
|
|
+ }
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case MOVE: {
|
|
|
|
|
+ auto remotePosition = calcPosition(program.position, task.direction, 1);
|
|
|
|
|
+ auto remoteProgram = findProgram(remotePosition);
|
|
|
|
|
+ if(!remoteProgram) {
|
|
|
|
|
+ program.position = remotePosition;
|
|
|
|
|
+ }
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case DIE: {
|
|
|
|
|
+ program.error = DieExecuted;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case TRANS: {
|
|
|
|
|
+ auto remotePosition = calcPosition(program.position, task.direction, 1);
|
|
|
|
|
+ auto remoteProgram = findProgram(remotePosition);
|
|
|
|
|
+ if(remoteProgram && task.b < remoteProgram->banks.size() && task.a < program.banks.size()) {
|
|
|
|
|
+ remoteProgram->banks[task.b] = program.banks[task.a];
|
|
|
|
|
+ }
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case RTRANS: {
|
|
|
|
|
+ auto remotePosition = calcPosition(program.position, task.direction, 1);
|
|
|
|
|
+ auto remoteProgram = findProgram(remotePosition);
|
|
|
|
|
+ if(remoteProgram && task.a < remoteProgram->banks.size() && task.b < program.banks.size()) {
|
|
|
|
|
+ program.banks[task.b] = remoteProgram->banks[task.a];
|
|
|
|
|
+ }
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case TURN: {
|
|
|
|
|
+ task.direction = static_cast<Direction>(qMax(0, (task.direction + ((task.a >= 0) ? 1 : -1)) % 4));
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case JUMP: {
|
|
|
|
|
+ task.instIndex += task.a;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case AJUMP: {
|
|
|
|
|
+ task.instIndex = task.a;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case BJUMP: {
|
|
|
|
|
+ task.bankIndex = task.a;
|
|
|
|
|
+ task.instIndex = task.b;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case SCAN: {
|
|
|
|
|
+ // Scans a field, result in #a
|
|
|
|
|
+ // #a=0 ...empty.
|
|
|
|
|
+ // #a=1 ...enemy
|
|
|
|
|
+ // #a=2 ...friend
|
|
|
|
|
+ auto remotePosition = calcPosition(program.position, task.direction, 1);
|
|
|
|
|
+ auto remoteProgram = findProgram(remotePosition);
|
|
|
|
|
+ *task.var_a = !remoteProgram ? 0 : remoteProgram->team == program.team ? 2: 1;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case FARSCAN: {
|
|
|
|
|
+ // Scans up to c fields straight in front of the bot.
|
|
|
|
|
+ // The nearest bot's type is stored in #a:
|
|
|
|
|
+ // #a=0 ...empty.
|
|
|
|
|
+ // #a=1 ...enemy
|
|
|
|
|
+ // #a=2 ...friend
|
|
|
|
|
+ // Its distance is stored in #b.
|
|
|
|
|
+ *task.var_a = 0;
|
|
|
|
|
+ *task.var_b = 0;
|
|
|
|
|
+ for(int i = 0; i < task.c; ++i) {
|
|
|
|
|
+ auto remotePosition = calcPosition(program.position, task.direction, i + 1);
|
|
|
|
|
+ auto remoteProgram = findProgram(remotePosition);
|
|
|
|
|
+ if(remoteProgram) {
|
|
|
|
|
+ *task.var_a = remoteProgram->team == program.team ? 2: 1;
|
|
|
|
|
+ *task.var_b = i;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case SET:
|
|
|
|
|
+ *task.var_a = task.b;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case ADD:
|
|
|
|
|
+ *task.var_a += task.b;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case SUB:
|
|
|
|
|
+ *task.var_a -= task.b;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MUL:
|
|
|
|
|
+ *task.var_a *= task.b;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case DIV:
|
|
|
|
|
+ if(task.b == 0) {
|
|
|
|
|
+ program.error = DivisionByZero;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ *task.var_a /= task.b;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MOD:
|
|
|
|
|
+ if(task.b == 0) {
|
|
|
|
|
+ program.error = DivisionByZero;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ *task.var_a %= task.b;
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MIN:
|
|
|
|
|
+ *task.var_a = qMin(task.a, task.b);
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MAX:
|
|
|
|
|
+ *task.var_a = qMax(task.a, task.b);
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case RANDOM:
|
|
|
|
|
+ *task.var_a = task.b + (rand() % (task.c - task.b + 1));
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IF:
|
|
|
|
|
+ task.instIndex += ((task.a == task.b) ? 1 : 2);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFN:
|
|
|
|
|
+ task.instIndex += ((task.a != task.b) ? 1 : 2);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFG:
|
|
|
|
|
+ task.instIndex += ((task.a > task.b) ? 1 : 2);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFL:
|
|
|
|
|
+ task.instIndex += ((task.a < task.b) ? 1 : 2);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFGE:
|
|
|
|
|
+ task.instIndex += ((task.a >= task.b) ? 1 : 2);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFLE:
|
|
|
|
|
+ task.instIndex += ((task.a <= task.b) ? 1 : 2);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ task.instIndex += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
|
|
+void Simulator::simulatex() {
|
|
|
for (auto& program : programs) {
|
|
for (auto& program : programs) {
|
|
|
auto& taskIndex = program.taskIndex;
|
|
auto& taskIndex = program.taskIndex;
|
|
|
|
|
|
|
@@ -61,7 +331,7 @@ void Simulator::simulate() {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- taskIndex = (taskIndex + 1) % program.tasks.size();
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
if (taskIndex < program.tasks.size()) {
|
|
if (taskIndex < program.tasks.size()) {
|
|
|
auto& task = program.tasks[taskIndex];
|
|
auto& task = program.tasks[taskIndex];
|
|
@@ -401,3 +671,4 @@ void Simulator::simulate() {
|
|
|
}
|
|
}
|
|
|
++cycle;
|
|
++cycle;
|
|
|
}
|
|
}
|
|
|
|
|
+#endif
|