Esempio n. 1
0
    def __init__(self, renderer: GameRenderer, my_id, remote_id, remote_addr, ports):
        self._renderer = renderer

        self._game = DurakSerialized()  # геймплей

        self._my_id = int(my_id)
        self._remote_id = int(remote_id)
        self._remote_addr = remote_addr

        # проверка на адекватность ID
        assert self._my_id != 0 and self._remote_id != 0 and self._my_id != self._remote_id

        # кто ходит первый выбираем просто сравнивая ID (они же случайные)!
        me_first = self._my_id < self._remote_id
        # мой индекс 0 если я первый, и 1 иначе. у соперника наоборот
        self._my_index = 0 if me_first else 1

        # две сетевых примочки на разны портах
        network1 = Networking(port_no=ports[0])
        network2 = Networking(port_no=ports[1])

        # кто слушает какой порт выбираем также на базе сравнения ID как чисел
        self._receiver = network1 if me_first else network2
        self._receiver.bind("")

        self._sender = network2 if me_first else network1
Esempio n. 2
0
    def _new_game(self):
        # игрок с индексом 0 создает игру!
        self._game = DurakSerialized()

        # и отсылает ее сопернику
        self._send_game_state()
        self._renderer.render_game(self._game, self._my_index)
Esempio n. 3
0
 def _on_remote_message(self, data):
     action = data['action']
     if action == 'state':
         self.state = DurakSerialized(data['state'])  # обновить остояние
         self.on_state_updated(self.state)  # 'Пришел ход от соперника!'
     elif action == 'quit':
         self.on_opponent_quit()  # 'Соперник вышел!'
Esempio n. 4
0
 def _on_remote_message(self, data):
     action = data['action']
     if action == 'state':
         self._game = DurakSerialized(data['state'])  # обновить остояние
         print('Пришел ход от соперника!')
         self._renderer.render_game(self._game, self._my_index)
     elif action == 'quit':
         print('Соперник вышел!')
         exit(0)
Esempio n. 5
0
def test_ser1():
    g = DurakSerialized()

    g.attack(g.players[0].cards[0])

    jg = g.serialized()
    g2 = DurakSerialized(jg)

    assert g.attacker_index == g2.attacker_index
    assert g.winner == g2.winner
    assert g.field == g2.field

    assert all(c1 == c2 for c1, c2 in zip(g.deck, g2.deck))

    for p1, p2 in zip(g.players, g2.players):
        assert p1.index == p2.index
        assert p1.cards == p2.cards
Esempio n. 6
0
class DurakNetGame:
    def __init__(self, renderer: GameRenderer, my_id, remote_id, remote_addr, ports):
        self._renderer = renderer

        self._game = DurakSerialized()  # геймплей

        self._my_id = int(my_id)
        self._remote_id = int(remote_id)
        self._remote_addr = remote_addr

        # проверка на адекватность ID
        assert self._my_id != 0 and self._remote_id != 0 and self._my_id != self._remote_id

        # кто ходит первый выбираем просто сравнивая ID (они же случайные)!
        me_first = self._my_id < self._remote_id
        # мой индекс 0 если я первый, и 1 иначе. у соперника наоборот
        self._my_index = 0 if me_first else 1

        # две сетевых примочки на разны портах
        network1 = Networking(port_no=ports[0])
        network2 = Networking(port_no=ports[1])

        # кто слушает какой порт выбираем также на базе сравнения ID как чисел
        self._receiver = network1 if me_first else network2
        self._receiver.bind("")

        self._sender = network2 if me_first else network1

    def _send_game_state(self):
        self._sender.send_json({
            'action': 'state',
            'state': self._game.serialized()
        }, self._remote_addr)

    def _send_quit(self):
        self._sender.send_json({
            'action': 'quit'
        }, self._remote_addr)

    def _handle_finish(self, my_turn):
        g = self._game
        if g.field:
            if my_turn and g.any_unbeaten_cards:
                print('Не можете вынудить соперника взять карты!')
                return False
            elif not my_turn and not g.any_unbeaten_cards:
                print('Только атакующий может сказать "Бито!"')
                return False
            else:
                r = g.finish_turn()
                if r == g.GAME_OVER:
                    r_str = 'игра окончена!'
                elif r == g.TOOK_CARDS:
                    r_str = 'взяли карты.'
                else:
                    r_str = 'бито.'
                print(f'Ход завершен: {r_str}')
                return True
        else:
            print('Пока ход не сделал, чтобы его завершить!')
            return False

    def _handle_attack(self, parts):
        g = self._game
        index = int(parts[1]) - 1
        card = g.attacking_player.cards[index]
        if not g.attack(card):
            print('ОШИБКА! Вы не можете ходить этой картой!')
            return False
        else:
            return True

    def _handle_defence(self, parts):
        g = self._game
        index = int(parts[1]) - 1
        new_card = g.defending_player.cards[index]
        if g.field:
            variants = g.defend_variants(new_card)

            print(f'variants {variants} - {new_card}')

            if len(variants) == 1:
                def_index = variants[0]
            elif len(variants) >= 2:
                max_pos = len(g.field)
                def_index = int(input(f'Какую позицию отбить {new_card} (1-{max_pos})? ')) - 1
            else:
                print('Вам придется взять карты!')
                return False

            old_card = list(g.field.keys())[def_index]
            if not g.defend(old_card, new_card):
                print('ОШИБКА! Нельзя так отбиться!')
            else:
                return True
        else:
            print('Пока нечего отбивать!')
            return False

    def _new_game(self):
        # игрок с индексом 0 создает игру!
        self._game = DurakSerialized()

        # и отсылает ее сопернику
        self._send_game_state()
        self._renderer.render_game(self._game, self._my_index)

    def _on_remote_message(self, data):
        action = data['action']
        if action == 'state':
            self._game = DurakSerialized(data['state'])  # обновить остояние
            print('Пришел ход от соперника!')
            self._renderer.render_game(self._game, self._my_index)
        elif action == 'quit':
            print('Соперник вышел!')
            exit(0)

    def _game_loop(self):
        while True:
            q = input('Ваш ход (q = выход)? ')

            parts = q.lower().split(' ')
            if not parts:
                continue

            command = parts[0]

            good_move = False  # флаг, удачный ли был ход после ввода команды
            g = self._game

            # мой ли ход атаковать?
            is_my_turn = g.attacker_index == self._my_index

            try:
                if command == 'f':
                    good_move = self._handle_finish(is_my_turn)
                elif command == 'a' and is_my_turn:
                    good_move = self._handle_attack(parts)
                elif command == 'd' and not is_my_turn:
                    good_move = self._handle_defence(parts)
                elif command == 'q':
                    print('Вы вышли из игры!')
                    self._send_quit()
                    break
                else:
                    print('Неизвестная команда.')
            except IndexError:
                print('ОШИБКА! Неверный выбор карты')
            except ValueError:
                print('Введите число через пробел после команды')

            if good_move:
                # если ход удачный, пошлем копию состояния игры
                self._send_game_state()
                self._renderer.render_game(g, self._my_index)

                # проверка на окончание игры (если есть победитель, в g.winner - этог индекс)
                if g.winner is not None:
                    outcome = 'Вы победили!' if g.winner == self._my_index else 'Вы проиграли!'
                    print(f'Игра окончена! {outcome}')
                    break

    def start(self):
        print(f'Мой ID #{self._my_id}, мой индекс {self._my_index}')
        print(f'Удаленный адрес {self._remote_addr}')
        self._renderer.help()

        if self._my_index == 0:
            # игрок с индексом 0 создает игру!
            self._new_game()

        self._receiver.run_reader_thread(self._on_remote_message)
        self._game_loop()
Esempio n. 7
0
    def _new_game(self):
        # игрок с индексом 0 создает игру!
        self.state = DurakSerialized()

        # и отсылает ее сопернику через небольшой промежуток времени, чтобы тот успел начать слушать
        Timer(0.5, self._send_game_state).start()
Esempio n. 8
0
class DurakNetGame:
    def __init__(self, my_id, remote_id, remote_addr, ports):
        self.state = DurakSerialized()  # геймплей

        self._my_id = int(my_id)
        self._remote_id = int(remote_id)
        self._remote_addr = remote_addr

        # проверка на адекватность ID
        assert self._my_id != 0 and self._remote_id != 0 and self._my_id != self._remote_id

        # кто ходит первый выбираем просто сравнивая ID (они же случайные)!
        me_first = self._my_id < self._remote_id
        # мой индекс 0 если я первый, и 1 иначе. у соперника наоборот
        self._my_index = 0 if me_first else 1
        self._opp_index = 1 if me_first else 0

        # две сетевых примочки на разны портах
        network1 = Networking(port_no=ports[0])
        network2 = Networking(port_no=ports[1])

        # кто слушает какой порт выбираем также на базе сравнения ID как чисел
        self._receiver = network1 if me_first else network2
        self._receiver.bind("")

        self._sender = network2 if me_first else network1

        self.on_state_updated = lambda _:...
        self.on_opponent_quit = lambda:...

    def _send_game_state(self):
        self.on_state_updated(self.state)
        self._sender.send_json(
            {
                'action': 'state',
                'state': self.state.serialized()
            }, self._remote_addr)

    def _send_quit(self):
        self._sender.send_json({'action': 'quit'}, self._remote_addr)

    def finish_turn(self) -> TurnFinishResult:
        g = self.state
        if g.field:
            if self.is_my_turn and g.any_unbeaten_cards:
                return TurnFinishResult.CANT_FORCE_TO_TAKE  # print('Не можете вынудить соперника взять карты!')
            else:
                result = g.finish_turn()
                self._send_game_state()
                return result
        else:
            return TurnFinishResult.EMPTY

    def attack(self, card):
        assert self.is_my_turn
        result = self.state.attack(card)
        if result:
            self._send_game_state()
        return result

    def defend(self, my_card, field_card):
        assert not self.is_my_turn
        g = self.state
        if g.field:
            # если передали номер карты на поле, то преобразуем его в саму карту
            if isinstance(field_card, int):
                field_card = list(g.field.keys())[field_card]

            assert my_card in self.state.defending_player.cards
            assert field_card in self.state.field.keys()
            result = g.defend(field_card, my_card)
            if result:
                self._send_game_state()
            return result
        else:
            return False  # 'Пока нечего отбивать!'

    def _new_game(self):
        # игрок с индексом 0 создает игру!
        self.state = DurakSerialized()

        # и отсылает ее сопернику через небольшой промежуток времени, чтобы тот успел начать слушать
        Timer(0.5, self._send_game_state).start()

    def _on_remote_message(self, data):
        action = data['action']
        if action == 'state':
            self.state = DurakSerialized(data['state'])  # обновить остояние
            self.on_state_updated(self.state)  # 'Пришел ход от соперника!'
        elif action == 'quit':
            self.on_opponent_quit()  # 'Соперник вышел!'

    def start(self):
        # поток слушающий сообщений от другого игрока
        self._receiver.run_reader_thread(self._on_remote_message)

        if self._my_index == 0:
            # игрок с индексом 0 создает игру!
            self._new_game()

    def stop(self):
        self._send_quit()
        self._receiver.read_running = False

    @property
    def my_cards(self):
        return self.state.players[self._my_index].cards

    @property
    def opp_cards(self):
        return self.state.players[self._opp_index].cards

    @property
    def is_my_turn(self):
        return self.state.attacker_index == self._my_index

    def is_me(self, index):
        return index == self._my_index

    ME = 'me'
    OPPONENT = 'opponent'

    @property
    def winner(self):
        if self.state.winner is not None:
            return self.ME if self._my_index == self.state.winner else self.OPPONENT