1
1
Эх сурвалжийг харах

new execution model implmented

Zoadian 10 жил өмнө
parent
commit
963a1a56b3
5 өөрчлөгдсөн 287 нэмэгдсэн , 12 устгасан
  1. 2 4
      playfield.cpp
  2. 2 1
      program.cpp
  3. 7 5
      program.h
  4. 273 2
      simulator.cpp
  5. 3 0
      simulator.h

+ 2 - 4
playfield.cpp

@@ -45,10 +45,6 @@ void Playfield::paintEvent(QPaintEvent* event) {
 
 
 
 
     for (auto& program : simulator.programs) {
     for (auto& program : simulator.programs) {
-        if(program.error != NoError) {
-            continue;
-        }
-
         int xx = program.position.x * w;
         int xx = program.position.x * w;
         int yy = program.position.y * w;
         int yy = program.position.y * w;
         painter.setPen(QPen(program.team->color, 3));
         painter.setPen(QPen(program.team->color, 3));
@@ -58,6 +54,8 @@ void Playfield::paintEvent(QPaintEvent* event) {
 
 
         auto& taskIndex = program.taskIndex;
         auto& taskIndex = program.taskIndex;
 
 
+        painter.drawText(rect, QString("%1").arg(program.error));
+
         if(program.tasks.empty()) {
         if(program.tasks.empty()) {
             continue;
             continue;
         }
         }

+ 2 - 1
program.cpp

@@ -1,10 +1,11 @@
 #include "program.h"
 #include "program.h"
 
 
 
 
-Program::Program(shared_ptr<Team> team, Position position, int32_t instructionSet, int32_t slotCount, int32_t mobile)
+Program::Program(shared_ptr<Team> team, Direction direction, Position position, int32_t instructionSet, int32_t slotCount, int32_t mobile)
     : team(team)
     : team(team)
     , position(position)
     , position(position)
 {
 {
     banks.resize(slotCount);
     banks.resize(slotCount);
     tasks.resize(1);
     tasks.resize(1);
+    tasks[0].direction = direction;
 }
 }

+ 7 - 5
program.h

@@ -71,17 +71,19 @@ using InstIndex = size_t;
 using TaskIndex = size_t;
 using TaskIndex = size_t;
 
 
 struct Task {
 struct Task {
+    bool paused = false;
     Direction direction = Right;
     Direction direction = Right;
     BankIndex bankIndex = 0;
     BankIndex bankIndex = 0;
     InstIndex instIndex = 0;
     InstIndex instIndex = 0;
 
 
-    shared_ptr<Bank> bank;
+    int remainingCycles = 0;
+    shared_ptr<Bank> execBank;
     int32_t a = 0;
     int32_t a = 0;
     int32_t b = 0;
     int32_t b = 0;
     int32_t c = 0;
     int32_t c = 0;
-    int32_t* p_a = nullptr;
-    int32_t* p_b = nullptr;
-    int32_t* p_c = nullptr;
+    int32_t* var_a = nullptr;
+    int32_t* var_b = nullptr;
+    int32_t* var_c = nullptr;
 };
 };
 
 
 struct Program {
 struct Program {
@@ -98,6 +100,6 @@ struct Program {
     vector<shared_ptr<Bank>> banks;
     vector<shared_ptr<Bank>> banks;
     array<int32_t, 20> vars{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
     array<int32_t, 20> vars{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
 
 
-    Program(shared_ptr<Team> team, Position position, int32_t instructionSet, int32_t slotCount, int32_t mobile);
+    Program(shared_ptr<Team> team, Direction direction, Position position, int32_t instructionSet, int32_t slotCount, int32_t mobile);
 };
 };
 #endif // CPROGRAM_H
 #endif // CPROGRAM_H

+ 273 - 2
simulator.cpp

@@ -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

+ 3 - 0
simulator.h

@@ -30,7 +30,10 @@ struct Simulator {
 
 
     Program* findProgram(Position position);
     Program* findProgram(Position position);
 
 
+    void removeErroneousPrograms();
     void simulate();
     void simulate();
+    void beginInstruction(Program& program, Task& task);
+    void endInstruction(Program& program, Task& task);
 };
 };