test_move.py 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. # coding: utf-8
  2. import pytest
  3. from freezegun import freeze_time
  4. from synergine2_xyz.move.intention import MoveToIntention
  5. from synergine2_xyz.simulation import XYZSimulation
  6. from opencombat.simulation.move import MoveWithRotationBehaviour
  7. from opencombat.simulation.move import MoveToMechanism
  8. from opencombat.simulation.move import MoveBehaviour
  9. from opencombat.simulation.move import SubjectFinishMoveEvent
  10. from opencombat.simulation.move import SubjectStartRotationEvent
  11. from opencombat.simulation.move import SubjectFinishRotationEvent
  12. from opencombat.simulation.move import SubjectContinueRotationEvent
  13. from opencombat.simulation.move import SubjectStartTileMoveEvent
  14. from opencombat.simulation.move import SubjectContinueTileMoveEvent
  15. from opencombat.simulation.move import SubjectFinishTileMoveEvent
  16. from opencombat.simulation.subject import TankSubject
  17. from opencombat.simulation.subject import ManSubject
  18. from opencombat.user_action import UserAction
  19. def test_move_and_rotate_behaviour__begin_rotate(config):
  20. simulation = XYZSimulation(config)
  21. simulation.physics.graph.add_edge('0.0', '1.1', {})
  22. simulation.physics.graph.add_edge('1.1', '2.1', {})
  23. subject = TankSubject(
  24. config,
  25. simulation,
  26. position=(0, 0),
  27. )
  28. move = MoveToIntention(
  29. to=(2, 1),
  30. gui_action=UserAction.ORDER_MOVE,
  31. )
  32. subject.intentions.set(move)
  33. move_behaviour = MoveWithRotationBehaviour(
  34. config=config,
  35. simulation=simulation,
  36. subject=subject,
  37. )
  38. # Rotation required to begin move
  39. with freeze_time("2000-01-01 00:00:00", tz_offset=0):
  40. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  41. assert {
  42. 'gui_action': UserAction.ORDER_MOVE,'gui_action': UserAction.ORDER_MOVE,
  43. 'path': [
  44. (0, 0),
  45. (1, 1),
  46. (2, 1),
  47. ],
  48. 'rotate_relative': 45,
  49. 'rotate_absolute': 45,
  50. } == data
  51. events = move_behaviour.action(data)
  52. assert events
  53. assert 1 == len(events)
  54. assert isinstance(events[0], SubjectStartRotationEvent)
  55. assert 45.0 == events[0].rotate_relative
  56. assert 4.9995 == events[0].duration
  57. assert subject.position == (0, 0)
  58. assert subject.direction == 0
  59. assert subject.rotate_to == 45
  60. assert subject.start_rotation == 946684800.0
  61. assert subject.rotate_duration == 4.9995
  62. assert subject.intentions.get(MoveToIntention)
  63. # This is 1 second before end of rotation
  64. with freeze_time("2000-01-01 00:00:04", tz_offset=0):
  65. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  66. assert {
  67. 'gui_action': UserAction.ORDER_MOVE,
  68. 'rotate_relative': 45,
  69. 'rotate_absolute': 45,
  70. } == data
  71. events = move_behaviour.action(data)
  72. assert 1 == len(events)
  73. assert isinstance(events[0], SubjectContinueRotationEvent)
  74. assert 9 == round(events[0].rotate_relative)
  75. assert 0.9995 == events[0].duration
  76. assert subject.position == (0, 0)
  77. assert int(subject.direction) == 36
  78. assert subject.rotate_to == 45
  79. assert subject.start_rotation == 946684804.0
  80. assert subject.rotate_duration == 0.9995
  81. assert subject.intentions.get(MoveToIntention)
  82. # We are now just after rotation duration, a move will start
  83. with freeze_time("2000-01-01 00:00:05", tz_offset=0):
  84. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  85. assert {
  86. 'gui_action': UserAction.ORDER_MOVE,
  87. 'tile_move_to': (1, 1),
  88. 'rotate_to_finished': 45,
  89. } == data
  90. events = move_behaviour.action(data)
  91. assert 2 == len(events)
  92. assert isinstance(events[1], SubjectStartTileMoveEvent)
  93. assert isinstance(events[0], SubjectFinishRotationEvent)
  94. assert (1, 1) == events[1].move_to
  95. assert 9.0 == events[1].duration
  96. assert subject.position == (0, 0)
  97. assert subject.moving_to == (1, 1)
  98. assert subject.move_duration == 9.0
  99. assert subject.start_move == 946684805.0
  100. assert subject.intentions.get(MoveToIntention)
  101. # We are during the move
  102. with freeze_time("2000-01-01 00:00:13", tz_offset=0):
  103. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  104. assert {
  105. 'gui_action': UserAction.ORDER_MOVE,
  106. 'tile_move_to': (1, 1),
  107. } == data
  108. events = move_behaviour.action(data)
  109. assert 1 == len(events)
  110. assert isinstance(events[0], SubjectContinueTileMoveEvent)
  111. assert (1, 1) == events[0].move_to
  112. assert 1.0 == events[0].duration
  113. assert subject.intentions.get(MoveToIntention)
  114. # We are after the move
  115. with freeze_time("2000-01-01 00:00:14", tz_offset=0):
  116. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  117. assert {
  118. 'gui_action': UserAction.ORDER_MOVE,
  119. 'tile_move_to_finished': (1, 1),
  120. 'rotate_relative': 45,
  121. 'rotate_absolute': 90,
  122. } == data
  123. events = move_behaviour.action(data)
  124. assert 2 == len(events)
  125. assert isinstance(events[0], SubjectFinishTileMoveEvent)
  126. assert isinstance(events[1], SubjectStartRotationEvent)
  127. assert (1, 1) == events[0].move_to
  128. assert 4.9995 == events[1].duration
  129. assert 45 == events[1].rotate_relative
  130. assert (1, 1) == subject.position
  131. assert (-1, -1) == subject.moving_to
  132. assert -1 == subject.start_move
  133. assert -1 == subject.move_duration
  134. assert subject.rotate_to == 90
  135. assert subject.start_rotation == 946684814.0
  136. assert subject.rotate_duration == 4.9995
  137. assert subject.intentions.get(MoveToIntention)
  138. # We are rotating
  139. with freeze_time("2000-01-01 00:00:18", tz_offset=0):
  140. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  141. assert {
  142. 'gui_action': UserAction.ORDER_MOVE,
  143. 'rotate_relative': 45,
  144. 'rotate_absolute': 90,
  145. } == data
  146. events = move_behaviour.action(data)
  147. assert 1 == len(events)
  148. assert isinstance(events[0], SubjectContinueRotationEvent)
  149. assert 9 == round(events[0].rotate_relative)
  150. assert 0.9995 == events[0].duration
  151. assert subject.position == (1, 1)
  152. assert int(subject.direction) == 81
  153. assert subject.rotate_to == 90
  154. assert subject.start_rotation == 946684818.0
  155. assert subject.rotate_duration == 0.9995
  156. assert subject.intentions.get(MoveToIntention)
  157. # We finish rotating and start to move to final tile
  158. with freeze_time("2000-01-01 00:00:19", tz_offset=0):
  159. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  160. assert {
  161. 'gui_action': UserAction.ORDER_MOVE,
  162. 'tile_move_to': (2, 1),
  163. 'rotate_to_finished': 90,
  164. } == data
  165. events = move_behaviour.action(data)
  166. assert 2 == len(events)
  167. assert isinstance(events[1], SubjectStartTileMoveEvent)
  168. assert isinstance(events[0], SubjectFinishRotationEvent)
  169. assert (2, 1) == events[1].move_to
  170. assert 9.0 == events[1].duration
  171. assert subject.position == (1, 1)
  172. assert subject.moving_to == (2, 1)
  173. assert subject.move_duration == 9.0
  174. assert subject.start_move == 946684819.0
  175. assert subject.intentions.get(MoveToIntention)
  176. # We are moving to final tile
  177. with freeze_time("2000-01-01 00:00:27", tz_offset=0):
  178. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  179. assert {
  180. 'gui_action': UserAction.ORDER_MOVE,
  181. 'tile_move_to': (2, 1),
  182. } == data
  183. events = move_behaviour.action(data)
  184. assert 1 == len(events)
  185. assert isinstance(events[0], SubjectContinueTileMoveEvent)
  186. assert (2, 1) == events[0].move_to
  187. assert 1.0 == events[0].duration
  188. assert subject.intentions.get(MoveToIntention)
  189. # We arrived on final tile
  190. with freeze_time("2000-01-01 00:00:28", tz_offset=0):
  191. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  192. assert {
  193. 'gui_action': UserAction.ORDER_MOVE,
  194. 'move_to_finished': (2, 1),
  195. } == data
  196. events = move_behaviour.action(data)
  197. assert 1 == len(events)
  198. assert isinstance(events[0], SubjectFinishMoveEvent)
  199. assert (2, 1) == events[0].move_to
  200. assert (2, 1) == subject.position
  201. assert (-1, -1) == subject.moving_to
  202. assert -1 == subject.start_move
  203. assert -1 == subject.move_duration
  204. with pytest.raises(KeyError):
  205. assert subject.intentions.get(MoveToIntention)
  206. def test_move_and_rotate_behaviour__begin_move(config):
  207. simulation = XYZSimulation(config)
  208. simulation.physics.graph.add_edge('0.0', '0.1', {})
  209. simulation.physics.graph.add_edge('0.1', '1.1', {})
  210. subject = TankSubject(
  211. config,
  212. simulation,
  213. position=(0, 0),
  214. )
  215. move = MoveToIntention(
  216. to=(1, 1),
  217. gui_action=UserAction.ORDER_MOVE,
  218. )
  219. subject.intentions.set(move)
  220. move_behaviour = MoveWithRotationBehaviour(
  221. config=config,
  222. simulation=simulation,
  223. subject=subject,
  224. )
  225. # First is a move
  226. with freeze_time("2000-01-01 00:00:00", tz_offset=0):
  227. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  228. assert {
  229. 'gui_action': UserAction.ORDER_MOVE,
  230. 'path': [
  231. (0, 0),
  232. (0, 1),
  233. (1, 1),
  234. ],
  235. 'tile_move_to': (0, 1),
  236. } == data
  237. events = move_behaviour.action(data)
  238. assert 1 == len(events)
  239. assert isinstance(events[0], SubjectStartTileMoveEvent)
  240. assert (0, 1) == events[0].move_to
  241. assert 9.0 == events[0].duration
  242. assert subject.intentions.get(MoveToIntention)
  243. # Continue the move, rest 1s
  244. with freeze_time("2000-01-01 00:00:08", tz_offset=0):
  245. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  246. assert {
  247. 'gui_action': UserAction.ORDER_MOVE,
  248. 'tile_move_to': (0, 1),
  249. } == data
  250. events = move_behaviour.action(data)
  251. assert 1 == len(events)
  252. assert isinstance(events[0], SubjectContinueTileMoveEvent)
  253. assert (0, 1) == events[0].move_to
  254. assert 1.0 == events[0].duration
  255. assert subject.intentions.get(MoveToIntention)
  256. # Tile move finished, begin a rotate
  257. with freeze_time("2000-01-01 00:00:09", tz_offset=0):
  258. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  259. assert {
  260. 'gui_action': UserAction.ORDER_MOVE,
  261. 'tile_move_to_finished': (0, 1),
  262. 'rotate_relative': 90,
  263. 'rotate_absolute': 90,
  264. } == data
  265. events = move_behaviour.action(data)
  266. assert 2 == len(events)
  267. assert isinstance(events[0], SubjectFinishTileMoveEvent)
  268. assert isinstance(events[1], SubjectStartRotationEvent)
  269. assert (0, 1) == events[0].move_to
  270. assert 10 == round(events[1].duration)
  271. assert 90 == events[1].rotate_relative
  272. assert (0, 1) == subject.position
  273. assert (-1, -1) == subject.moving_to
  274. assert -1 == subject.start_move
  275. assert -1 == subject.move_duration
  276. assert subject.rotate_to == 90
  277. assert subject.start_rotation == 946684809.0
  278. assert round(subject.rotate_duration) == 10
  279. assert subject.intentions.get(MoveToIntention)
  280. # We are rotating, rest 1s
  281. with freeze_time("2000-01-01 00:00:18", tz_offset=0):
  282. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  283. assert {
  284. 'gui_action': UserAction.ORDER_MOVE,
  285. 'rotate_relative': 90,
  286. 'rotate_absolute': 90,
  287. } == data
  288. events = move_behaviour.action(data)
  289. assert 1 == len(events)
  290. assert isinstance(events[0], SubjectContinueRotationEvent)
  291. assert 9 == round(events[0].rotate_relative)
  292. assert 1 == round(events[0].duration)
  293. assert subject.position == (0, 1)
  294. assert int(subject.direction) == 81
  295. assert subject.rotate_to == 90
  296. assert subject.start_rotation == 946684818.0
  297. assert round(subject.rotate_duration) == 1
  298. assert subject.intentions.get(MoveToIntention)
  299. # We finish rotating and start to move to final tile
  300. with freeze_time("2000-01-01 00:00:19", tz_offset=0):
  301. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  302. assert {
  303. 'gui_action': UserAction.ORDER_MOVE,
  304. 'tile_move_to': (1, 1),
  305. 'rotate_to_finished': 90,
  306. } == data
  307. events = move_behaviour.action(data)
  308. assert 2 == len(events)
  309. assert isinstance(events[1], SubjectStartTileMoveEvent)
  310. assert isinstance(events[0], SubjectFinishRotationEvent)
  311. assert (1, 1) == events[1].move_to
  312. assert 9.0 == events[1].duration
  313. assert subject.position == (0, 1)
  314. assert subject.moving_to == (1, 1)
  315. assert subject.move_duration == 9.0
  316. assert subject.start_move == 946684819.0
  317. assert subject.intentions.get(MoveToIntention)
  318. # Continue the move, rest 1s
  319. with freeze_time("2000-01-01 00:00:27", tz_offset=0):
  320. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  321. assert {
  322. 'gui_action': UserAction.ORDER_MOVE,
  323. 'tile_move_to': (1, 1),
  324. } == data
  325. events = move_behaviour.action(data)
  326. assert 1 == len(events)
  327. assert isinstance(events[0], SubjectContinueTileMoveEvent)
  328. assert (1, 1) == events[0].move_to
  329. assert 1.0 == events[0].duration
  330. assert subject.moving_to == (1, 1)
  331. assert subject.move_duration == 1.0
  332. assert subject.start_move == 946684819.0
  333. assert subject.intentions.get(MoveToIntention)
  334. # We arrived on final tile
  335. with freeze_time("2000-01-01 00:00:28", tz_offset=0):
  336. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  337. assert {
  338. 'gui_action': UserAction.ORDER_MOVE,
  339. 'move_to_finished': (1, 1),
  340. } == data
  341. events = move_behaviour.action(data)
  342. assert 1 == len(events)
  343. assert isinstance(events[0], SubjectFinishMoveEvent)
  344. assert (1, 1) == events[0].move_to
  345. assert (1, 1) == subject.position
  346. assert (-1, -1) == subject.moving_to
  347. assert -1 == subject.start_move
  348. assert -1 == subject.move_duration
  349. with pytest.raises(KeyError):
  350. assert subject.intentions.get(MoveToIntention)
  351. def test_move_behaviour(config):
  352. simulation = XYZSimulation(config)
  353. simulation.physics.graph.add_edge('0.0', '0.1', {})
  354. simulation.physics.graph.add_edge('0.1', '1.1', {})
  355. subject = ManSubject(
  356. config,
  357. simulation,
  358. position=(0, 0),
  359. )
  360. move = MoveToIntention(
  361. to=(1, 1),
  362. gui_action=UserAction.ORDER_MOVE,
  363. )
  364. subject.intentions.set(move)
  365. move_behaviour = MoveBehaviour(
  366. config=config,
  367. simulation=simulation,
  368. subject=subject,
  369. )
  370. # First begin move
  371. with freeze_time("2000-01-01 00:00:00", tz_offset=0):
  372. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  373. assert {
  374. 'gui_action': UserAction.ORDER_MOVE,
  375. 'path': [
  376. (0, 0),
  377. (0, 1),
  378. (1, 1),
  379. ],
  380. 'tile_move_to': (0, 1),
  381. } == data
  382. events = move_behaviour.action(data)
  383. assert 1 == len(events)
  384. assert isinstance(events[0], SubjectStartTileMoveEvent)
  385. assert (0, 1) == events[0].move_to
  386. assert 3.0 == events[0].duration
  387. assert subject.intentions.get(MoveToIntention)
  388. # Continue the move, rest 1s
  389. with freeze_time("2000-01-01 00:00:02", tz_offset=0):
  390. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  391. assert {
  392. 'gui_action': UserAction.ORDER_MOVE,
  393. 'tile_move_to': (0, 1),
  394. } == data
  395. events = move_behaviour.action(data)
  396. assert 1 == len(events)
  397. assert isinstance(events[0], SubjectContinueTileMoveEvent)
  398. assert (0, 1) == events[0].move_to
  399. assert 1.0 == events[0].duration
  400. assert subject.intentions.get(MoveToIntention)
  401. # Tile move finished, begin a new move
  402. with freeze_time("2000-01-01 00:00:03", tz_offset=0):
  403. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  404. assert {
  405. 'gui_action': UserAction.ORDER_MOVE,
  406. 'tile_move_to_finished': (0, 1),
  407. 'tile_move_to': (1, 1),
  408. } == data
  409. events = move_behaviour.action(data)
  410. assert 2 == len(events)
  411. assert isinstance(events[0], SubjectFinishTileMoveEvent)
  412. assert isinstance(events[1], SubjectStartTileMoveEvent)
  413. assert (0, 1) == events[0].move_to
  414. assert (1, 1) == events[1].move_to
  415. assert 3 == events[1].duration
  416. assert (0, 1) == subject.position
  417. assert (1, 1) == subject.moving_to
  418. assert 946684803.0 == subject.start_move
  419. assert 3 == subject.move_duration
  420. assert subject.intentions.get(MoveToIntention)
  421. # We are moving, rest 1s
  422. with freeze_time("2000-01-01 00:00:05", tz_offset=0):
  423. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  424. assert {
  425. 'gui_action': UserAction.ORDER_MOVE,
  426. 'tile_move_to': (1, 1),
  427. } == data
  428. events = move_behaviour.action(data)
  429. assert 1 == len(events)
  430. assert isinstance(events[0], SubjectContinueTileMoveEvent)
  431. assert (1, 1) == events[0].move_to
  432. assert 1.0 == events[0].duration
  433. assert (0, 1) == subject.position
  434. assert (1, 1) == subject.moving_to
  435. assert 946684805.0 == subject.start_move
  436. assert 1 == subject.move_duration
  437. assert subject.intentions.get(MoveToIntention)
  438. # We arrived on final tile
  439. with freeze_time("2000-01-01 00:00:06", tz_offset=0):
  440. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  441. assert {
  442. 'gui_action': UserAction.ORDER_MOVE,
  443. 'move_to_finished': (1, 1),
  444. } == data
  445. events = move_behaviour.action(data)
  446. assert 1 == len(events)
  447. assert isinstance(events[0], SubjectFinishMoveEvent)
  448. assert (1, 1) == events[0].move_to
  449. assert (1, 1) == subject.position
  450. assert (-1, -1) == subject.moving_to
  451. assert -1 == subject.start_move
  452. assert -1 == subject.move_duration
  453. with pytest.raises(KeyError):
  454. assert subject.intentions.get(MoveToIntention)
  455. def test_move_and_rotate_behaviour__rotate_negatively(config):
  456. simulation = XYZSimulation(config)
  457. simulation.physics.graph.add_edge('0.0', '1.-1', {})
  458. simulation.physics.graph.add_edge('1.-1', '2.-1', {})
  459. subject = TankSubject(
  460. config,
  461. simulation,
  462. position=(0, 0),
  463. )
  464. move = MoveToIntention(
  465. to=(2, -1),
  466. gui_action=UserAction.ORDER_MOVE,
  467. )
  468. subject.intentions.set(move)
  469. move_behaviour = MoveWithRotationBehaviour(
  470. config=config,
  471. simulation=simulation,
  472. subject=subject,
  473. )
  474. # First is a move
  475. with freeze_time("2000-01-01 00:00:00", tz_offset=0):
  476. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  477. assert {
  478. 'gui_action': UserAction.ORDER_MOVE,
  479. 'path': [
  480. (0, 0),
  481. (1, -1),
  482. (2, -1),
  483. ],
  484. 'rotate_absolute': 135.0,
  485. 'rotate_relative': 135.0,
  486. } == data
  487. events = move_behaviour.action(data)
  488. assert 1 == len(events)
  489. assert isinstance(events[0], SubjectStartRotationEvent)
  490. assert 135 == events[0].rotate_relative
  491. assert 135 == events[0].rotate_absolute
  492. assert 15 == round(events[0].duration)
  493. assert subject.intentions.get(MoveToIntention)
  494. with freeze_time("2000-01-01 00:00:15", tz_offset=0):
  495. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  496. assert {
  497. 'gui_action': UserAction.ORDER_MOVE,
  498. 'rotate_to_finished': 135,
  499. 'tile_move_to': (1, -1),
  500. } == data
  501. events = move_behaviour.action(data)
  502. assert 2 == len(events)
  503. assert isinstance(events[1], SubjectStartTileMoveEvent)
  504. assert isinstance(events[0], SubjectFinishRotationEvent)
  505. assert (1, -1) == events[1].move_to
  506. assert 9.0 == events[1].duration
  507. assert 135 == events[0].rotation_absolute
  508. assert subject.intentions.get(MoveToIntention)
  509. with freeze_time("2000-01-01 00:00:24", tz_offset=0):
  510. data = move_behaviour.run({MoveToMechanism: move.get_data()})
  511. assert {
  512. 'gui_action': UserAction.ORDER_MOVE,
  513. 'rotate_absolute': 90,
  514. 'rotate_relative': -45,
  515. 'tile_move_to_finished': (1, -1),
  516. } == data
  517. events = move_behaviour.action(data)
  518. assert 2 == len(events)
  519. assert isinstance(events[0], SubjectFinishTileMoveEvent)
  520. assert isinstance(events[1], SubjectStartRotationEvent)
  521. assert (1, -1) == events[0].move_to
  522. assert 90 == events[1].rotate_absolute
  523. assert -45 == events[1].rotate_relative
  524. assert 5 == round(events[1].duration)
  525. assert subject.intentions.get(MoveToIntention)