|
@@ -18,6 +18,87 @@ Position Simulator::calcPosition(Position position, Direction direction, int32_t
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void Simulator::decodeInstructionParameters(Task& task, const Instruction& instruction) {
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+ task.b = instruction.b;
|
|
|
|
|
+ task.c = instruction.c;
|
|
|
|
|
+ task.var_a = nullptr;
|
|
|
|
|
+ task.var_b = nullptr;
|
|
|
|
|
+ task.var_c = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ switch(instruction.params) {
|
|
|
|
|
+ case N:
|
|
|
|
|
+ break;
|
|
|
|
|
+ case L:
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case V:
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ case LL:
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+ task.b = instruction.b;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case LV:
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ case VL:
|
|
|
|
|
+
|
|
|
|
|
+ task.b = instruction.b;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case VV:
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ case LLL:
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+ task.b = instruction.b;
|
|
|
|
|
+ task.c = instruction.c;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case LLV:
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+ task.b = instruction.b;
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ case LVL:
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+
|
|
|
|
|
+ task.c = instruction.c;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case LVV:
|
|
|
|
|
+ task.a = instruction.a;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ case VLL:
|
|
|
|
|
+
|
|
|
|
|
+ task.b = instruction.b;
|
|
|
|
|
+ task.c = instruction.c;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case VLV:
|
|
|
|
|
+
|
|
|
|
|
+ task.b = instruction.b;
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ case VVL:
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ task.c = instruction.c;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case VVV:
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ //@todo: remove dummy!
|
|
|
|
|
+ task.var_a = &task.a;
|
|
|
|
|
+ task.var_b = &task.b;
|
|
|
|
|
+ task.var_c = &task.c;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
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);
|
|
@@ -106,22 +187,193 @@ void Simulator::beginInstruction(Program& program, Task& task) {
|
|
|
|
|
|
|
|
task.execBank = program.banks[task.bankIndex];
|
|
task.execBank = program.banks[task.bankIndex];
|
|
|
|
|
|
|
|
- task.remainingCycles = 10;
|
|
|
|
|
|
|
+ auto& instruction = program.banks[task.bankIndex]->instructions[task.instIndex];
|
|
|
|
|
|
|
|
- auto& inst = program.banks[task.bankIndex]->instructions[task.instIndex];
|
|
|
|
|
- task.a = inst.a;
|
|
|
|
|
- task.b = inst.b;
|
|
|
|
|
- task.c = inst.c;
|
|
|
|
|
|
|
+ decodeInstructionParameters(task, instruction);
|
|
|
|
|
|
|
|
- //@todo: remove dummy!
|
|
|
|
|
- task.var_a = &task.a;
|
|
|
|
|
- task.var_b = &task.b;
|
|
|
|
|
- task.var_c = &task.c;
|
|
|
|
|
|
|
+ switch(instruction.command) {
|
|
|
|
|
+ case CREATE:
|
|
|
|
|
+ if(program.instructionSet < 2) {
|
|
|
|
|
+ program.error = HigherInstructionSetRequired;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(task.a < 0 || task.a > 2 || task.b < 1 || task.b > 50 || task.c < 0 || task.c > 1) {
|
|
|
|
|
+ program.error = InvalidParameter;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ task.remainingCycles = 100 + 50 * task.a + 25 * task.b + 120 * task.c;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MOVE:
|
|
|
|
|
+ if(program.mobile < 1) {
|
|
|
|
|
+ program.error = MobilityRequired;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ task.remainingCycles = 20;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case DIE:
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case TRANS: {
|
|
|
|
|
+ if(program.instructionSet < 1) {
|
|
|
|
|
+ program.error = HigherInstructionSetRequired;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(task.a < 0 || task.a >= program.banks.size()) {
|
|
|
|
|
+ program.error = InvalidBankNumber;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ const auto& bank = program.banks[task.a];
|
|
|
|
|
+ task.remainingCycles = 14 + (bank ? bank->instructions.size() : 0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case RTRANS: {
|
|
|
|
|
+ if(program.instructionSet < 1) {
|
|
|
|
|
+ program.error = HigherInstructionSetRequired;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(task.a < 0 || task.a >= 50 || task.b < 0 || task.b >= program.banks.size()) {
|
|
|
|
|
+ program.error = InvalidBankNumber;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ auto remotePosition = calcPosition(program.position, task.direction, 1);
|
|
|
|
|
+ auto remoteProgram = findProgram(remotePosition);
|
|
|
|
|
+ task.remainingCycles = 14 + remoteProgram ? (task.a < remoteProgram->banks.size() ? (remoteProgram->banks[task.a] ? remoteProgram->banks[task.a]->instructions.size() : 0): 0): 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ case TURN:
|
|
|
|
|
+ task.remainingCycles = 8;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case JUMP:
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case AJUMP:
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case BJUMP:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case SCAN:
|
|
|
|
|
+ if(program.instructionSet < 1) {
|
|
|
|
|
+ program.error = HigherInstructionSetRequired;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ task.remainingCycles = 8;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case FARSCAN:
|
|
|
|
|
+ if(program.instructionSet < 1) {
|
|
|
|
|
+ program.error = HigherInstructionSetRequired;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ task.remainingCycles = 10 + 3 * task.c;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case SET:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case ADD:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case SUB:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MUL:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case DIV:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MOD:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MIN:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case MAX:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case RANDOM:
|
|
|
|
|
+ if(task.b > task.c) {
|
|
|
|
|
+ program.error = InvalidParameter;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IF:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFN:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFG:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFL:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFGE:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case IFLE:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case INIT:
|
|
|
|
|
+ task.remainingCycles = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case BREAK:
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case RESUME:
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case SEIZE:
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case SLEEP:
|
|
|
|
|
+ if(task.a > 2000) {
|
|
|
|
|
+ program.error = InvalidParameter;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ task.remainingCycles = task.a;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case QUIT:
|
|
|
|
|
+ task.remainingCycles = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Simulator::endInstruction(Program& program, Task& task) {
|
|
void Simulator::endInstruction(Program& program, Task& task) {
|
|
|
// we are not executing yet
|
|
// we are not executing yet
|
|
|
- if(!task.execBank) {
|
|
|
|
|
|
|
+ if(!task.execBank || program.error != NoError) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|