# coding: utf-8 import pytest from freezegun import freeze_time from synergine2_xyz.move.intention import MoveToIntention from synergine2_xyz.simulation import XYZSimulation from opencombat.simulation.move import MoveWithRotationBehaviour from opencombat.simulation.move import MoveToMechanism from opencombat.simulation.move import MoveBehaviour from opencombat.simulation.move import SubjectFinishMoveEvent from opencombat.simulation.move import SubjectStartRotationEvent from opencombat.simulation.move import SubjectFinishRotationEvent from opencombat.simulation.move import SubjectContinueRotationEvent from opencombat.simulation.move import SubjectStartTileMoveEvent from opencombat.simulation.move import SubjectContinueTileMoveEvent from opencombat.simulation.move import SubjectFinishTileMoveEvent from opencombat.simulation.subject import TankSubject from opencombat.simulation.subject import ManSubject from opencombat.user_action import UserAction def test_move_and_rotate_behaviour__begin_rotate(config): simulation = XYZSimulation(config) simulation.physics.graph.add_edge('0.0', '1.1', {}) simulation.physics.graph.add_edge('1.1', '2.1', {}) subject = TankSubject( config, simulation, position=(0, 0), ) move = MoveToIntention( to=(2, 1), gui_action=UserAction.ORDER_MOVE, ) subject.intentions.set(move) move_behaviour = MoveWithRotationBehaviour( config=config, simulation=simulation, subject=subject, ) # Rotation required to begin move with freeze_time("2000-01-01 00:00:00", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE,'gui_action': UserAction.ORDER_MOVE, 'path': [ (0, 0), (1, 1), (2, 1), ], 'rotate_relative': 45, 'rotate_absolute': 45, } == data events = move_behaviour.action(data) assert events assert 1 == len(events) assert isinstance(events[0], SubjectStartRotationEvent) assert 45.0 == events[0].rotate_relative assert 4.9995 == events[0].duration assert subject.position == (0, 0) assert subject.direction == 0 assert subject.rotate_to == 45 assert subject.start_rotation == 946684800.0 assert subject.rotate_duration == 4.9995 assert subject.intentions.get(MoveToIntention) # This is 1 second before end of rotation with freeze_time("2000-01-01 00:00:04", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'rotate_relative': 45, 'rotate_absolute': 45, } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueRotationEvent) assert 9 == round(events[0].rotate_relative) assert 0.9995 == events[0].duration assert subject.position == (0, 0) assert int(subject.direction) == 36 assert subject.rotate_to == 45 assert subject.start_rotation == 946684804.0 assert subject.rotate_duration == 0.9995 assert subject.intentions.get(MoveToIntention) # We are now just after rotation duration, a move will start with freeze_time("2000-01-01 00:00:05", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (1, 1), 'rotate_to_finished': 45, } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[1], SubjectStartTileMoveEvent) assert isinstance(events[0], SubjectFinishRotationEvent) assert (1, 1) == events[1].move_to assert 9.0 == events[1].duration assert subject.position == (0, 0) assert subject.moving_to == (1, 1) assert subject.move_duration == 9.0 assert subject.start_move == 946684805.0 assert subject.intentions.get(MoveToIntention) # We are during the move with freeze_time("2000-01-01 00:00:13", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (1, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueTileMoveEvent) assert (1, 1) == events[0].move_to assert 1.0 == events[0].duration assert subject.intentions.get(MoveToIntention) # We are after the move with freeze_time("2000-01-01 00:00:14", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to_finished': (1, 1), 'rotate_relative': 45, 'rotate_absolute': 90, } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[0], SubjectFinishTileMoveEvent) assert isinstance(events[1], SubjectStartRotationEvent) assert (1, 1) == events[0].move_to assert 4.9995 == events[1].duration assert 45 == events[1].rotate_relative assert (1, 1) == subject.position assert (-1, -1) == subject.moving_to assert -1 == subject.start_move assert -1 == subject.move_duration assert subject.rotate_to == 90 assert subject.start_rotation == 946684814.0 assert subject.rotate_duration == 4.9995 assert subject.intentions.get(MoveToIntention) # We are rotating with freeze_time("2000-01-01 00:00:18", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'rotate_relative': 45, 'rotate_absolute': 90, } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueRotationEvent) assert 9 == round(events[0].rotate_relative) assert 0.9995 == events[0].duration assert subject.position == (1, 1) assert int(subject.direction) == 81 assert subject.rotate_to == 90 assert subject.start_rotation == 946684818.0 assert subject.rotate_duration == 0.9995 assert subject.intentions.get(MoveToIntention) # We finish rotating and start to move to final tile with freeze_time("2000-01-01 00:00:19", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (2, 1), 'rotate_to_finished': 90, } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[1], SubjectStartTileMoveEvent) assert isinstance(events[0], SubjectFinishRotationEvent) assert (2, 1) == events[1].move_to assert 9.0 == events[1].duration assert subject.position == (1, 1) assert subject.moving_to == (2, 1) assert subject.move_duration == 9.0 assert subject.start_move == 946684819.0 assert subject.intentions.get(MoveToIntention) # We are moving to final tile with freeze_time("2000-01-01 00:00:27", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (2, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueTileMoveEvent) assert (2, 1) == events[0].move_to assert 1.0 == events[0].duration assert subject.intentions.get(MoveToIntention) # We arrived on final tile with freeze_time("2000-01-01 00:00:28", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'move_to_finished': (2, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectFinishMoveEvent) assert (2, 1) == events[0].move_to assert (2, 1) == subject.position assert (-1, -1) == subject.moving_to assert -1 == subject.start_move assert -1 == subject.move_duration with pytest.raises(KeyError): assert subject.intentions.get(MoveToIntention) def test_move_and_rotate_behaviour__begin_move(config): simulation = XYZSimulation(config) simulation.physics.graph.add_edge('0.0', '0.1', {}) simulation.physics.graph.add_edge('0.1', '1.1', {}) subject = TankSubject( config, simulation, position=(0, 0), ) move = MoveToIntention( to=(1, 1), gui_action=UserAction.ORDER_MOVE, ) subject.intentions.set(move) move_behaviour = MoveWithRotationBehaviour( config=config, simulation=simulation, subject=subject, ) # First is a move with freeze_time("2000-01-01 00:00:00", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'path': [ (0, 0), (0, 1), (1, 1), ], 'tile_move_to': (0, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectStartTileMoveEvent) assert (0, 1) == events[0].move_to assert 9.0 == events[0].duration assert subject.intentions.get(MoveToIntention) # Continue the move, rest 1s with freeze_time("2000-01-01 00:00:08", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (0, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueTileMoveEvent) assert (0, 1) == events[0].move_to assert 1.0 == events[0].duration assert subject.intentions.get(MoveToIntention) # Tile move finished, begin a rotate with freeze_time("2000-01-01 00:00:09", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to_finished': (0, 1), 'rotate_relative': 90, 'rotate_absolute': 90, } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[0], SubjectFinishTileMoveEvent) assert isinstance(events[1], SubjectStartRotationEvent) assert (0, 1) == events[0].move_to assert 10 == round(events[1].duration) assert 90 == events[1].rotate_relative assert (0, 1) == subject.position assert (-1, -1) == subject.moving_to assert -1 == subject.start_move assert -1 == subject.move_duration assert subject.rotate_to == 90 assert subject.start_rotation == 946684809.0 assert round(subject.rotate_duration) == 10 assert subject.intentions.get(MoveToIntention) # We are rotating, rest 1s with freeze_time("2000-01-01 00:00:18", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'rotate_relative': 90, 'rotate_absolute': 90, } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueRotationEvent) assert 9 == round(events[0].rotate_relative) assert 1 == round(events[0].duration) assert subject.position == (0, 1) assert int(subject.direction) == 81 assert subject.rotate_to == 90 assert subject.start_rotation == 946684818.0 assert round(subject.rotate_duration) == 1 assert subject.intentions.get(MoveToIntention) # We finish rotating and start to move to final tile with freeze_time("2000-01-01 00:00:19", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (1, 1), 'rotate_to_finished': 90, } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[1], SubjectStartTileMoveEvent) assert isinstance(events[0], SubjectFinishRotationEvent) assert (1, 1) == events[1].move_to assert 9.0 == events[1].duration assert subject.position == (0, 1) assert subject.moving_to == (1, 1) assert subject.move_duration == 9.0 assert subject.start_move == 946684819.0 assert subject.intentions.get(MoveToIntention) # Continue the move, rest 1s with freeze_time("2000-01-01 00:00:27", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (1, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueTileMoveEvent) assert (1, 1) == events[0].move_to assert 1.0 == events[0].duration assert subject.moving_to == (1, 1) assert subject.move_duration == 1.0 assert subject.start_move == 946684819.0 assert subject.intentions.get(MoveToIntention) # We arrived on final tile with freeze_time("2000-01-01 00:00:28", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'move_to_finished': (1, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectFinishMoveEvent) assert (1, 1) == events[0].move_to assert (1, 1) == subject.position assert (-1, -1) == subject.moving_to assert -1 == subject.start_move assert -1 == subject.move_duration with pytest.raises(KeyError): assert subject.intentions.get(MoveToIntention) def test_move_behaviour(config): simulation = XYZSimulation(config) simulation.physics.graph.add_edge('0.0', '0.1', {}) simulation.physics.graph.add_edge('0.1', '1.1', {}) subject = ManSubject( config, simulation, position=(0, 0), ) move = MoveToIntention( to=(1, 1), gui_action=UserAction.ORDER_MOVE, ) subject.intentions.set(move) move_behaviour = MoveBehaviour( config=config, simulation=simulation, subject=subject, ) # First begin move with freeze_time("2000-01-01 00:00:00", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'path': [ (0, 0), (0, 1), (1, 1), ], 'tile_move_to': (0, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectStartTileMoveEvent) assert (0, 1) == events[0].move_to assert 3.0 == events[0].duration assert subject.intentions.get(MoveToIntention) # Continue the move, rest 1s with freeze_time("2000-01-01 00:00:02", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (0, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueTileMoveEvent) assert (0, 1) == events[0].move_to assert 1.0 == events[0].duration assert subject.intentions.get(MoveToIntention) # Tile move finished, begin a new move with freeze_time("2000-01-01 00:00:03", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to_finished': (0, 1), 'tile_move_to': (1, 1), } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[0], SubjectFinishTileMoveEvent) assert isinstance(events[1], SubjectStartTileMoveEvent) assert (0, 1) == events[0].move_to assert (1, 1) == events[1].move_to assert 3 == events[1].duration assert (0, 1) == subject.position assert (1, 1) == subject.moving_to assert 946684803.0 == subject.start_move assert 3 == subject.move_duration assert subject.intentions.get(MoveToIntention) # We are moving, rest 1s with freeze_time("2000-01-01 00:00:05", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'tile_move_to': (1, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectContinueTileMoveEvent) assert (1, 1) == events[0].move_to assert 1.0 == events[0].duration assert (0, 1) == subject.position assert (1, 1) == subject.moving_to assert 946684805.0 == subject.start_move assert 1 == subject.move_duration assert subject.intentions.get(MoveToIntention) # We arrived on final tile with freeze_time("2000-01-01 00:00:06", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'move_to_finished': (1, 1), } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectFinishMoveEvent) assert (1, 1) == events[0].move_to assert (1, 1) == subject.position assert (-1, -1) == subject.moving_to assert -1 == subject.start_move assert -1 == subject.move_duration with pytest.raises(KeyError): assert subject.intentions.get(MoveToIntention) def test_move_and_rotate_behaviour__rotate_negatively(config): simulation = XYZSimulation(config) simulation.physics.graph.add_edge('0.0', '1.-1', {}) simulation.physics.graph.add_edge('1.-1', '2.-1', {}) subject = TankSubject( config, simulation, position=(0, 0), ) move = MoveToIntention( to=(2, -1), gui_action=UserAction.ORDER_MOVE, ) subject.intentions.set(move) move_behaviour = MoveWithRotationBehaviour( config=config, simulation=simulation, subject=subject, ) # First is a move with freeze_time("2000-01-01 00:00:00", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'path': [ (0, 0), (1, -1), (2, -1), ], 'rotate_absolute': 135.0, 'rotate_relative': 135.0, } == data events = move_behaviour.action(data) assert 1 == len(events) assert isinstance(events[0], SubjectStartRotationEvent) assert 135 == events[0].rotate_relative assert 135 == events[0].rotate_absolute assert 15 == round(events[0].duration) assert subject.intentions.get(MoveToIntention) with freeze_time("2000-01-01 00:00:15", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'rotate_to_finished': 135, 'tile_move_to': (1, -1), } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[1], SubjectStartTileMoveEvent) assert isinstance(events[0], SubjectFinishRotationEvent) assert (1, -1) == events[1].move_to assert 9.0 == events[1].duration assert 135 == events[0].rotation_absolute assert subject.intentions.get(MoveToIntention) with freeze_time("2000-01-01 00:00:24", tz_offset=0): data = move_behaviour.run({MoveToMechanism: move.get_data()}) assert { 'gui_action': UserAction.ORDER_MOVE, 'rotate_absolute': 90, 'rotate_relative': -45, 'tile_move_to_finished': (1, -1), } == data events = move_behaviour.action(data) assert 2 == len(events) assert isinstance(events[0], SubjectFinishTileMoveEvent) assert isinstance(events[1], SubjectStartRotationEvent) assert (1, -1) == events[0].move_to assert 90 == events[1].rotate_absolute assert -45 == events[1].rotate_relative assert 5 == round(events[1].duration) assert subject.intentions.get(MoveToIntention)