diff --git a/zulip_bots/zulip_bots/bots/merels/libraries/game.py b/zulip_bots/zulip_bots/bots/merels/libraries/game.py index ccd6f43..3e7d43d 100644 --- a/zulip_bots/zulip_bots/bots/merels/libraries/game.py +++ b/zulip_bots/zulip_bots/bots/merels/libraries/game.py @@ -45,7 +45,6 @@ def unknown_command(): "put (v,h), take (v,h), move (v,h) -> (v,h)" raise BadMoveException(message) -# def beat(message, topic_name, merels_storage): def beat(message, topic_name, merels_storage): """ This gets triggered every time a user send a message in any topic :param message: User's message @@ -133,6 +132,7 @@ def beat(message, topic_name, merels_storage): mechanics.update_hill_uid(topic_name, merels_storage) responses += mechanics.display_game(topic_name, merels_storage) + "\n" + responses += check_win(topic_name, merels_storage) if no_moves != "": same_player_move = no_moves diff --git a/zulip_bots/zulip_bots/bots/merels/merels.py b/zulip_bots/zulip_bots/bots/merels/merels.py index 4928aa0..6bea75e 100644 --- a/zulip_bots/zulip_bots/bots/merels/merels.py +++ b/zulip_bots/zulip_bots/bots/merels/merels.py @@ -5,7 +5,7 @@ from zulip_bots.bots.merels.libraries import ( database, game_data ) -from zulip_bots.game_handler import GameAdapter, SamePlayerMove +from zulip_bots.game_handler import GameAdapter, SamePlayerMove, GameInstance class Storage(object): data = {} @@ -32,7 +32,7 @@ class MerelsModel(object): return 'current turn' return '' - def contains_winning_move(self, board: Any) -> bool: + def contains_winning_move(self, board: Any) ->bool: merels = database.MerelsStorage(self.topic, self.storage) data = game_data.GameData(merels.get_game_data(self.topic)) @@ -64,7 +64,7 @@ class MerelsMessageHandler(object): return self.tokens[turn] def alert_move_message(self, original_player: str, move_info: str) -> str: - return original_player + " :" + return original_player + " :" + move_info def game_start_message(self) -> str: return game.getHelp() @@ -88,6 +88,7 @@ class MerelsHandler(GameAdapter): move_help_message = "" move_regex = '.*' model = MerelsModel + rules = game.getInfo() gameMessageHandler = MerelsMessageHandler super(MerelsHandler, self).__init__( game_name, @@ -96,6 +97,9 @@ class MerelsHandler(GameAdapter): move_regex, model, gameMessageHandler, + rules, + max_players = 2, + min_players = 2, supports_computer=False ) diff --git a/zulip_bots/zulip_bots/bots/merels/test/test_database.py b/zulip_bots/zulip_bots/bots/merels/test/test_database.py index ea092b1..61fd6ef 100644 --- a/zulip_bots/zulip_bots/bots/merels/test/test_database.py +++ b/zulip_bots/zulip_bots/bots/merels/test/test_database.py @@ -3,64 +3,36 @@ import unittest from libraries import database from libraries import game_data from zulip_bots.simple_lib import SimpleStorage +from zulip_bots.test_lib import BotTestCase, DefaultTests +from zulip_bots.game_handler import GameInstance +from merels import MerelsHandler +class DatabaseTest(BotTestCase, DefaultTests): + bot_name = 'merels' -class DatabaseTest(unittest.TestCase): def setUp(self): self.storage = SimpleStorage() - self.merels = database.MerelsStorage(self.storage) - - def test_create_duplicate_game(self): - self.merels.create_new_game("test") - - self.assertEqual(self.merels.create_new_game("test"), False) + self.merels = database.MerelsStorage("", self.storage) def test_obtain_gamedata(self): - self.merels.create_new_game("test") - - res = self.merels.get_game_data("test") + self.merels.update_game("topic1", "X", 0, 0, 'NNNNNNNNNNNNNNNNNNNNNNNN', "", 0) + res = self.merels.get_game_data("topic1") self.assertTupleEqual(res, ( - 'test', 'X', 0, 0, 'NNNNNNNNNNNNNNNNNNNNNNNN', "", 0)) + 'topic1', 'X', 0, 0, 'NNNNNNNNNNNNNNNNNNNNNNNN', "", 0)) self.assertEqual(len(res), 7) def test_obtain_nonexisting_gamedata(self): - res = self.merels.get_game_data("test") - + res = self.merels.get_game_data("NoGame") self.assertEqual(res, None) def test_game_session(self): - self.merels.create_new_game("test") - - self.merels.update_game("test", "O", 5, 4, "XXXXOOOOONNNNNNNNNNNNNNN", - "", - 0) - - self.merels.create_new_game("test2") - - self.assertTrue(self.storage.contains("test"), self.storage.contains( - "test2")) - - self.assertEqual( - game_data.GameData(self.merels.get_game_data("test")).board, - "XXXXOOOOONNNNNNNNNNNNNNN") - - def test_no_duplicates(self): - self.merels.create_new_game("test") - self.merels.update_game("test", "X", 0, 0, "XXXNNNOOOXXXNNNOOOXXXNNN", - "", 1) - self.merels.create_new_game("test") - self.merels.create_new_game("test") - self.merels.create_new_game("test") - self.merels.create_new_game("test") - self.merels.create_new_game("test") - self.merels.create_new_game("test") - self.merels.create_new_game("test") - - self.assertEqual(game_data.GameData(self.merels.get_game_data( - "test")).board, "XXXNNNOOOXXXNNNOOOXXXNNN") + self.merels.update_game("topic1", "X", 0, 0, 'NNNNNNNNNNNNNNNNNNNNNNNN', "", 0) + self.merels.update_game("topic2", "O", 5, 4, 'XXXXOOOOONNNNNNNNNNNNNNN', "", 0) + self.assertTrue(self.storage.contains("topic1"), self.storage.contains("topic2")) + topic2Board = game_data.GameData(self.merels.get_game_data("topic2")) + self.assertEqual(topic2Board.board, "XXXXOOOOONNNNNNNNNNNNNNN") def test_remove_game(self): - self.merels.create_new_game("test") - self.merels.remove_game("test") - - self.assertTrue(self.merels.create_new_game("test")) + self.merels.update_game("topic1", "X", 0, 0, 'NNNNNNNNNNNNNNNNNNNNNNNN', "", 0) + self.merels.remove_game("topic1") + self.assertEqual(self.merels.get_game_data("topic1"), None) diff --git a/zulip_bots/zulip_bots/bots/merels/test/test_game.py b/zulip_bots/zulip_bots/bots/merels/test/test_game.py index de4dcf7..35e2395 100644 --- a/zulip_bots/zulip_bots/bots/merels/test/test_game.py +++ b/zulip_bots/zulip_bots/bots/merels/test/test_game.py @@ -2,116 +2,97 @@ import unittest from libraries import game from libraries import database - from zulip_bots.simple_lib import SimpleStorage - +from zulip_bots.game_handler import BadMoveException class GameTest(unittest.TestCase): def setUp(self): self.storage = SimpleStorage() self.topic_name = "test" - def test_reset_game_output(self): - game.beat("create", self.topic_name, self.storage) - self.assertTrue("reset" in game.beat("reset", self.topic_name, - self.storage)) - - def test_reset_no_game_output(self): - self.assertTrue("No game created yet" in game.beat("reset", - self.topic_name, - self.storage)) - def test_command_when_no_game_created_output(self): - self.assertTrue("cannot do any of the game commands" in game.beat( - "put 0,0", self.topic_name, self.storage)) + with self.assertRaises(TypeError) as warning: + resp, move = game.beat("put 0,0", self.topic_name, self.storage) + self.assertTrue("NoneType" in str(warning)) def test_put_piece_output(self): - game.beat("create", self.topic_name, self.storage) - self.assertTrue("Put a man" in game.beat("put 0,0", self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + # All new games start with updating the game as follows + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + resp, move = game.beat("put 0,0", self.topic_name, self.storage) + self.assertTrue("Put a man" in resp) def test_not_possible_put_piece_output(self): - game.beat("create", self.topic_name, self.storage) - self.assertTrue("Failed" in game.beat("put 0,1", self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + with self.assertRaises(BadMoveException) as warning: + game.beat("put 0,1", self.topic_name, self.storage) + self.assertTrue("Failed" in str(warning)) def test_take_before_put_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 0, 0, - "XXXNNNOOOXXXNNNOOOXXXNNN", "", 1) - self.assertTrue("Take is required", game.beat("put 1,1", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 0, 0, "XXXNNNOOOXXXNNNOOOXXXNNN", "", 1) + with self.assertRaises(BadMoveException) as warning: + game.beat("put 1,1", self.topic_name, self.storage) + self.assertTrue("Take is required" in str(warning)) def test_move_piece_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 0, 0, - "XXXNNNOOOXXXNNNOOOXXXOOO", "", 0) - self.assertTrue("Moved a man" in game.beat("move 0,3 1,3", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 0, 0, "XXXNNNOOOXXXNNNOOOXXXOOO", "", 0) + resp, _ = game.beat("move 0,3 1,3", self.topic_name, self.storage) + self.assertTrue("Moved a man" in resp) def test_not_possible_move_piece_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 0, 0, - "XXXNNNOOOXXXNNNOOOXXXOOO", "", 0) - self.assertTrue("Failed" in game.beat("move 0,3 1,2", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 0, 0, "XXXNNNOOOXXXNNNOOOXXXOOO", "", 0) + with self.assertRaises(BadMoveException) as warning: + game.beat("move 0,3 1,2", self.topic_name, self.storage) + self.assertTrue("Failed" in str(warning)) def test_cannot_make_any_move_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 3, 4, - "OOXOXNOXNNOXNNNNNNXNNXNN", "", 0) - self.assertTrue("Switching" in game.beat("move 6,0 3,0", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 3, 4, "OOXOXNOXNNOXNNNNNNXNNXNN", "", 0) + _, move = game.beat("move 6,0 3,0", self.topic_name, self.storage) + self.assertTrue("Switching" in move) def test_take_before_move_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 6, 6, - "XXXNNNOOONNNNNNNNNNNNNNN", "", 1) - self.assertTrue("Take is required", game.beat("move 0,1 1,3", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 6, 6, "XXXNNNOOONNNNNNNNNNNNNNN", "", 1) + with self.assertRaises(BadMoveException) as warning: + game.beat("move 0,1 1,3", self.topic_name, self.storage) + self.assertTrue("Take is required" in str(warning)) def test_unknown_command(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 6, 6, - "XXXNNNOOONNNNNNNNNNNNNNN", "", 1) - self.assertTrue("Unknown command", game.beat("magic 2,2", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 6, 6, "XXXNNNOOONNNNNNNNNNNNNNN", "", 1) + with self.assertRaises(BadMoveException) as warning: + game.beat("magic 2,2", self.topic_name, self.storage) + self.assertTrue("Unknown command" in str(warning)) def test_take_piece_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 0, 0, - "XXXNNNOOOXXXNNNOOOXXXOOO", "", 1) - self.assertTrue("Taken a man" in game.beat("take 2,2", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 0, 0, "XXXNNNOOOXXXNNNOOOXXXOOO", "", 1) + resp, move = game.beat("take 2,2", self.topic_name, self.storage) + self.assertTrue("Taken a man" in resp) def test_not_possible_take_piece_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 6, 6, - "XXXNNNOOOXXXNNNOOOXXXOOO", "", 0) - self.assertTrue("Taking is not possible" in game.beat("take 2,2", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 6, 6, "XXXNNNOOOXXXNNNOOOXXXOOO", "", 0) + with self.assertRaises(BadMoveException) as warning: + game.beat("take 2,2", self.topic_name, self.storage) + self.assertTrue("Taking is not possible" in str(warning)) def test_win_output(self): - merels = database.MerelsStorage(self.storage) - game.beat("create", self.topic_name, self.storage) - merels.update_game(self.topic_name, "X", 6, 6, - "XXXNNNOOONNNNNNNNNNNNNNN", "", 1) - self.assertTrue("wins the game!", game.beat("take 2,2", - self.topic_name, - self.storage)) + merels = database.MerelsStorage(self.topic_name, self.storage) + merels.update_game(self.topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) + merels.update_game(self.topic_name, "X", 6, 6, "XXXNNNOOONNNNNNNNNNNNNNN", "", 1) + resp, _ = game.beat("take 2,2", self.topic_name, self.storage) + self.assertTrue("wins the game!" in resp) diff --git a/zulip_bots/zulip_bots/bots/merels/test/test_mechanics.py b/zulip_bots/zulip_bots/bots/merels/test/test_mechanics.py index 13daf3f..6073b3b 100644 --- a/zulip_bots/zulip_bots/bots/merels/test/test_mechanics.py +++ b/zulip_bots/zulip_bots/bots/merels/test/test_mechanics.py @@ -167,8 +167,9 @@ class HillsTest(unittest.TestCase): class PhaseTest(unittest.TestCase): def test_new_game_phase(self): storage = SimpleStorage() - merels = database.MerelsStorage(storage) - merels.create_new_game("test") + topic_name = "test" + merels = database.MerelsStorage(topic_name, storage) + merels.update_game(topic_name, "X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0) res = game_data.GameData(merels.get_game_data("test")) self.assertEqual(res.get_phase(), 1) diff --git a/zulip_bots/zulip_bots/bots/merels/test_merels.py b/zulip_bots/zulip_bots/bots/merels/test_merels.py index 7681c3b..9f05080 100644 --- a/zulip_bots/zulip_bots/bots/merels/test_merels.py +++ b/zulip_bots/zulip_bots/bots/merels/test_merels.py @@ -1,24 +1,81 @@ -""" -Most of the testing for the actual game are done in test_database - -This is only to really verify the output of the chat -""" - from zulip_bots.test_lib import BotTestCase, DefaultTests +from zulip_bots.game_handler import GameInstance +from libraries.constants import EMPTY_BOARD + +from typing import List, Tuple, Any class TestMerelsBot(BotTestCase, DefaultTests): - bot_name = "merels" + bot_name = 'merels' def test_no_command(self): - message = dict( - content='magic', - type='stream', - sender_email="boo@email.com", - sender_full_name="boo" - ) - + message = dict(content='magic', type='stream', sender_email="boo@email.com", sender_full_name="boo") res = self.get_response(message) + self.assertEqual(res['content'], 'You are not in a game at the moment.'' Type `help` for help.') - self.assertEqual(res['content'], - 'You are not in a game at the moment.' - ' Type `help` for help.') + # FIXME: Add tests for computer moves + # FIXME: Add test lib for game_handler + + # Test for unchanging aspects within the game + # Player Color, Start Message, Moving Message + def test_static_responses(self) -> None: + model, message_handler = self._get_game_handlers() + self.assertNotEqual(message_handler.get_player_color(0), None) + self.assertNotEqual(message_handler.game_start_message(), None) + self.assertEqual(message_handler.alert_move_message('foo', 'moved right'), 'foo :moved right') + + # Test to see if the attributes exist + def test_has_attributes(self) -> None: + model, message_handler = self._get_game_handlers() + # Attributes from the Merels Handler + self.assertTrue(hasattr(message_handler, 'parse_board') is not None) + self.assertTrue(hasattr(message_handler, 'get_player_color') is not None) + self.assertTrue(hasattr(message_handler, 'alert_move_message') is not None) + self.assertTrue(hasattr(message_handler, 'game_start_message') is not None) + self.assertTrue(hasattr(message_handler, 'alert_move_message') is not None) + # Attributes from the Merels Model + self.assertTrue(hasattr(model, 'determine_game_over') is not None) + self.assertTrue(hasattr(model, 'contains_winning_move') is not None) + self.assertTrue(hasattr(model, 'make_move') is not None) + + def test_parse_board(self) -> None: + board = EMPTY_BOARD + expectResponse = EMPTY_BOARD + self._test_parse_board(board, expectResponse) + + def test_add_user_to_cache(self): + self.add_user_to_cache("Name") + + def test_setup_game(self): + self.setup_game() + + def add_user_to_cache(self, name: str, bot: Any=None) -> Any: + if bot is None: + bot, bot_handler = self._get_handlers() + message = { + 'sender_email': '{}@example.com'.format(name), + 'sender_full_name': '{}'.format(name)} + bot.add_user_to_cache(message) + return bot + + def setup_game(self) -> None: + bot = self.add_user_to_cache('foo') + self.add_user_to_cache('baz', bot) + instance = GameInstance(bot, False, 'test game', 'abc123', [ + 'foo@example.com', 'baz@example.com'], 'test') + bot.instances.update({'abc123': instance}) + instance.start() + return bot + + def _get_game_handlers(self) -> Tuple[Any, Any]: + bot, bot_handler = self._get_handlers() + return bot.model, bot.gameMessageHandler + + def _test_parse_board(self, board: str, expected_response: str) -> None: + model, message_handler = self._get_game_handlers() + response = message_handler.parse_board(board) + self.assertEqual(response, expected_response) + + def _test_determine_game_over(self, board: List[List[int]], players: List[str], expected_response: str) -> None: + model, message_handler = self._get_game_handlers() + response = model.determine_game_over(players) + self.assertEqual(response, expected_response)