Răsfoiți Sursa

refactoring

Zoadian 10 ani în urmă
părinte
comite
40242f327f
7 a modificat fișierele cu 680 adăugiri și 630 ștergeri
  1. 7 2
      ccsim.pro
  2. 10 0
      instruction.cpp
  3. 140 0
      instruction.h
  4. 10 0
      program.cpp
  5. 103 0
      program.h
  6. 403 0
      simulator.cpp
  7. 7 628
      simulator.h

+ 7 - 2
ccsim.pro

@@ -15,12 +15,17 @@ TEMPLATE = app
 SOURCES += main.cpp\
         mainwindow.cpp \
     playfield.cpp \
-    debugwidget.cpp
+    debugwidget.cpp \
+    program.cpp \
+    simulator.cpp \
+    instruction.cpp
 
 HEADERS  += mainwindow.h \
     simulator.h \
     playfield.h \
-    debugwidget.h
+    debugwidget.h \
+    program.h \
+    instruction.h
 
 FORMS    += mainwindow.ui \
     debugwidget.ui

+ 10 - 0
instruction.cpp

@@ -0,0 +1,10 @@
+#include "instruction.h"
+
+Instruction::Instruction(Command _command, Params _params, Parameter _a, Parameter _b, Parameter _c)
+    : command(_command)
+    , params(_params)
+    , a(_a)
+    , b(_b)
+    , c(_c)
+{
+}

+ 140 - 0
instruction.h

@@ -0,0 +1,140 @@
+#ifndef CINSTRUCTION_H
+#define CINSTRUCTION_H
+
+#include <stdint.h>
+
+enum Command : uint16_t {
+    CREATE,
+    MOVE,
+    DIE,
+    TRANS,
+    RTRANS,
+    TURN,
+
+    JUMP,
+    AJUMP,
+    BJUMP,
+
+    SCAN,
+    FARSCAN,
+
+    SET,
+    ADD,
+    SUB,
+    MUL,
+    DIV,
+    MOD,
+    MIN,
+    MAX,
+    RANDOM,
+
+    IF,
+    IFN,
+    IFG,
+    IFL,
+    IFGE,
+    IFLE,
+
+    INIT,
+    BREAK,
+    RESUME,
+    SEIZE,
+    SLEEP,
+    QUIT,
+};
+
+enum Params : uint16_t {
+    LLL,
+    LLV,
+    LVL,
+    LVV,
+    VLL,
+    VLV,
+    VVL,
+    VVV,
+
+    N = LLL,
+    L = LLL,
+    V = VLL,
+
+    LL = LLL,
+    LV = LVL,
+    VL = VLL,
+    VV = VVV,
+};
+
+enum Variables {
+    Local_0,
+    Local_1,
+    Local_2,
+    Local_3,
+    Local_4,
+    Local_5,
+    Local_6,
+    Local_7,
+    Local_8,
+    Local_9,
+    Local_10,
+    Local_11,
+    Local_12,
+    Local_13,
+    Local_14,
+    Local_15,
+    Local_16,
+    Local_17,
+    Local_18,
+    Local_19,
+    LocalActive,
+    LocalBanks,
+    LocalInstrSet,
+    LocalMobile,
+    LocalAge,
+    LocalTasks,
+    LocalGeneration,
+    LocalId,
+
+    RemoteActive,
+    RemoteBanks,
+    RemoteInstrSet,
+    RemoteMobile,
+    RemoteAge,
+    RemoteTasks,
+    RemoteGeneration,
+
+    GlobalPub,
+    GlobalTeam,
+    GlobalOwn,
+    GlobalOthers,
+    GlobalFields,
+    GlobalTime,
+    GlobalTimeout,
+};
+
+enum Error {
+    NoError, // No error
+    EliminationTrigger, // Elimination Trigger released
+    DataHunger, // Data Hunger (Bank 1 empty and executed)
+    DivisionByZero, // Division by zero
+    InvalidBankNumber, // Invalid bank number (e.g. in TRANS or BJUMP)
+    HigherInstructionSetRequired, // Higher Instruction Set required
+    MobilityRequired, // Mobility required
+    DieExecuted, // DIE executed
+    InvalidParameter , // Invalid parameter (e.g. CREATE x, -1, x)
+    Unemployment, // No more tasks left in a robot (Unemployment)
+    InstructionDurationTooHigh, // Instruction duration too high (i.e. > MaxInstrDur)
+};
+
+
+using Parameter = int32_t;
+
+struct Instruction {
+    Command command = DIE;
+    Params params = N;
+    Parameter a = 0;
+    Parameter b = 0;
+    Parameter c = 0;
+
+    Instruction(Command _command, Params _params = N, Parameter _a = 0, Parameter _b = 0, Parameter _c = 0);
+};
+
+#endif // CINSTRUCTION_H

+ 10 - 0
program.cpp

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

+ 103 - 0
program.h

@@ -0,0 +1,103 @@
+#ifndef CPROGRAM_H
+#define CPROGRAM_H
+
+#include <array>
+#include <vector>
+#include <memory>
+#include <climits>
+#include <stdint.h>
+#include <QColor>
+using namespace std;
+
+#include "instruction.h"
+
+enum Direction {
+    Right,
+    Down,
+    Left,
+    Up,
+};
+
+struct Position {
+    size_t x = 0;
+    size_t y = 0;
+
+    Position()
+        : x(0)
+        , y(0)
+    {}
+    Position(size_t _x, size_t _y)
+        : x(_x)
+        , y(_y)
+    {}
+    Position(const Position& _pos)
+        : x(_pos.x)
+        , y(_pos.y)
+    {}
+};
+
+struct Team {
+    QColor color = Qt::red;
+
+    Team(QColor color)
+        : color(color)
+    {
+    }
+};
+
+struct Bank {
+    shared_ptr<Team> team;
+    vector<Instruction> instructions;
+
+    Bank(shared_ptr<Team> team, const vector<Instruction>& instructions)
+        : team(team)
+        , instructions(instructions)
+    {
+    }
+
+    Bank(const Bank& bank)
+        : team(bank.team)
+        , instructions(bank.instructions)
+    {
+
+    }
+};
+
+
+
+
+using BankIndex = size_t;
+using InstIndex = size_t;
+using TaskIndex = size_t;
+
+struct Task {
+    Direction direction = Right;
+    BankIndex bankIndex = 0;
+    InstIndex instIndex = 0;
+
+    shared_ptr<Bank> bank;
+    int32_t a = 0;
+    int32_t b = 0;
+    int32_t c = 0;
+    int32_t* p_a = nullptr;
+    int32_t* p_b = nullptr;
+    int32_t* p_c = nullptr;
+};
+
+struct Program {
+    int active = 0;
+    int instructionSet = 0;
+    int mobile = 0;
+    int creationCycle = 0;
+    int generation = 0;
+    Error error = NoError;
+    shared_ptr<Team> team;
+    Position position;
+    vector<Task> tasks;
+    TaskIndex taskIndex = 0;
+    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}};
+
+    Program(shared_ptr<Team> team, Position position, int32_t instructionSet, int32_t slotCount, int32_t mobile);
+};
+#endif // CPROGRAM_H

+ 403 - 0
simulator.cpp

@@ -0,0 +1,403 @@
+#include "simulator.h"
+
+
+Simulator::Simulator() {
+    programs.reserve(FIELDS_XY * FIELDS_XY);
+
+//    std::srand(std::time(0));
+    std::srand(0);
+}
+
+
+Position Simulator::calcPosition(Position position, Direction direction, int32_t distance) {
+    switch(direction) {
+    case Right: return Position{(position.x + distance) % FIELDS_XY, position.y};
+    case Down: return Position{position.x, (position.y + distance) % FIELDS_XY};
+    case Left: return Position{(position.x - distance) % FIELDS_XY, position.y};
+    case Up: return Position{position.x, (position.y - distance) % FIELDS_XY};
+    }
+}
+
+
+void Simulator::loadProgram(QColor color, size_t x, size_t y) {
+    shared_ptr<Team> team = make_shared<Team>(color);
+
+    programs.push_back(Program(team, Position{x, y}, 2, 50, 1));
+
+    programs.back().banks[0] = make_shared<Bank>(team, vector<Instruction>{
+                                                          Instruction(BJUMP, LL, 1, 0)
+                                                      });
+
+    programs.back().banks[1] = make_shared<Bank>(team, vector<Instruction>{
+                                                          Instruction(SCAN, V, 1),
+                                                          Instruction(CREATE, LLL, 2, 50, 1),
+                                                          Instruction(TRANS, LL, 0, 0),
+                                                          Instruction(TRANS, LL, 1, 1),
+                                                          Instruction(TURN, L, 0),
+                                                          Instruction(AJUMP, L, 0)
+                                                      });
+}
+
+Program* Simulator::findProgram(Position position) {
+    for(auto& program : programs) {
+        if(program.position.x == position.x && program.position.y == position.y && program.error == NoError) {
+            return &program;
+        }
+    }
+    return nullptr;
+}
+
+
+
+void Simulator::simulate() {
+    for (auto& program : programs) {
+        auto& taskIndex = program.taskIndex;
+
+        if(program.error != NoError) {
+            continue;
+        }
+
+        if(program.tasks.empty()) {
+            continue;
+        }
+
+        taskIndex = (taskIndex + 1) % program.tasks.size();
+
+        if (taskIndex < program.tasks.size()) {
+            auto& task = program.tasks[taskIndex];
+
+            if(task.bankIndex >= program.banks.size()) {
+                continue;
+            }
+
+            const auto bank_ptr = program.banks[task.bankIndex].get();
+
+            if(bank_ptr == nullptr || task.instIndex >= bank_ptr->instructions.size()) {
+                continue;
+            }
+
+            const auto& bank = *bank_ptr;
+            const auto& inst = bank.instructions[task.instIndex];
+
+            //prevent overrideing of instuctions...
+
+
+
+            auto mapParameters = [this](Program& program, Task& task, const Instruction& inst) {
+                task.p_a = &task.a;
+                task.p_b = &task.b;
+                task.p_c = &task.c;
+
+                auto decode = [&](int32_t*& v) {
+                    switch(*v) {
+                        case Local_0:  v = &program.vars[0]; break;
+                        case Local_1:  v = &program.vars[1]; break;
+                        case Local_2:  v = &program.vars[2]; break;
+                        case Local_3:  v = &program.vars[3]; break;
+                        case Local_4:  v = &program.vars[4]; break;
+                        case Local_5:  v = &program.vars[5]; break;
+                        case Local_6:  v = &program.vars[6]; break;
+                        case Local_7:  v = &program.vars[7]; break;
+                        case Local_8:  v = &program.vars[8]; break;
+                        case Local_9:  v = &program.vars[9]; break;
+                        case Local_10: v = &program.vars[10]; break;
+                        case Local_11: v = &program.vars[11]; break;
+                        case Local_12: v = &program.vars[12]; break;
+                        case Local_13: v = &program.vars[13]; break;
+                        case Local_14: v = &program.vars[14]; break;
+                        case Local_15: v = &program.vars[15]; break;
+                        case Local_16: v = &program.vars[16]; break;
+                        case Local_17: v = &program.vars[17]; break;
+                        case Local_18: v = &program.vars[18]; break;
+                        case Local_19: v = &program.vars[19]; break;
+                        case LocalActive:
+                            v = &program.active;
+                            break;
+                        case LocalBanks:
+                            *v = program.banks.size();
+                            break;
+                        case LocalInstrSet:
+                            *v = program.instructionSet;
+                            break;
+                        case LocalMobile:
+                            *v = program.mobile;
+                            break;
+                        case LocalAge:
+                            *v = cycle - program.creationCycle;
+                            break;
+                        case LocalTasks:
+                            *v = program.tasks.size();
+                            break;
+                        case LocalGeneration:
+                            *v = program.generation;
+                            break;
+                        case LocalId:
+                            // @todo
+                            break;
+                        case RemoteActive: {
+                            auto remotePosition = calcPosition(program.position, task.direction, 1);
+                            auto remoteProgram = findProgram(remotePosition);
+                            if(remoteProgram) {
+                                v = &remoteProgram->active;
+                            }
+                            else {
+                                *v = 0;
+                            }
+                            break;
+                        }
+                        case RemoteBanks: {
+                            auto remotePosition = calcPosition(program.position, task.direction, 1);
+                            auto remoteProgram = findProgram(remotePosition);
+                            *v = remoteProgram ? remoteProgram->banks.size() : 0;
+                            break;
+                        }
+                        case RemoteInstrSet: {
+                            auto remotePosition = calcPosition(program.position, task.direction, 1);
+                            auto remoteProgram = findProgram(remotePosition);
+                            *v = remoteProgram ? remoteProgram->instructionSet : 0;
+                            break;
+                        }
+                        case RemoteMobile: {
+                            auto remotePosition = calcPosition(program.position, task.direction, 1);
+                            auto remoteProgram = findProgram(remotePosition);
+                            *v = remoteProgram ? remoteProgram->mobile: 0;
+                            break;
+                        }
+                        case RemoteAge: {
+                            auto remotePosition = calcPosition(program.position, task.direction, 1);
+                            auto remoteProgram = findProgram(remotePosition);
+                            *v = remoteProgram ? (cycle - remoteProgram->creationCycle) : 0;
+                            break;
+                        }
+                        case RemoteTasks: {
+                            auto remotePosition = calcPosition(program.position, task.direction, 1);
+                            auto remoteProgram = findProgram(remotePosition);
+                            *v = remoteProgram ? remoteProgram->tasks.size() : 0;
+                            break;
+                        }
+                        case RemoteGeneration: {
+                            auto remotePosition = calcPosition(program.position, task.direction, 1);
+                            auto remoteProgram = findProgram(remotePosition);
+                            *v = remoteProgram ? remoteProgram->generation : 0;
+                            break;
+                        }
+                        case GlobalPub:
+                            // @todo
+                            break;
+                        case GlobalTeam:
+                            // @todo
+                            break;
+                        case GlobalOwn:
+                            // @todo
+                            break;
+                        case GlobalOthers:
+                            // @todo
+                            break;
+                        case GlobalFields:
+                            *v = FIELDS_XY * FIELDS_XY;
+                            break;
+                        case GlobalTime:
+                            *v = cycle;
+                            break;
+                        case GlobalTimeout:
+                            *v = CYCLE_TIMEOUT;
+                            break;
+                    }
+                };
+
+                switch(inst.params) {
+                    case LLL: { task.a = inst.a;  task.b = inst.b;  task.c = inst.c;  break; }
+                    case LLV: { task.a = inst.a;  task.b = inst.b;  decode(task.p_c); break; }
+                    case LVL: { task.a = inst.a;  decode(task.p_b); task.c = inst.c;  break; }
+                    case LVV: { task.a = inst.a;  decode(task.p_b); decode(task.p_c); break; }
+                    case VLL: { decode(task.p_a); task.b = inst.b;  task.c = inst.c;  break; }
+                    case VLV: { decode(task.p_a); task.b = inst.b;  decode(task.p_c); break; }
+                    case VVL: { decode(task.p_a); decode(task.p_b); task.c = inst.c;  break; }
+                    case VVV: { decode(task.p_a); decode(task.p_b); decode(task.p_c); break; }
+                }
+            };
+
+            mapParameters(program, task, inst);
+
+            switch(inst.command) {
+            case CREATE: {
+                auto remotePosition = calcPosition(program.position, task.direction, 1);
+                auto remoteProgram = findProgram(remotePosition);
+                if(!remoteProgram) {
+                    programs.push_back(Program(program.team, remotePosition, *task.p_a, *task.p_b, *task.p_c));
+                }
+                task.instIndex += 1;
+                break;
+            }
+
+            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.p_b < remoteProgram->banks.size() && *task.p_a < program.banks.size()) {
+                    remoteProgram->banks[*task.p_b] = program.banks[*task.p_a];
+                }
+                task.instIndex += 1;
+                break;
+            }
+
+            case RTRANS: {
+                auto remotePosition = calcPosition(program.position, task.direction, 1);
+                auto remoteProgram = findProgram(remotePosition);
+                if(remoteProgram && *task.p_a < remoteProgram->banks.size() && *task.p_b < program.banks.size()) {
+                    program.banks[*task.p_b] = remoteProgram->banks[*task.p_a];
+                }
+                task.instIndex += 1;
+                break;
+            }
+
+            case TURN: {
+                task.direction = static_cast<Direction>(qMax(0, (task.direction + ((*task.p_a >= 0) ? 1 : -1)) % 4));
+                task.instIndex += 1;
+                break;
+            }
+
+            case JUMP: {
+                task.instIndex += *task.p_a;
+                break;
+            }
+
+            case AJUMP: {
+                task.instIndex = *task.p_a;
+                break;
+            }
+
+            case BJUMP: {
+                task.bankIndex = *task.p_a;
+                task.instIndex = *task.p_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.p_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.p_a = 0;
+                *task.p_b = 0;
+                for(int i = 0; i < *task.p_c; ++i) {
+                    auto remotePosition = calcPosition(program.position, task.direction, i + 1);
+                    auto remoteProgram = findProgram(remotePosition);
+                    if(remoteProgram) {
+                        *task.p_a = remoteProgram->team == program.team ? 2: 1;
+                        *task.p_b = i;
+                        break;
+                    }
+                }
+                task.instIndex += 1;
+                break;
+            }
+
+
+            case SET:
+                *task.p_a = *task.p_b;
+                task.instIndex += 1;
+                break;
+
+            case ADD:
+                *task.p_a += *task.p_b;
+                task.instIndex += 1;
+                break;
+
+            case SUB:
+                *task.p_a -= *task.p_b;
+                task.instIndex += 1;
+                break;
+
+            case MUL:
+                *task.p_a *= *task.p_b;
+                task.instIndex += 1;
+                break;
+
+            case DIV:
+                *task.p_a /= *task.p_b;
+                task.instIndex += 1;
+                break;
+
+            case MOD:
+                *task.p_a %= *task.p_b;
+                task.instIndex += 1;
+                break;
+
+            case MIN:
+                *task.p_a = qMin(*task.p_a, *task.p_b);
+                task.instIndex += 1;
+                break;
+
+            case MAX:
+                *task.p_a = qMax(*task.p_a, *task.p_b);
+                task.instIndex += 1;
+                break;
+
+            case RANDOM:
+                *task.p_a = *task.p_b + (rand() % (*task.p_c - *task.p_b + 1));
+                task.instIndex += 1;
+            break;
+
+            case IF:
+                task.instIndex += ((*task.p_a == *task.p_b) ? 1 : 2);
+            break;
+
+            case IFN:
+                task.instIndex += ((*task.p_a != *task.p_b) ? 1 : 2);
+            break;
+
+            case IFG:
+                task.instIndex += ((*task.p_a > *task.p_b) ? 1 : 2);
+            break;
+
+            case IFL:
+                task.instIndex += ((*task.p_a < *task.p_b) ? 1 : 2);
+            break;
+
+            case IFGE:
+                task.instIndex += ((*task.p_a >= *task.p_b) ? 1 : 2);
+            break;
+
+            case IFLE:
+                task.instIndex += ((*task.p_a <= *task.p_b) ? 1 : 2);
+            break;
+
+
+            default:
+                task.instIndex += 1;
+                break;
+            }
+        }
+    }
+    ++cycle;
+}

+ 7 - 628
simulator.h

@@ -8,650 +8,29 @@
 #include <stdint.h>
 using namespace std;
 
+#include "program.h"
+
 enum {
     CYCLE_TIMEOUT = 100000,
     FIELDS_XY = 20,
 };
 
-struct Position {
-    size_t x = 0;
-    size_t y = 0;
-
-    Position()
-        : x(0)
-        , y(0)
-    {}
-    Position(size_t _x, size_t _y)
-        : x(_x)
-        , y(_y)
-    {}
-    Position(const Position& _pos)
-        : x(_pos.x)
-        , y(_pos.y)
-    {}
-};
-
-enum Direction {
-    Right,
-    Down,
-    Left,
-    Up,
-};
-
-enum Command : uint16_t {
-    NOP,
-
-    CREATE,
-    MOVE,
-    DIE,
-    TRANS,
-    RTRANS,
-    TURN,
-
-    JUMP,
-    AJUMP,
-    BJUMP,
-
-    SCAN,
-    FARSCAN,
-
-    SET,
-    ADD,
-    SUB,
-    MUL,
-    DIV,
-    MOD,
-    MIN,
-    MAX,
-    RANDOM,
-
-    IF,
-    IFN,
-    IFG,
-    IFL,
-    IFGE,
-    IFLE,
-
-    // INIT,
-    // BREAK,
-    // RESUME,
-    // SEIZE,
-    // SLEEP,
-    // QUIT,
-};
-
-enum Params : uint16_t {
-    LLL,
-    LLV,
-    LVL,
-    LVV,
-    VLL,
-    VLV,
-    VVL,
-    VVV,
-
-    N = LLL,
-    L = LLL,
-    V = VLL,
-
-    LL = LLL,
-    LV = LVL,
-    VL = VLL,
-    VV = VVV,
-};
-
-enum Variables {
-    Local_0,
-    Local_1,
-    Local_2,
-    Local_3,
-    Local_4,
-    Local_5,
-    Local_6,
-    Local_7,
-    Local_8,
-    Local_9,
-    Local_10,
-    Local_11,
-    Local_12,
-    Local_13,
-    Local_14,
-    Local_15,
-    Local_16,
-    Local_17,
-    Local_18,
-    Local_19,
-    LocalActive,
-    LocalBanks,
-    LocalInstrSet,
-    LocalMobile,
-    LocalAge,
-    LocalTasks,
-    LocalGeneration,
-    LocalId,
-
-    RemoteActive,
-    RemoteBanks,
-    RemoteInstrSet,
-    RemoteMobile,
-    RemoteAge,
-    RemoteTasks,
-    RemoteGeneration,
-
-    GlobalPub,
-    GlobalTeam,
-    GlobalOwn,
-    GlobalOthers,
-    GlobalFields,
-    GlobalTime,
-    GlobalTimeout,
-};
-
-enum Error {
-    NoError, // No error
-    EliminationTrigger, // Elimination Trigger released
-    DataHunger, // Data Hunger (Bank 1 empty and executed)
-    DivisionByZero, // Division by zero
-    InvalidBankNumber, // Invalid bank number (e.g. in TRANS or BJUMP)
-    HigherInstructionSetRequired, // Higher Instruction Set required
-    MobilityRequired, // Mobility required
-    DieExecuted, // DIE executed
-    InvalidParameter , // Invalid parameter (e.g. CREATE x, -1, x)
-    Unemployment, // No more tasks left in a robot (Unemployment)
-    InstructionDurationTooHigh, // Instruction duration too high (i.e. > MaxInstrDur)
-};
-
-
-using Parameter = int32_t;
-
-struct Instruction {
-    Command command = NOP;
-    Params params = N;
-    Parameter a = 0;
-    Parameter b = 0;
-    Parameter c = 0;
-
-    Instruction(Command _command, Params _params = N, Parameter _a = 0, Parameter _b = 0, Parameter _c = 0)
-        : command(_command)
-        , params(_params)
-        , a(_a)
-        , b(_b)
-        , c(_c)
-    {
-    }
-};
-
-struct Team {
-    QColor color = Qt::red;
 
-    Team(QColor color)
-        : color(color)
-    {
-    }
-};
-
-struct Bank {
-    shared_ptr<Team> team;
-    vector<Instruction> instructions;
-
-    Bank(shared_ptr<Team> team, const vector<Instruction>& instructions)
-        : team(team)
-        , instructions(instructions)
-    {
-    }
-
-    Bank(const Bank& bank)
-        : team(bank.team)
-        , instructions(bank.instructions)
-    {
-
-    }
-};
 
 
-using BankIndex = size_t;
-using InstIndex = size_t;
-using TaskIndex = size_t;
-
-struct Task {
-    Direction direction = Right;
-    BankIndex bankIndex = 0;
-    InstIndex instIndex = 0;
-    int32_t a = 0;
-    int32_t b = 0;
-    int32_t c = 0;
-    int32_t* p_a = nullptr;
-    int32_t* p_b = nullptr;
-    int32_t* p_c = nullptr;
-};
-
-struct Program {
-    int active = 0;
-    int instructionSet = 0;
-    int mobile = 0;
-    int creationCycle = 0;
-    int generation = 0;
-    Error error = NoError;
-    shared_ptr<Team> team;
-    Position position;
-    vector<Task> tasks;
-    TaskIndex taskIndex = 0;
-    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}};
-
-    Program(shared_ptr<Team> _team, Position _position, int32_t instructionSet, int32_t slotCount, int32_t mobile) {
-        team = _team;
-        position = _position;
-        banks.resize(slotCount);
-        tasks.resize(1);
-    }
-};
-
-struct Field {
-    Program* program = nullptr;
-};
-
 struct Simulator {
     size_t cycle = 0;
     vector<Program> programs;
 
-    Simulator() {
-        programs.reserve(FIELDS_XY * FIELDS_XY);
-
-//        std::srand(std::time(0));
-        std::srand(0);
-    }
-
-    Position calcPosition(Position position, Direction direction, int32_t distance) {
-        switch(direction) {
-        case Right: return Position{(position.x + distance) % FIELDS_XY, position.y};
-        case Down: return Position{position.x, (position.y + distance) % FIELDS_XY};
-        case Left: return Position{(position.x - distance) % FIELDS_XY, position.y};
-        case Up: return Position{position.x, (position.y - distance) % FIELDS_XY};
-        }
-    }
-
-
-    void loadProgram(QColor color, size_t x, size_t y) {
-        shared_ptr<Team> team = make_shared<Team>(color);
-
-        programs.push_back(Program(team, Position{x, y}, 2, 50, 1));
-
-        programs.back().banks[0] = make_shared<Bank>(team, vector<Instruction>{
-                                                              Instruction(BJUMP, LL, 1, 0)
-                                                          });
-
-        programs.back().banks[1] = make_shared<Bank>(team, vector<Instruction>{
-                                                              Instruction(SCAN, V, 1),
-                                                              Instruction(CREATE, LLL, 2, 50, 1),
-                                                              Instruction(TRANS, LL, 0, 0),
-                                                              Instruction(TRANS, LL, 1, 1),
-                                                              Instruction(TURN, L, 0),
-                                                              Instruction(AJUMP, L, 0)
-                                                          });
-        }
-
-    Program* findProgram(Position position) {
-        for(auto& program : programs) {
-            if(program.position.x == position.x && program.position.y == position.y && program.error == NoError) {
-                return &program;
-            }
-        }
-        return nullptr;
-    }
-
-    void simulate() {
-        for (auto& program : programs) {
-            auto& taskIndex = program.taskIndex;
-
-            if(program.error != NoError) {
-                continue;
-            }
-
-            if(program.tasks.empty()) {
-                continue;
-            }
-
-            taskIndex = (taskIndex + 1) % program.tasks.size();
-
-            if (taskIndex < program.tasks.size()) {
-                auto& task = program.tasks[taskIndex];
-
-                if(task.bankIndex >= program.banks.size()) {
-                    continue;
-                }
-
-                const auto bank_ptr = program.banks[task.bankIndex].get();
-
-                if(bank_ptr == nullptr || task.instIndex >= bank_ptr->instructions.size()) {
-                    continue;
-                }
-
-                const auto& bank = *bank_ptr;
-                const auto& inst = bank.instructions[task.instIndex];
-
-                //prevent overrideing of instuctions...
-
-
-
-                auto mapParameters = [this](Program& program, Task& task, const Instruction& inst) {
-                    task.p_a = &task.a;
-                    task.p_b = &task.b;
-                    task.p_c = &task.c;
-
-                    auto decode = [&](int32_t*& v) {
-                        switch(*v) {
-                            case Local_0:  v = &program.vars[0]; break;
-                            case Local_1:  v = &program.vars[1]; break;
-                            case Local_2:  v = &program.vars[2]; break;
-                            case Local_3:  v = &program.vars[3]; break;
-                            case Local_4:  v = &program.vars[4]; break;
-                            case Local_5:  v = &program.vars[5]; break;
-                            case Local_6:  v = &program.vars[6]; break;
-                            case Local_7:  v = &program.vars[7]; break;
-                            case Local_8:  v = &program.vars[8]; break;
-                            case Local_9:  v = &program.vars[9]; break;
-                            case Local_10: v = &program.vars[10]; break;
-                            case Local_11: v = &program.vars[11]; break;
-                            case Local_12: v = &program.vars[12]; break;
-                            case Local_13: v = &program.vars[13]; break;
-                            case Local_14: v = &program.vars[14]; break;
-                            case Local_15: v = &program.vars[15]; break;
-                            case Local_16: v = &program.vars[16]; break;
-                            case Local_17: v = &program.vars[17]; break;
-                            case Local_18: v = &program.vars[18]; break;
-                            case Local_19: v = &program.vars[19]; break;
-                            case LocalActive:
-                                v = &program.active;
-                                break;
-                            case LocalBanks:
-                                *v = program.banks.size();
-                                break;
-                            case LocalInstrSet:
-                                *v = program.instructionSet;
-                                break;
-                            case LocalMobile:
-                                *v = program.mobile;
-                                break;
-                            case LocalAge:
-                                *v = cycle - program.creationCycle;
-                                break;
-                            case LocalTasks:
-                                *v = program.tasks.size();
-                                break;
-                            case LocalGeneration:
-                                *v = program.generation;
-                                break;
-                            case LocalId:
-                                // @todo
-                                break;
-                            case RemoteActive: {
-                                auto remotePosition = calcPosition(program.position, task.direction, 1);
-                                auto remoteProgram = findProgram(remotePosition);
-                                if(remoteProgram) {
-                                    v = &remoteProgram->active;
-                                }
-                                else {
-                                    *v = 0;
-                                }
-                                break;
-                            }
-                            case RemoteBanks: {
-                                auto remotePosition = calcPosition(program.position, task.direction, 1);
-                                auto remoteProgram = findProgram(remotePosition);
-                                *v = remoteProgram ? remoteProgram->banks.size() : 0;
-                                break;
-                            }
-                            case RemoteInstrSet: {
-                                auto remotePosition = calcPosition(program.position, task.direction, 1);
-                                auto remoteProgram = findProgram(remotePosition);
-                                *v = remoteProgram ? remoteProgram->instructionSet : 0;
-                                break;
-                            }
-                            case RemoteMobile: {
-                                auto remotePosition = calcPosition(program.position, task.direction, 1);
-                                auto remoteProgram = findProgram(remotePosition);
-                                *v = remoteProgram ? remoteProgram->mobile: 0;
-                                break;
-                            }
-                            case RemoteAge: {
-                                auto remotePosition = calcPosition(program.position, task.direction, 1);
-                                auto remoteProgram = findProgram(remotePosition);
-                                *v = remoteProgram ? (cycle - remoteProgram->creationCycle) : 0;
-                                break;
-                            }
-                            case RemoteTasks: {
-                                auto remotePosition = calcPosition(program.position, task.direction, 1);
-                                auto remoteProgram = findProgram(remotePosition);
-                                *v = remoteProgram ? remoteProgram->tasks.size() : 0;
-                                break;
-                            }
-                            case RemoteGeneration: {
-                                auto remotePosition = calcPosition(program.position, task.direction, 1);
-                                auto remoteProgram = findProgram(remotePosition);
-                                *v = remoteProgram ? remoteProgram->generation : 0;
-                                break;
-                            }
-                            case GlobalPub:
-                                // @todo
-                                break;
-                            case GlobalTeam:
-                                // @todo
-                                break;
-                            case GlobalOwn:
-                                // @todo
-                                break;
-                            case GlobalOthers:
-                                // @todo
-                                break;
-                            case GlobalFields:
-                                *v = FIELDS_XY * FIELDS_XY;
-                                break;
-                            case GlobalTime:
-                                *v = cycle;
-                                break;
-                            case GlobalTimeout:
-                                *v = CYCLE_TIMEOUT;
-                                break;
-                        }
-                    };
-
-                    switch(inst.params) {
-                        case LLL: { task.a = inst.a;  task.b = inst.b;  task.c = inst.c;  break; }
-                        case LLV: { task.a = inst.a;  task.b = inst.b;  decode(task.p_c); break; }
-                        case LVL: { task.a = inst.a;  decode(task.p_b); task.c = inst.c;  break; }
-                        case LVV: { task.a = inst.a;  decode(task.p_b); decode(task.p_c); break; }
-                        case VLL: { decode(task.p_a); task.b = inst.b;  task.c = inst.c;  break; }
-                        case VLV: { decode(task.p_a); task.b = inst.b;  decode(task.p_c); break; }
-                        case VVL: { decode(task.p_a); decode(task.p_b); task.c = inst.c;  break; }
-                        case VVV: { decode(task.p_a); decode(task.p_b); decode(task.p_c); break; }
-                    }
-                };
-
-                mapParameters(program, task, inst);
-
-                switch(inst.command) {
-                case CREATE: {
-                    auto remotePosition = calcPosition(program.position, task.direction, 1);
-                    auto remoteProgram = findProgram(remotePosition);
-                    if(!remoteProgram) {
-                        programs.push_back(Program(program.team, remotePosition, *task.p_a, *task.p_b, *task.p_c));
-                    }
-                    task.instIndex += 1;
-                    break;
-                }
-
-                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.p_b < remoteProgram->banks.size() && *task.p_a < program.banks.size()) {
-                        remoteProgram->banks[*task.p_b] = program.banks[*task.p_a];
-                    }
-                    task.instIndex += 1;
-                    break;
-                }
-
-                case RTRANS: {
-                    auto remotePosition = calcPosition(program.position, task.direction, 1);
-                    auto remoteProgram = findProgram(remotePosition);
-                    if(remoteProgram && *task.p_a < remoteProgram->banks.size() && *task.p_b < program.banks.size()) {
-                        program.banks[*task.p_b] = remoteProgram->banks[*task.p_a];
-                    }
-                    task.instIndex += 1;
-                    break;
-                }
-
-                case TURN: {
-                    task.direction = static_cast<Direction>(qMax(0, (task.direction + ((*task.p_a >= 0) ? 1 : -1)) % 4));
-                    task.instIndex += 1;
-                    break;
-                }
-
-                case JUMP: {
-                    task.instIndex += *task.p_a;
-                    break;
-                }
-
-                case AJUMP: {
-                    task.instIndex = *task.p_a;
-                    break;
-                }
-
-                case BJUMP: {
-                    task.bankIndex = *task.p_a;
-                    task.instIndex = *task.p_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.p_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.p_a = 0;
-                    *task.p_b = 0;
-                    for(int i = 0; i < *task.p_c; ++i) {
-                        auto remotePosition = calcPosition(program.position, task.direction, i + 1);
-                        auto remoteProgram = findProgram(remotePosition);
-                        if(remoteProgram) {
-                            *task.p_a = remoteProgram->team == program.team ? 2: 1;
-                            *task.p_b = i;
-                            break;
-                        }
-                    }
-                    task.instIndex += 1;
-                    break;
-                }
-
-
-                case SET:
-                    *task.p_a = *task.p_b;
-                    task.instIndex += 1;
-                    break;
-
-                case ADD:
-                    *task.p_a += *task.p_b;
-                    task.instIndex += 1;
-                    break;
-
-                case SUB:
-                    *task.p_a -= *task.p_b;
-                    task.instIndex += 1;
-                    break;
-
-                case MUL:
-                    *task.p_a *= *task.p_b;
-                    task.instIndex += 1;
-                    break;
-
-                case DIV:
-                    *task.p_a /= *task.p_b;
-                    task.instIndex += 1;
-                    break;
-
-                case MOD:
-                    *task.p_a %= *task.p_b;
-                    task.instIndex += 1;
-                    break;
-
-                case MIN:
-                    *task.p_a = qMin(*task.p_a, *task.p_b);
-                    task.instIndex += 1;
-                    break;
-
-                case MAX:
-                    *task.p_a = qMax(*task.p_a, *task.p_b);
-                    task.instIndex += 1;
-                    break;
-
-                case RANDOM:
-                    *task.p_a = *task.p_b + (rand() % (*task.p_c - *task.p_b + 1));
-                    task.instIndex += 1;
-                break;
-
-                case IF:
-                    task.instIndex += ((*task.p_a == *task.p_b) ? 1 : 2);
-                break;
-
-                case IFN:
-                    task.instIndex += ((*task.p_a != *task.p_b) ? 1 : 2);
-                break;
-
-                case IFG:
-                    task.instIndex += ((*task.p_a > *task.p_b) ? 1 : 2);
-                break;
-
-                case IFL:
-                    task.instIndex += ((*task.p_a < *task.p_b) ? 1 : 2);
-                break;
+    Simulator();
 
-                case IFGE:
-                    task.instIndex += ((*task.p_a >= *task.p_b) ? 1 : 2);
-                break;
+    Position calcPosition(Position position, Direction direction, int32_t distance);
 
-                case IFLE:
-                    task.instIndex += ((*task.p_a <= *task.p_b) ? 1 : 2);
-                break;
+    void loadProgram(QColor color, size_t x, size_t y);
 
+    Program* findProgram(Position position);
 
-                default:
-                    task.instIndex += 1;
-                    break;
-                }
-            }
-        }
-        ++cycle;
-    }
+    void simulate();
 };