simulator.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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::loadProgram(QColor color, size_t x, size_t y) {
  16. shared_ptr<Team> team = make_shared<Team>(color);
  17. programs.push_back(Program(team, Position{x, y}, 2, 50, 1));
  18. programs.back().banks[0] = make_shared<Bank>(team, vector<Instruction>{
  19. Instruction(BJUMP, LL, 1, 0)
  20. });
  21. programs.back().banks[1] = make_shared<Bank>(team, vector<Instruction>{
  22. Instruction(SCAN, V, 1),
  23. Instruction(CREATE, LLL, 2, 50, 1),
  24. Instruction(TRANS, LL, 0, 0),
  25. Instruction(TRANS, LL, 1, 1),
  26. Instruction(TURN, L, 0),
  27. Instruction(AJUMP, L, 0)
  28. });
  29. }
  30. Program* Simulator::findProgram(Position position) {
  31. for(auto& program : programs) {
  32. if(program.position.x == position.x && program.position.y == position.y && program.error == NoError) {
  33. return &program;
  34. }
  35. }
  36. return nullptr;
  37. }
  38. void Simulator::simulate() {
  39. for (auto& program : programs) {
  40. auto& taskIndex = program.taskIndex;
  41. if(program.error != NoError) {
  42. continue;
  43. }
  44. if(program.tasks.empty()) {
  45. continue;
  46. }
  47. taskIndex = (taskIndex + 1) % program.tasks.size();
  48. if (taskIndex < program.tasks.size()) {
  49. auto& task = program.tasks[taskIndex];
  50. if(task.bankIndex >= program.banks.size()) {
  51. continue;
  52. }
  53. const auto bank_ptr = program.banks[task.bankIndex].get();
  54. if(bank_ptr == nullptr || task.instIndex >= bank_ptr->instructions.size()) {
  55. continue;
  56. }
  57. const auto& bank = *bank_ptr;
  58. const auto& inst = bank.instructions[task.instIndex];
  59. //prevent overrideing of instuctions...
  60. auto mapParameters = [this](Program& program, Task& task, const Instruction& inst) {
  61. task.p_a = &task.a;
  62. task.p_b = &task.b;
  63. task.p_c = &task.c;
  64. auto decode = [&](int32_t*& v) {
  65. switch(*v) {
  66. case Local_0: v = &program.vars[0]; break;
  67. case Local_1: v = &program.vars[1]; break;
  68. case Local_2: v = &program.vars[2]; break;
  69. case Local_3: v = &program.vars[3]; break;
  70. case Local_4: v = &program.vars[4]; break;
  71. case Local_5: v = &program.vars[5]; break;
  72. case Local_6: v = &program.vars[6]; break;
  73. case Local_7: v = &program.vars[7]; break;
  74. case Local_8: v = &program.vars[8]; break;
  75. case Local_9: v = &program.vars[9]; break;
  76. case Local_10: v = &program.vars[10]; break;
  77. case Local_11: v = &program.vars[11]; break;
  78. case Local_12: v = &program.vars[12]; break;
  79. case Local_13: v = &program.vars[13]; break;
  80. case Local_14: v = &program.vars[14]; break;
  81. case Local_15: v = &program.vars[15]; break;
  82. case Local_16: v = &program.vars[16]; break;
  83. case Local_17: v = &program.vars[17]; break;
  84. case Local_18: v = &program.vars[18]; break;
  85. case Local_19: v = &program.vars[19]; break;
  86. case LocalActive:
  87. v = &program.active;
  88. break;
  89. case LocalBanks:
  90. *v = program.banks.size();
  91. break;
  92. case LocalInstrSet:
  93. *v = program.instructionSet;
  94. break;
  95. case LocalMobile:
  96. *v = program.mobile;
  97. break;
  98. case LocalAge:
  99. *v = cycle - program.creationCycle;
  100. break;
  101. case LocalTasks:
  102. *v = program.tasks.size();
  103. break;
  104. case LocalGeneration:
  105. *v = program.generation;
  106. break;
  107. case LocalId:
  108. // @todo
  109. break;
  110. case RemoteActive: {
  111. auto remotePosition = calcPosition(program.position, task.direction, 1);
  112. auto remoteProgram = findProgram(remotePosition);
  113. if(remoteProgram) {
  114. v = &remoteProgram->active;
  115. }
  116. else {
  117. *v = 0;
  118. }
  119. break;
  120. }
  121. case RemoteBanks: {
  122. auto remotePosition = calcPosition(program.position, task.direction, 1);
  123. auto remoteProgram = findProgram(remotePosition);
  124. *v = remoteProgram ? remoteProgram->banks.size() : 0;
  125. break;
  126. }
  127. case RemoteInstrSet: {
  128. auto remotePosition = calcPosition(program.position, task.direction, 1);
  129. auto remoteProgram = findProgram(remotePosition);
  130. *v = remoteProgram ? remoteProgram->instructionSet : 0;
  131. break;
  132. }
  133. case RemoteMobile: {
  134. auto remotePosition = calcPosition(program.position, task.direction, 1);
  135. auto remoteProgram = findProgram(remotePosition);
  136. *v = remoteProgram ? remoteProgram->mobile: 0;
  137. break;
  138. }
  139. case RemoteAge: {
  140. auto remotePosition = calcPosition(program.position, task.direction, 1);
  141. auto remoteProgram = findProgram(remotePosition);
  142. *v = remoteProgram ? (cycle - remoteProgram->creationCycle) : 0;
  143. break;
  144. }
  145. case RemoteTasks: {
  146. auto remotePosition = calcPosition(program.position, task.direction, 1);
  147. auto remoteProgram = findProgram(remotePosition);
  148. *v = remoteProgram ? remoteProgram->tasks.size() : 0;
  149. break;
  150. }
  151. case RemoteGeneration: {
  152. auto remotePosition = calcPosition(program.position, task.direction, 1);
  153. auto remoteProgram = findProgram(remotePosition);
  154. *v = remoteProgram ? remoteProgram->generation : 0;
  155. break;
  156. }
  157. case GlobalPub:
  158. // @todo
  159. break;
  160. case GlobalTeam:
  161. // @todo
  162. break;
  163. case GlobalOwn:
  164. // @todo
  165. break;
  166. case GlobalOthers:
  167. // @todo
  168. break;
  169. case GlobalFields:
  170. *v = FIELDS_XY * FIELDS_XY;
  171. break;
  172. case GlobalTime:
  173. *v = cycle;
  174. break;
  175. case GlobalTimeout:
  176. *v = CYCLE_TIMEOUT;
  177. break;
  178. }
  179. };
  180. switch(inst.params) {
  181. case LLL: { task.a = inst.a; task.b = inst.b; task.c = inst.c; break; }
  182. case LLV: { task.a = inst.a; task.b = inst.b; decode(task.p_c); break; }
  183. case LVL: { task.a = inst.a; decode(task.p_b); task.c = inst.c; break; }
  184. case LVV: { task.a = inst.a; decode(task.p_b); decode(task.p_c); break; }
  185. case VLL: { decode(task.p_a); task.b = inst.b; task.c = inst.c; break; }
  186. case VLV: { decode(task.p_a); task.b = inst.b; decode(task.p_c); break; }
  187. case VVL: { decode(task.p_a); decode(task.p_b); task.c = inst.c; break; }
  188. case VVV: { decode(task.p_a); decode(task.p_b); decode(task.p_c); break; }
  189. }
  190. };
  191. mapParameters(program, task, inst);
  192. switch(inst.command) {
  193. case CREATE: {
  194. auto remotePosition = calcPosition(program.position, task.direction, 1);
  195. auto remoteProgram = findProgram(remotePosition);
  196. if(!remoteProgram) {
  197. programs.push_back(Program(program.team, remotePosition, *task.p_a, *task.p_b, *task.p_c));
  198. }
  199. task.instIndex += 1;
  200. break;
  201. }
  202. case MOVE: {
  203. auto remotePosition = calcPosition(program.position, task.direction, 1);
  204. auto remoteProgram = findProgram(remotePosition);
  205. if(!remoteProgram) {
  206. program.position = remotePosition;
  207. }
  208. task.instIndex += 1;
  209. break;
  210. }
  211. case DIE: {
  212. program.error = DieExecuted;
  213. task.instIndex += 1;
  214. break;
  215. }
  216. case TRANS: {
  217. auto remotePosition = calcPosition(program.position, task.direction, 1);
  218. auto remoteProgram = findProgram(remotePosition);
  219. if(remoteProgram && *task.p_b < remoteProgram->banks.size() && *task.p_a < program.banks.size()) {
  220. remoteProgram->banks[*task.p_b] = program.banks[*task.p_a];
  221. }
  222. task.instIndex += 1;
  223. break;
  224. }
  225. case RTRANS: {
  226. auto remotePosition = calcPosition(program.position, task.direction, 1);
  227. auto remoteProgram = findProgram(remotePosition);
  228. if(remoteProgram && *task.p_a < remoteProgram->banks.size() && *task.p_b < program.banks.size()) {
  229. program.banks[*task.p_b] = remoteProgram->banks[*task.p_a];
  230. }
  231. task.instIndex += 1;
  232. break;
  233. }
  234. case TURN: {
  235. task.direction = static_cast<Direction>(qMax(0, (task.direction + ((*task.p_a >= 0) ? 1 : -1)) % 4));
  236. task.instIndex += 1;
  237. break;
  238. }
  239. case JUMP: {
  240. task.instIndex += *task.p_a;
  241. break;
  242. }
  243. case AJUMP: {
  244. task.instIndex = *task.p_a;
  245. break;
  246. }
  247. case BJUMP: {
  248. task.bankIndex = *task.p_a;
  249. task.instIndex = *task.p_b;
  250. break;
  251. }
  252. case SCAN: {
  253. // Scans a field, result in #a
  254. // #a=0 ...empty.
  255. // #a=1 ...enemy
  256. // #a=2 ...friend
  257. auto remotePosition = calcPosition(program.position, task.direction, 1);
  258. auto remoteProgram = findProgram(remotePosition);
  259. *task.p_a = !remoteProgram ? 0 : remoteProgram->team == program.team ? 2: 1;
  260. task.instIndex += 1;
  261. break;
  262. }
  263. case FARSCAN: {
  264. // Scans up to c fields straight in front of the bot.
  265. // The nearest bot's type is stored in #a:
  266. // #a=0 ...empty.
  267. // #a=1 ...enemy
  268. // #a=2 ...friend
  269. // Its distance is stored in #b.
  270. *task.p_a = 0;
  271. *task.p_b = 0;
  272. for(int i = 0; i < *task.p_c; ++i) {
  273. auto remotePosition = calcPosition(program.position, task.direction, i + 1);
  274. auto remoteProgram = findProgram(remotePosition);
  275. if(remoteProgram) {
  276. *task.p_a = remoteProgram->team == program.team ? 2: 1;
  277. *task.p_b = i;
  278. break;
  279. }
  280. }
  281. task.instIndex += 1;
  282. break;
  283. }
  284. case SET:
  285. *task.p_a = *task.p_b;
  286. task.instIndex += 1;
  287. break;
  288. case ADD:
  289. *task.p_a += *task.p_b;
  290. task.instIndex += 1;
  291. break;
  292. case SUB:
  293. *task.p_a -= *task.p_b;
  294. task.instIndex += 1;
  295. break;
  296. case MUL:
  297. *task.p_a *= *task.p_b;
  298. task.instIndex += 1;
  299. break;
  300. case DIV:
  301. *task.p_a /= *task.p_b;
  302. task.instIndex += 1;
  303. break;
  304. case MOD:
  305. *task.p_a %= *task.p_b;
  306. task.instIndex += 1;
  307. break;
  308. case MIN:
  309. *task.p_a = qMin(*task.p_a, *task.p_b);
  310. task.instIndex += 1;
  311. break;
  312. case MAX:
  313. *task.p_a = qMax(*task.p_a, *task.p_b);
  314. task.instIndex += 1;
  315. break;
  316. case RANDOM:
  317. *task.p_a = *task.p_b + (rand() % (*task.p_c - *task.p_b + 1));
  318. task.instIndex += 1;
  319. break;
  320. case IF:
  321. task.instIndex += ((*task.p_a == *task.p_b) ? 1 : 2);
  322. break;
  323. case IFN:
  324. task.instIndex += ((*task.p_a != *task.p_b) ? 1 : 2);
  325. break;
  326. case IFG:
  327. task.instIndex += ((*task.p_a > *task.p_b) ? 1 : 2);
  328. break;
  329. case IFL:
  330. task.instIndex += ((*task.p_a < *task.p_b) ? 1 : 2);
  331. break;
  332. case IFGE:
  333. task.instIndex += ((*task.p_a >= *task.p_b) ? 1 : 2);
  334. break;
  335. case IFLE:
  336. task.instIndex += ((*task.p_a <= *task.p_b) ? 1 : 2);
  337. break;
  338. default:
  339. task.instIndex += 1;
  340. break;
  341. }
  342. }
  343. }
  344. ++cycle;
  345. }