| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- #ifndef SIMULATOR_H
- #define SIMULATOR_H
- #include <array>
- #include <vector>
- #include <memory>
- #include <climits>
- #include <stdint.h>
- using namespace std;
- 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,
- };
- 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)
- {
- }
- };
- using Bank = shared_ptr<vector<Instruction>>;
- using BankIndex = size_t;
- using InstIndex = size_t;
- using TaskIndex = size_t;
- struct Task {
- Direction direction = Right;
- BankIndex bankIndex = 0;
- InstIndex instIndex = 0;
- };
- struct Program {
- QColor color;
- Position position;
- vector<Task> tasks;
- TaskIndex taskIndex = 0;
- vector<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(QColor _color, Position _position, int32_t instructionSet, int32_t slotCount, int32_t mobile) {
- color = _color;
- position = _position;
- banks.resize(slotCount);
- tasks.resize(1);
- }
- };
- struct Field {
- Program* program = nullptr;
- };
- struct Simulator {
- size_t cylcle = 0;
- vector<Program> programs;
- size_t size = 0;
- Simulator() {
- size = 20;
- programs.reserve(size * size);
- // 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) % size, position.y};
- case Down: return Position{position.x, (position.y + distance) % size};
- case Left: return Position{(position.x - distance) % size, position.y};
- case Up: return Position{position.x, (position.y - distance) % size};
- }
- }
- void loadProgram(QColor color, size_t x, size_t y) {
- programs.push_back(Program(color, Position{x, y}, 2, 50, 1));
- {
- Bank bank = make_shared<vector<Instruction>>();
- bank->push_back(Instruction(BJUMP, LL, 1, 0));
- programs.back().banks[0] = bank;
- }
- {
- Bank bank = make_shared<vector<Instruction>>();
- bank->push_back(Instruction(SCAN, V, 1));
- bank->push_back(Instruction(CREATE, LLL, 2, 50, 1));
- bank->push_back(Instruction(TRANS, LL, 0, 0));
- bank->push_back(Instruction(TRANS, LL, 1, 1));
- bank->push_back(Instruction(RANDOM, VLL, 5, -5, 5));
- bank->push_back(Instruction(TURN, V, 5));
- bank->push_back(Instruction(AJUMP, L, 0));
- programs.back().banks[1] = bank;
- }
- }
- Program* findProgram(Position position) {
- for(auto& program : programs) {
- if(program.position.x == position.x && program.position.y == position.y) {
- return &program;
- }
- }
- return nullptr;
- }
- void simulate() {
- for (auto& program : programs) {
- auto& taskIndex = program.taskIndex;
- 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->size()) {
- continue;
- }
- const auto& bank = *bank_ptr;
- const auto& inst = bank[task.instIndex];
- //prevent overrideing of instuctions...
- int32_t a_safe = inst.a;
- int32_t b_safe = inst.b;
- int32_t c_safe = inst.c;
- int32_t* a = &a_safe;
- int32_t* b = &b_safe;
- int32_t* c = &c_safe;
- auto decode = [&](int*& v) {
- if(*v >= 0 && *v <= 20) {
- v = &program.vars[*v];
- }
- else {
- switch(*v) {
- case 21: break;
- }
- }
- };
- switch(inst.params) {
- case LLL: { break; }
- case LLV: { decode(c); break; }
- case LVL: { decode(b); break; }
- case LVV: { decode(b); decode(c); break; }
- case VLL: { decode(a); break; }
- case VLV: { decode(a); decode(c); break; }
- case VVL: { decode(a); decode(b); break; }
- case VVV: { decode(a); decode(b); decode(c); break; }
- }
- switch(inst.command) {
- case CREATE: {
- auto remotePosition = calcPosition(program.position, task.direction, 1);
- auto remoteProgram = findProgram(remotePosition);
- if(!remoteProgram) {
- programs.push_back(Program(program.color, remotePosition, *a, *b, *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 TRANS: {
- auto remotePosition = calcPosition(program.position, task.direction, 1);
- auto remoteProgram = findProgram(remotePosition);
- if(remoteProgram && *b < remoteProgram->banks.size() && *a < program.banks.size()) {
- remoteProgram->banks[*b] = program.banks[*a];
- }
- task.instIndex += 1;
- break;
- }
- case RTRANS: {
- auto remotePosition = calcPosition(program.position, task.direction, 1);
- auto remoteProgram = findProgram(remotePosition);
- if(remoteProgram && *a < remoteProgram->banks.size() && *b < program.banks.size()) {
- program.banks[*b] = remoteProgram->banks[*a];
- }
- task.instIndex += 1;
- break;
- }
- case TURN: {
- task.direction = static_cast<Direction>(qMax(0, (task.direction + ((*a >= 0) ? 1 : -1)) % 4));
- task.instIndex += 1;
- break;
- }
- case JUMP: {
- task.instIndex += *a;
- break;
- }
- case AJUMP: {
- task.instIndex = *a;
- break;
- }
- case BJUMP: {
- task.bankIndex = *a;
- task.instIndex = *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);
- *a = !remoteProgram ? 0 : remoteProgram->color == program.color ? 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.
- *a = 0;
- *b = 0;
- for(int i = 0; i < *c; ++i) {
- auto remotePosition = calcPosition(program.position, task.direction, i + 1);
- auto remoteProgram = findProgram(remotePosition);
- if(remoteProgram) {
- *a = remoteProgram->color == program.color ? 2: 1;
- *b = i;
- break;
- }
- }
- task.instIndex += 1;
- break;
- }
- case SET:
- *a = *b;
- task.instIndex += 1;
- break;
- case ADD:
- *a += *b;
- task.instIndex += 1;
- break;
- case SUB:
- *a -= *b;
- task.instIndex += 1;
- break;
- case MUL:
- *a *= *b;
- task.instIndex += 1;
- break;
- case DIV:
- *a /= *b;
- task.instIndex += 1;
- break;
- case MOD:
- *a %= *b;
- task.instIndex += 1;
- break;
- case MIN:
- *a = qMin(*a, *b);
- task.instIndex += 1;
- break;
- case MAX:
- *a = qMax(*a, *b);
- task.instIndex += 1;
- break;
- case RANDOM:
- *a = *b + (rand() % (*c - *b + 1));
- task.instIndex += 1;
- break;
- case IF:
- task.instIndex += ((*a == *b) ? 1 : 2);
- break;
- case IFN:
- task.instIndex += ((*a != *b) ? 1 : 2);
- break;
- case IFG:
- task.instIndex += ((*a > *b) ? 1 : 2);
- break;
- case IFL:
- task.instIndex += ((*a < *b) ? 1 : 2);
- break;
- case IFGE:
- task.instIndex += ((*a >= *b) ? 1 : 2);
- break;
- case IFLE:
- task.instIndex += ((*a <= *b) ? 1 : 2);
- break;
- default:
- task.instIndex += 1;
- break;
- }
- }
- }
- ++cylcle;
- }
- };
- #endif // SIMULATOR_H
|