| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- #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;
- }
|