1
1

simulator.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. #include "simulator.h"
  2. Simulator::Simulator() {
  3. programs.reserve(FIELDS_XY * FIELDS_XY);
  4. // std::srand(std::time(0));
  5. std::srand(0);
  6. }
  7. Position Simulator::calcPosition(Position position, Direction direction, int32_t distance) {
  8. switch(direction) {
  9. case Right: return Position{(position.x + distance) % FIELDS_XY, position.y};
  10. case Down: return Position{position.x, (position.y + distance) % FIELDS_XY};
  11. case Left: return Position{(position.x - distance) % FIELDS_XY, position.y};
  12. case Up: return Position{position.x, (position.y - distance) % FIELDS_XY};
  13. }
  14. }
  15. void Simulator::decodeInstructionParameters(Task& task, const Instruction& instruction) {
  16. task.a = instruction.a;
  17. task.b = instruction.b;
  18. task.c = instruction.c;
  19. task.var_a = nullptr;
  20. task.var_b = nullptr;
  21. task.var_c = nullptr;
  22. switch(instruction.params) {
  23. case N:
  24. break;
  25. case L:
  26. task.a = instruction.a;
  27. break;
  28. case V:
  29. break;
  30. case LL:
  31. task.a = instruction.a;
  32. task.b = instruction.b;
  33. break;
  34. case LV:
  35. task.a = instruction.a;
  36. break;
  37. case VL:
  38. task.b = instruction.b;
  39. break;
  40. case VV:
  41. break;
  42. case LLL:
  43. task.a = instruction.a;
  44. task.b = instruction.b;
  45. task.c = instruction.c;
  46. break;
  47. case LLV:
  48. task.a = instruction.a;
  49. task.b = instruction.b;
  50. break;
  51. case LVL:
  52. task.a = instruction.a;
  53. task.c = instruction.c;
  54. break;
  55. case LVV:
  56. task.a = instruction.a;
  57. break;
  58. case VLL:
  59. task.b = instruction.b;
  60. task.c = instruction.c;
  61. break;
  62. case VLV:
  63. task.b = instruction.b;
  64. break;
  65. case VVL:
  66. task.c = instruction.c;
  67. break;
  68. case VVV:
  69. break;
  70. }
  71. //@todo: remove dummy!
  72. task.var_a = &task.a;
  73. task.var_b = &task.b;
  74. task.var_c = &task.c;
  75. }
  76. void Simulator::loadProgram(QColor color, size_t x, size_t y) {
  77. shared_ptr<Team> team = make_shared<Team>(color);
  78. programs.push_back(Program(team, Right, Position{x, y}, 2, 50, 1));
  79. programs.back().banks[0] = make_shared<Bank>(team, vector<Instruction>{
  80. Instruction(BJUMP, LL, 1, 0)
  81. });
  82. programs.back().banks[1] = make_shared<Bank>(team, vector<Instruction>{
  83. Instruction(SCAN, V, 1),
  84. Instruction(CREATE, LLL, 2, 50, 1),
  85. Instruction(TRANS, LL, 0, 0),
  86. Instruction(TRANS, LL, 1, 1),
  87. Instruction(TURN, L, 0),
  88. Instruction(AJUMP, L, 0)
  89. });
  90. }
  91. Program* Simulator::findProgram(Position position) {
  92. for(auto& program : programs) {
  93. if(program.position.x == position.x && program.position.y == position.y && program.error == NoError) {
  94. return &program;
  95. }
  96. }
  97. return nullptr;
  98. }
  99. void Simulator::removeErroneousPrograms() {
  100. auto it = std::remove_if(programs.begin(), programs.end(), [](const Program& program){ return program.error != NoError; });
  101. programs.erase(it, programs.end());
  102. }
  103. void Simulator::simulate() {
  104. removeErroneousPrograms();
  105. for (auto& program : programs) {
  106. auto& taskIndex = program.taskIndex;
  107. // error if no active task exists
  108. if(find_if(program.tasks.begin(), program.tasks.end(), [](const Task& task){ return !task.paused; }) == program.tasks.end()) {
  109. program.error = Unemployment;
  110. continue;
  111. }
  112. // switch to next unpasued task
  113. do {
  114. taskIndex = (taskIndex + 1) % program.tasks.size();
  115. } while(program.tasks[taskIndex].paused);
  116. // check if we are still executing an instruction
  117. auto& task = program.tasks[taskIndex];
  118. if(task.remainingCycles > 0) {
  119. --task.remainingCycles;
  120. continue;
  121. }
  122. else {
  123. endInstruction(program, task);
  124. beginInstruction(program, task);
  125. }
  126. }
  127. ++cycle;
  128. }
  129. void Simulator::beginInstruction(Program& program, Task& task) {
  130. // handle invalid bank number
  131. if(program.banks.empty() || task.bankIndex >= program.banks.size()) {
  132. program.error = InvalidBankNumber;
  133. return;
  134. }
  135. // handle autoreset to bank 0,0 if instructionIndex is out of banks bound or bank is empty
  136. if(!program.banks[task.bankIndex] || task.instIndex >= program.banks[task.bankIndex]->instructions.size()) {
  137. task.bankIndex = 0;
  138. task.instIndex = 0;
  139. }
  140. // handle data hunger
  141. if(task.bankIndex == 0 && !program.banks[0]) {
  142. program.error = DataHunger;
  143. return;
  144. }
  145. task.execBank = program.banks[task.bankIndex];
  146. auto& instruction = program.banks[task.bankIndex]->instructions[task.instIndex];
  147. decodeInstructionParameters(task, instruction);
  148. switch(instruction.command) {
  149. case CREATE:
  150. if(program.instructionSet < 2) {
  151. program.error = HigherInstructionSetRequired;
  152. break;
  153. }
  154. if(task.a < 0 || task.a > 2 || task.b < 1 || task.b > 50 || task.c < 0 || task.c > 1) {
  155. program.error = InvalidParameter;
  156. break;
  157. }
  158. task.remainingCycles = 100 + 50 * task.a + 25 * task.b + 120 * task.c;
  159. break;
  160. case MOVE:
  161. if(program.mobile < 1) {
  162. program.error = MobilityRequired;
  163. break;
  164. }
  165. task.remainingCycles = 20;
  166. break;
  167. case DIE:
  168. task.remainingCycles = 1;
  169. break;
  170. case TRANS: {
  171. if(program.instructionSet < 1) {
  172. program.error = HigherInstructionSetRequired;
  173. break;
  174. }
  175. if(task.a < 0 || task.a >= program.banks.size()) {
  176. program.error = InvalidBankNumber;
  177. break;
  178. }
  179. const auto& bank = program.banks[task.a];
  180. task.remainingCycles = 14 + (bank ? bank->instructions.size() : 0);
  181. break;
  182. }
  183. case RTRANS: {
  184. if(program.instructionSet < 1) {
  185. program.error = HigherInstructionSetRequired;
  186. break;
  187. }
  188. if(task.a < 0 || task.a >= 50 || task.b < 0 || task.b >= program.banks.size()) {
  189. program.error = InvalidBankNumber;
  190. break;
  191. }
  192. auto remotePosition = calcPosition(program.position, task.direction, 1);
  193. auto remoteProgram = findProgram(remotePosition);
  194. task.remainingCycles = 14 + remoteProgram ? (task.a < remoteProgram->banks.size() ? (remoteProgram->banks[task.a] ? remoteProgram->banks[task.a]->instructions.size() : 0): 0): 0;
  195. break;
  196. }
  197. case TURN:
  198. task.remainingCycles = 8;
  199. break;
  200. case JUMP:
  201. task.remainingCycles = 1;
  202. break;
  203. case AJUMP:
  204. task.remainingCycles = 1;
  205. break;
  206. case BJUMP:
  207. task.remainingCycles = 2;
  208. break;
  209. case SCAN:
  210. if(program.instructionSet < 1) {
  211. program.error = HigherInstructionSetRequired;
  212. break;
  213. }
  214. task.remainingCycles = 8;
  215. break;
  216. case FARSCAN:
  217. if(program.instructionSet < 1) {
  218. program.error = HigherInstructionSetRequired;
  219. break;
  220. }
  221. task.remainingCycles = 10 + 3 * task.c;
  222. break;
  223. case SET:
  224. task.remainingCycles = 2;
  225. break;
  226. case ADD:
  227. task.remainingCycles = 2;
  228. break;
  229. case SUB:
  230. task.remainingCycles = 2;
  231. break;
  232. case MUL:
  233. task.remainingCycles = 2;
  234. break;
  235. case DIV:
  236. task.remainingCycles = 2;
  237. break;
  238. case MOD:
  239. task.remainingCycles = 2;
  240. break;
  241. case MIN:
  242. task.remainingCycles = 2;
  243. break;
  244. case MAX:
  245. task.remainingCycles = 2;
  246. break;
  247. case RANDOM:
  248. if(task.b > task.c) {
  249. program.error = InvalidParameter;
  250. break;
  251. }
  252. task.remainingCycles = 1;
  253. break;
  254. case IF:
  255. task.remainingCycles = 2;
  256. break;
  257. case IFN:
  258. task.remainingCycles = 2;
  259. break;
  260. case IFG:
  261. task.remainingCycles = 2;
  262. break;
  263. case IFL:
  264. task.remainingCycles = 2;
  265. break;
  266. case IFGE:
  267. task.remainingCycles = 2;
  268. break;
  269. case IFLE:
  270. task.remainingCycles = 2;
  271. break;
  272. case INIT:
  273. task.remainingCycles = 2;
  274. break;
  275. case BREAK:
  276. task.remainingCycles = 1;
  277. break;
  278. case RESUME:
  279. task.remainingCycles = 1;
  280. break;
  281. case SEIZE:
  282. task.remainingCycles = 1;
  283. break;
  284. case SLEEP:
  285. if(task.a > 2000) {
  286. program.error = InvalidParameter;
  287. break;
  288. }
  289. task.remainingCycles = task.a;
  290. break;
  291. case QUIT:
  292. task.remainingCycles = 1;
  293. break;
  294. }
  295. }
  296. void Simulator::endInstruction(Program& program, Task& task) {
  297. // we are not executing yet
  298. if(!task.execBank || program.error != NoError) {
  299. return;
  300. }
  301. // check if bank is overwritten, skip execution of current command and begin new bank at instruction 0
  302. if(task.execBank != program.banks[task.bankIndex]) {
  303. task.instIndex = 0;
  304. return;
  305. }
  306. // execute command
  307. auto& instruction = task.execBank->instructions[task.instIndex];
  308. switch(instruction.command) {
  309. case CREATE: {
  310. auto remotePosition = calcPosition(program.position, task.direction, 1);
  311. auto remoteProgram = findProgram(remotePosition);
  312. if(!remoteProgram) {
  313. programs.push_back(Program(program.team, task.direction, remotePosition, task.a, task.b, task.c));
  314. }
  315. task.instIndex += 1;
  316. }
  317. case MOVE: {
  318. auto remotePosition = calcPosition(program.position, task.direction, 1);
  319. auto remoteProgram = findProgram(remotePosition);
  320. if(!remoteProgram) {
  321. program.position = remotePosition;
  322. }
  323. task.instIndex += 1;
  324. break;
  325. }
  326. case DIE: {
  327. program.error = DieExecuted;
  328. task.instIndex += 1;
  329. break;
  330. }
  331. case TRANS: {
  332. auto remotePosition = calcPosition(program.position, task.direction, 1);
  333. auto remoteProgram = findProgram(remotePosition);
  334. if(remoteProgram && task.b < remoteProgram->banks.size() && task.a < program.banks.size()) {
  335. remoteProgram->banks[task.b] = program.banks[task.a];
  336. }
  337. task.instIndex += 1;
  338. break;
  339. }
  340. case RTRANS: {
  341. auto remotePosition = calcPosition(program.position, task.direction, 1);
  342. auto remoteProgram = findProgram(remotePosition);
  343. if(remoteProgram && task.a < remoteProgram->banks.size() && task.b < program.banks.size()) {
  344. program.banks[task.b] = remoteProgram->banks[task.a];
  345. }
  346. task.instIndex += 1;
  347. break;
  348. }
  349. case TURN: {
  350. task.direction = static_cast<Direction>(qMax(0, (task.direction + ((task.a >= 0) ? 1 : -1)) % 4));
  351. task.instIndex += 1;
  352. break;
  353. }
  354. case JUMP: {
  355. task.instIndex += task.a;
  356. break;
  357. }
  358. case AJUMP: {
  359. task.instIndex = task.a;
  360. break;
  361. }
  362. case BJUMP: {
  363. task.bankIndex = task.a;
  364. task.instIndex = task.b;
  365. break;
  366. }
  367. case SCAN: {
  368. // Scans a field, result in #a
  369. // #a=0 ...empty.
  370. // #a=1 ...enemy
  371. // #a=2 ...friend
  372. auto remotePosition = calcPosition(program.position, task.direction, 1);
  373. auto remoteProgram = findProgram(remotePosition);
  374. *task.var_a = !remoteProgram ? 0 : remoteProgram->team == program.team ? 2: 1;
  375. task.instIndex += 1;
  376. break;
  377. }
  378. case FARSCAN: {
  379. // Scans up to c fields straight in front of the bot.
  380. // The nearest bot's type is stored in #a:
  381. // #a=0 ...empty.
  382. // #a=1 ...enemy
  383. // #a=2 ...friend
  384. // Its distance is stored in #b.
  385. *task.var_a = 0;
  386. *task.var_b = 0;
  387. for(int i = 0; i < task.c; ++i) {
  388. auto remotePosition = calcPosition(program.position, task.direction, i + 1);
  389. auto remoteProgram = findProgram(remotePosition);
  390. if(remoteProgram) {
  391. *task.var_a = remoteProgram->team == program.team ? 2: 1;
  392. *task.var_b = i;
  393. break;
  394. }
  395. }
  396. task.instIndex += 1;
  397. break;
  398. }
  399. case SET:
  400. *task.var_a = task.b;
  401. task.instIndex += 1;
  402. break;
  403. case ADD:
  404. *task.var_a += task.b;
  405. task.instIndex += 1;
  406. break;
  407. case SUB:
  408. *task.var_a -= task.b;
  409. task.instIndex += 1;
  410. break;
  411. case MUL:
  412. *task.var_a *= task.b;
  413. task.instIndex += 1;
  414. break;
  415. case DIV:
  416. if(task.b == 0) {
  417. program.error = DivisionByZero;
  418. break;
  419. }
  420. *task.var_a /= task.b;
  421. task.instIndex += 1;
  422. break;
  423. case MOD:
  424. if(task.b == 0) {
  425. program.error = DivisionByZero;
  426. break;
  427. }
  428. *task.var_a %= task.b;
  429. task.instIndex += 1;
  430. break;
  431. case MIN:
  432. *task.var_a = qMin(task.a, task.b);
  433. task.instIndex += 1;
  434. break;
  435. case MAX:
  436. *task.var_a = qMax(task.a, task.b);
  437. task.instIndex += 1;
  438. break;
  439. case RANDOM:
  440. *task.var_a = task.b + (rand() % (task.c - task.b + 1));
  441. task.instIndex += 1;
  442. break;
  443. case IF:
  444. task.instIndex += ((task.a == task.b) ? 1 : 2);
  445. break;
  446. case IFN:
  447. task.instIndex += ((task.a != task.b) ? 1 : 2);
  448. break;
  449. case IFG:
  450. task.instIndex += ((task.a > task.b) ? 1 : 2);
  451. break;
  452. case IFL:
  453. task.instIndex += ((task.a < task.b) ? 1 : 2);
  454. break;
  455. case IFGE:
  456. task.instIndex += ((task.a >= task.b) ? 1 : 2);
  457. break;
  458. case IFLE:
  459. task.instIndex += ((task.a <= task.b) ? 1 : 2);
  460. break;
  461. default:
  462. task.instIndex += 1;
  463. break;
  464. }
  465. }
  466. #if 0
  467. void Simulator::simulatex() {
  468. for (auto& program : programs) {
  469. auto& taskIndex = program.taskIndex;
  470. if(program.error != NoError) {
  471. continue;
  472. }
  473. if(program.tasks.empty()) {
  474. continue;
  475. }
  476. if (taskIndex < program.tasks.size()) {
  477. auto& task = program.tasks[taskIndex];
  478. if(task.bankIndex >= program.banks.size()) {
  479. continue;
  480. }
  481. const auto bank_ptr = program.banks[task.bankIndex].get();
  482. if(bank_ptr == nullptr || task.instIndex >= bank_ptr->instructions.size()) {
  483. continue;
  484. }
  485. const auto& bank = *bank_ptr;
  486. const auto& inst = bank.instructions[task.instIndex];
  487. //prevent overrideing of instuctions...
  488. auto mapParameters = [this](Program& program, Task& task, const Instruction& inst) {
  489. task.p_a = &task.a;
  490. task.p_b = &task.b;
  491. task.p_c = &task.c;
  492. auto decode = [&](int32_t*& v) {
  493. switch(*v) {
  494. case Local_0: v = &program.vars[0]; break;
  495. case Local_1: v = &program.vars[1]; break;
  496. case Local_2: v = &program.vars[2]; break;
  497. case Local_3: v = &program.vars[3]; break;
  498. case Local_4: v = &program.vars[4]; break;
  499. case Local_5: v = &program.vars[5]; break;
  500. case Local_6: v = &program.vars[6]; break;
  501. case Local_7: v = &program.vars[7]; break;
  502. case Local_8: v = &program.vars[8]; break;
  503. case Local_9: v = &program.vars[9]; break;
  504. case Local_10: v = &program.vars[10]; break;
  505. case Local_11: v = &program.vars[11]; break;
  506. case Local_12: v = &program.vars[12]; break;
  507. case Local_13: v = &program.vars[13]; break;
  508. case Local_14: v = &program.vars[14]; break;
  509. case Local_15: v = &program.vars[15]; break;
  510. case Local_16: v = &program.vars[16]; break;
  511. case Local_17: v = &program.vars[17]; break;
  512. case Local_18: v = &program.vars[18]; break;
  513. case Local_19: v = &program.vars[19]; break;
  514. case LocalActive:
  515. v = &program.active;
  516. break;
  517. case LocalBanks:
  518. *v = program.banks.size();
  519. break;
  520. case LocalInstrSet:
  521. *v = program.instructionSet;
  522. break;
  523. case LocalMobile:
  524. *v = program.mobile;
  525. break;
  526. case LocalAge:
  527. *v = cycle - program.creationCycle;
  528. break;
  529. case LocalTasks:
  530. *v = program.tasks.size();
  531. break;
  532. case LocalGeneration:
  533. *v = program.generation;
  534. break;
  535. case LocalId:
  536. // @todo
  537. break;
  538. case RemoteActive: {
  539. auto remotePosition = calcPosition(program.position, task.direction, 1);
  540. auto remoteProgram = findProgram(remotePosition);
  541. if(remoteProgram) {
  542. v = &remoteProgram->active;
  543. }
  544. else {
  545. *v = 0;
  546. }
  547. break;
  548. }
  549. case RemoteBanks: {
  550. auto remotePosition = calcPosition(program.position, task.direction, 1);
  551. auto remoteProgram = findProgram(remotePosition);
  552. *v = remoteProgram ? remoteProgram->banks.size() : 0;
  553. break;
  554. }
  555. case RemoteInstrSet: {
  556. auto remotePosition = calcPosition(program.position, task.direction, 1);
  557. auto remoteProgram = findProgram(remotePosition);
  558. *v = remoteProgram ? remoteProgram->instructionSet : 0;
  559. break;
  560. }
  561. case RemoteMobile: {
  562. auto remotePosition = calcPosition(program.position, task.direction, 1);
  563. auto remoteProgram = findProgram(remotePosition);
  564. *v = remoteProgram ? remoteProgram->mobile: 0;
  565. break;
  566. }
  567. case RemoteAge: {
  568. auto remotePosition = calcPosition(program.position, task.direction, 1);
  569. auto remoteProgram = findProgram(remotePosition);
  570. *v = remoteProgram ? (cycle - remoteProgram->creationCycle) : 0;
  571. break;
  572. }
  573. case RemoteTasks: {
  574. auto remotePosition = calcPosition(program.position, task.direction, 1);
  575. auto remoteProgram = findProgram(remotePosition);
  576. *v = remoteProgram ? remoteProgram->tasks.size() : 0;
  577. break;
  578. }
  579. case RemoteGeneration: {
  580. auto remotePosition = calcPosition(program.position, task.direction, 1);
  581. auto remoteProgram = findProgram(remotePosition);
  582. *v = remoteProgram ? remoteProgram->generation : 0;
  583. break;
  584. }
  585. case GlobalPub:
  586. // @todo
  587. break;
  588. case GlobalTeam:
  589. // @todo
  590. break;
  591. case GlobalOwn:
  592. // @todo
  593. break;
  594. case GlobalOthers:
  595. // @todo
  596. break;
  597. case GlobalFields:
  598. *v = FIELDS_XY * FIELDS_XY;
  599. break;
  600. case GlobalTime:
  601. *v = cycle;
  602. break;
  603. case GlobalTimeout:
  604. *v = CYCLE_TIMEOUT;
  605. break;
  606. }
  607. };
  608. switch(inst.params) {
  609. case LLL: { task.a = inst.a; task.b = inst.b; task.c = inst.c; break; }
  610. case LLV: { task.a = inst.a; task.b = inst.b; decode(task.p_c); break; }
  611. case LVL: { task.a = inst.a; decode(task.p_b); task.c = inst.c; break; }
  612. case LVV: { task.a = inst.a; decode(task.p_b); decode(task.p_c); break; }
  613. case VLL: { decode(task.p_a); task.b = inst.b; task.c = inst.c; break; }
  614. case VLV: { decode(task.p_a); task.b = inst.b; decode(task.p_c); break; }
  615. case VVL: { decode(task.p_a); decode(task.p_b); task.c = inst.c; break; }
  616. case VVV: { decode(task.p_a); decode(task.p_b); decode(task.p_c); break; }
  617. }
  618. };
  619. mapParameters(program, task, inst);
  620. switch(inst.command) {
  621. case CREATE: {
  622. auto remotePosition = calcPosition(program.position, task.direction, 1);
  623. auto remoteProgram = findProgram(remotePosition);
  624. if(!remoteProgram) {
  625. programs.push_back(Program(program.team, remotePosition, *task.p_a, *task.p_b, *task.p_c));
  626. }
  627. task.instIndex += 1;
  628. break;
  629. }
  630. case MOVE: {
  631. auto remotePosition = calcPosition(program.position, task.direction, 1);
  632. auto remoteProgram = findProgram(remotePosition);
  633. if(!remoteProgram) {
  634. program.position = remotePosition;
  635. }
  636. task.instIndex += 1;
  637. break;
  638. }
  639. case DIE: {
  640. program.error = DieExecuted;
  641. task.instIndex += 1;
  642. break;
  643. }
  644. case TRANS: {
  645. auto remotePosition = calcPosition(program.position, task.direction, 1);
  646. auto remoteProgram = findProgram(remotePosition);
  647. if(remoteProgram && *task.p_b < remoteProgram->banks.size() && *task.p_a < program.banks.size()) {
  648. remoteProgram->banks[*task.p_b] = program.banks[*task.p_a];
  649. }
  650. task.instIndex += 1;
  651. break;
  652. }
  653. case RTRANS: {
  654. auto remotePosition = calcPosition(program.position, task.direction, 1);
  655. auto remoteProgram = findProgram(remotePosition);
  656. if(remoteProgram && *task.p_a < remoteProgram->banks.size() && *task.p_b < program.banks.size()) {
  657. program.banks[*task.p_b] = remoteProgram->banks[*task.p_a];
  658. }
  659. task.instIndex += 1;
  660. break;
  661. }
  662. case TURN: {
  663. task.direction = static_cast<Direction>(qMax(0, (task.direction + ((*task.p_a >= 0) ? 1 : -1)) % 4));
  664. task.instIndex += 1;
  665. break;
  666. }
  667. case JUMP: {
  668. task.instIndex += *task.p_a;
  669. break;
  670. }
  671. case AJUMP: {
  672. task.instIndex = *task.p_a;
  673. break;
  674. }
  675. case BJUMP: {
  676. task.bankIndex = *task.p_a;
  677. task.instIndex = *task.p_b;
  678. break;
  679. }
  680. case SCAN: {
  681. // Scans a field, result in #a
  682. // #a=0 ...empty.
  683. // #a=1 ...enemy
  684. // #a=2 ...friend
  685. auto remotePosition = calcPosition(program.position, task.direction, 1);
  686. auto remoteProgram = findProgram(remotePosition);
  687. *task.p_a = !remoteProgram ? 0 : remoteProgram->team == program.team ? 2: 1;
  688. task.instIndex += 1;
  689. break;
  690. }
  691. case FARSCAN: {
  692. // Scans up to c fields straight in front of the bot.
  693. // The nearest bot's type is stored in #a:
  694. // #a=0 ...empty.
  695. // #a=1 ...enemy
  696. // #a=2 ...friend
  697. // Its distance is stored in #b.
  698. *task.p_a = 0;
  699. *task.p_b = 0;
  700. for(int i = 0; i < *task.p_c; ++i) {
  701. auto remotePosition = calcPosition(program.position, task.direction, i + 1);
  702. auto remoteProgram = findProgram(remotePosition);
  703. if(remoteProgram) {
  704. *task.p_a = remoteProgram->team == program.team ? 2: 1;
  705. *task.p_b = i;
  706. break;
  707. }
  708. }
  709. task.instIndex += 1;
  710. break;
  711. }
  712. case SET:
  713. *task.p_a = *task.p_b;
  714. task.instIndex += 1;
  715. break;
  716. case ADD:
  717. *task.p_a += *task.p_b;
  718. task.instIndex += 1;
  719. break;
  720. case SUB:
  721. *task.p_a -= *task.p_b;
  722. task.instIndex += 1;
  723. break;
  724. case MUL:
  725. *task.p_a *= *task.p_b;
  726. task.instIndex += 1;
  727. break;
  728. case DIV:
  729. *task.p_a /= *task.p_b;
  730. task.instIndex += 1;
  731. break;
  732. case MOD:
  733. *task.p_a %= *task.p_b;
  734. task.instIndex += 1;
  735. break;
  736. case MIN:
  737. *task.p_a = qMin(*task.p_a, *task.p_b);
  738. task.instIndex += 1;
  739. break;
  740. case MAX:
  741. *task.p_a = qMax(*task.p_a, *task.p_b);
  742. task.instIndex += 1;
  743. break;
  744. case RANDOM:
  745. *task.p_a = *task.p_b + (rand() % (*task.p_c - *task.p_b + 1));
  746. task.instIndex += 1;
  747. break;
  748. case IF:
  749. task.instIndex += ((*task.p_a == *task.p_b) ? 1 : 2);
  750. break;
  751. case IFN:
  752. task.instIndex += ((*task.p_a != *task.p_b) ? 1 : 2);
  753. break;
  754. case IFG:
  755. task.instIndex += ((*task.p_a > *task.p_b) ? 1 : 2);
  756. break;
  757. case IFL:
  758. task.instIndex += ((*task.p_a < *task.p_b) ? 1 : 2);
  759. break;
  760. case IFGE:
  761. task.instIndex += ((*task.p_a >= *task.p_b) ? 1 : 2);
  762. break;
  763. case IFLE:
  764. task.instIndex += ((*task.p_a <= *task.p_b) ? 1 : 2);
  765. break;
  766. default:
  767. task.instIndex += 1;
  768. break;
  769. }
  770. }
  771. }
  772. ++cycle;
  773. }
  774. #endif