mirror of
https://github.com/solero/houdini.git
synced 2024-11-13 22:28:21 +00:00
Card Jitsu Fire handlers
This commit is contained in:
parent
a44d505bb8
commit
1ac22ca1d4
@ -1,15 +1,651 @@
|
|||||||
from houdini import IWaddle
|
import asyncio
|
||||||
|
import itertools
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
from collections import Counter
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import List, Union
|
||||||
|
|
||||||
|
from houdini import IWaddle, handlers
|
||||||
|
from houdini.data.ninja import Card
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.handlers.games.ninja.card import ninja_stamps_earned
|
||||||
|
from houdini.penguin import Penguin
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FireNinja:
|
||||||
|
penguin: Penguin
|
||||||
|
seat_id: int
|
||||||
|
deck: List[Card] = field(default_factory=list)
|
||||||
|
chosen: Union[int, None] = None
|
||||||
|
energy: int = 6
|
||||||
|
energy_won: int = 0
|
||||||
|
state: int = 0
|
||||||
|
ready: bool = False
|
||||||
|
|
||||||
|
|
||||||
class CardJitsuFireLogic(IWaddle):
|
class CardJitsuFireLogic(IWaddle):
|
||||||
|
|
||||||
room_id = 997
|
room_id = 997
|
||||||
|
|
||||||
|
Board = ['b', 's', 'w', 'f', 'c',
|
||||||
|
's', 'f', 'w', 'b', 's',
|
||||||
|
'w', 'f', 'c', 'w', 's', 'f']
|
||||||
|
RuleSet = {'f': 's', 'w': 'f', 's': 'w'}
|
||||||
|
DefaultTiles = [0, 8, 4, 12]
|
||||||
|
AutoBattleTimeout = 22
|
||||||
|
|
||||||
|
ItemAwards = [6025, 4120, 2013, 1086, 3032]
|
||||||
|
StampAwards = {2: 256, 4: 262}
|
||||||
|
|
||||||
|
RankSpeed = 1
|
||||||
|
|
||||||
def __init__(self, waddle):
|
def __init__(self, waddle):
|
||||||
super().__init__(waddle)
|
super().__init__(waddle)
|
||||||
|
|
||||||
|
self.ninjas = [FireNinja(
|
||||||
|
penguin=p,
|
||||||
|
seat_id=seat_id
|
||||||
|
) for seat_id, p in enumerate(waddle.penguins)]
|
||||||
|
self.battle_ninjas = []
|
||||||
|
|
||||||
|
self.podium = [0]*self.seats
|
||||||
|
self.finish_position = self.seats
|
||||||
|
|
||||||
|
self.tile_ids = CardJitsuFireLogic.DefaultTiles[:self.seats].copy()
|
||||||
|
|
||||||
|
self.current_player = None
|
||||||
|
self.ninja_circle = itertools.cycle(self.ninjas)
|
||||||
|
|
||||||
|
self.spin_amount = 0
|
||||||
|
self.move_clockwise = 0
|
||||||
|
self.move_anticlockwise = 0
|
||||||
|
self.tab_id = None
|
||||||
|
|
||||||
|
self.current_battle_state = 0
|
||||||
|
self.current_battle_element = 0
|
||||||
|
self.current_battle_type = 'bt'
|
||||||
|
|
||||||
|
self.choose_card_timeout = None
|
||||||
|
self.choose_board_timeout = None
|
||||||
|
|
||||||
|
self.next()
|
||||||
|
self.deal()
|
||||||
|
self.spin()
|
||||||
|
self.set_choose_board_timeout()
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
self.current_player = next(self.ninja_circle)
|
||||||
|
while self.current_player not in self.ninjas:
|
||||||
|
self.current_player = next(self.ninja_circle)
|
||||||
|
|
||||||
|
def deal(self):
|
||||||
|
for ninja in self.ninjas:
|
||||||
|
penguin = ninja.penguin
|
||||||
|
deck = Counter(penguin.server.cards[card.card_id]
|
||||||
|
for card in penguin.cards.values()
|
||||||
|
for _ in range(card.quantity + card.member_quantity))
|
||||||
|
dealt = Counter(ninja.deck)
|
||||||
|
can_deal = list((deck - dealt).elements())
|
||||||
|
|
||||||
|
if ninja.chosen is None:
|
||||||
|
ninja.deck = random.sample(can_deal, 5)
|
||||||
|
else:
|
||||||
|
ninja.deck[ninja.chosen] = random.choice(can_deal)
|
||||||
|
|
||||||
|
def spin(self):
|
||||||
|
self.tab_id = None
|
||||||
|
self.spin_amount = random.randrange(1, 7)
|
||||||
|
|
||||||
|
player_position = self.tile_ids[self.current_player.seat_id]
|
||||||
|
self.move_clockwise = (player_position + self.spin_amount) % 16
|
||||||
|
self.move_anticlockwise = (player_position - self.spin_amount) % 16
|
||||||
|
|
||||||
|
def set_choose_board_timeout(self):
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
self.choose_board_timeout = loop.call_later(
|
||||||
|
CardJitsuFireLogic.AutoBattleTimeout,
|
||||||
|
lambda: asyncio.ensure_future(self.auto_choose_board())
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_choose_card_timeout(self):
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
self.choose_card_timeout = loop.call_later(
|
||||||
|
CardJitsuFireLogic.AutoBattleTimeout,
|
||||||
|
lambda: asyncio.ensure_future(self.auto_choose_card())
|
||||||
|
)
|
||||||
|
|
||||||
|
async def auto_choose_board(self):
|
||||||
|
self.tab_id = 1
|
||||||
|
await self.current_player.penguin.send_xt('zm', 'tb')
|
||||||
|
move = self.move_anticlockwise if random.randint(0, 1) else self.move_clockwise
|
||||||
|
await self.choose_board(move, is_auto_play=True)
|
||||||
|
|
||||||
|
async def auto_choose_card(self):
|
||||||
|
for ninja in self.battle_ninjas:
|
||||||
|
if ninja.chosen is None:
|
||||||
|
playable_cards = self.get_playable_cards(ninja)
|
||||||
|
await self.choose_card(ninja, random.choice(playable_cards))
|
||||||
|
|
||||||
|
def get_ninja_by_seat_id(self, seat_id):
|
||||||
|
return next(ninja for ninja in self.ninjas if ninja.seat_id == seat_id)
|
||||||
|
|
||||||
|
def get_ninja_by_penguin(self, penguin):
|
||||||
|
return next(ninja for ninja in self.ninjas if ninja.penguin == penguin)
|
||||||
|
|
||||||
|
def get_ninjas_by_tile_id(self, tile_id):
|
||||||
|
return [ninja for ninja in self.ninjas if self.tile_ids[ninja.seat_id] == tile_id]
|
||||||
|
|
||||||
|
def is_card_playable(self, ninja, card_id):
|
||||||
|
if self.current_battle_type == 'bt':
|
||||||
|
if ninja.deck[card_id].element == self.current_battle_element:
|
||||||
|
return True
|
||||||
|
return all(card.element != self.current_battle_element for card in ninja.deck)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_playable_cards(self, ninja):
|
||||||
|
return [card_id for card_id in range(len(ninja.deck)) if self.is_card_playable(ninja, card_id)]
|
||||||
|
|
||||||
|
def resolve_battle(self):
|
||||||
|
if self.current_battle_type == 'be':
|
||||||
|
first_ninja, second_ninja = self.battle_ninjas[:2]
|
||||||
|
first_card = first_ninja.deck[first_ninja.chosen]
|
||||||
|
second_card = second_ninja.deck[second_ninja.chosen]
|
||||||
|
|
||||||
|
battle_result = CardJitsuFireLogic.get_battle_result(first_card, second_card)
|
||||||
|
|
||||||
|
if battle_result == 0:
|
||||||
|
first_ninja.state, second_ninja.state = (4, 1)
|
||||||
|
first_ninja.energy += 1
|
||||||
|
second_ninja.energy -= 1
|
||||||
|
first_ninja.energy_won += 1
|
||||||
|
elif battle_result == 1:
|
||||||
|
first_ninja.state, second_ninja.state = (1, 4)
|
||||||
|
first_ninja.energy -= 1
|
||||||
|
second_ninja.energy += 1
|
||||||
|
second_ninja.energy_won += 1
|
||||||
|
else:
|
||||||
|
first_ninja.state, second_ninja.state = (2, 2)
|
||||||
|
|
||||||
|
self.current_battle_element = first_card.element if battle_result == 0 else second_card.element
|
||||||
|
elif self.current_battle_type == 'bt':
|
||||||
|
battle_card_values = [n.deck[n.chosen].value
|
||||||
|
if n.deck[n.chosen].element == self.current_battle_element
|
||||||
|
else 0 for n in self.battle_ninjas]
|
||||||
|
highest_battle_card = max(battle_card_values)
|
||||||
|
is_battle_tie = battle_card_values.count(highest_battle_card) >= 2
|
||||||
|
for ninja in self.battle_ninjas:
|
||||||
|
card = ninja.deck[ninja.chosen]
|
||||||
|
if card.element != self.current_battle_element:
|
||||||
|
ninja.state = 1
|
||||||
|
ninja.energy -= 1
|
||||||
|
elif is_battle_tie and card.value == highest_battle_card:
|
||||||
|
ninja.state = 2
|
||||||
|
elif card.value == highest_battle_card:
|
||||||
|
ninja.state = 3
|
||||||
|
else:
|
||||||
|
ninja.state = 1
|
||||||
|
ninja.energy -= 1
|
||||||
|
|
||||||
|
async def click_spinner(self, tab_id):
|
||||||
|
if self.current_battle_state == 0 and self.tab_id is None and 0 <= tab_id <= 6:
|
||||||
|
self.tab_id = tab_id
|
||||||
|
await self.send_xt('zm', 'is', self.current_player.seat_id, tab_id)
|
||||||
|
|
||||||
|
async def ready_ninja(self, ninja):
|
||||||
|
if self.current_battle_state == 0:
|
||||||
|
ninja.ready = True
|
||||||
|
|
||||||
|
if all(n.ready for n in self.ninjas):
|
||||||
|
self.next()
|
||||||
|
self.spin()
|
||||||
|
self.deal()
|
||||||
|
|
||||||
|
for n in self.ninjas:
|
||||||
|
n.chosen = None
|
||||||
|
n.ready = False
|
||||||
|
|
||||||
|
deck = ','.join(str(card.id) for card in n.deck)
|
||||||
|
spin = f'{self.spin_amount},{self.move_clockwise},{self.move_anticlockwise}'
|
||||||
|
|
||||||
|
await n.penguin.send_xt('zm', 'nt', self.current_player.seat_id, spin, deck)
|
||||||
|
|
||||||
|
self.set_choose_board_timeout()
|
||||||
|
|
||||||
|
async def choose_board(self, tile_id, is_auto_play=False):
|
||||||
|
if self.current_battle_state == 0 and tile_id == self.move_clockwise or tile_id == self.move_anticlockwise:
|
||||||
|
if not is_auto_play or self.current_battle_state == 0:
|
||||||
|
self.tile_ids[self.current_player.seat_id] = tile_id
|
||||||
|
tile_ids = ','.join(map(str, self.tile_ids))
|
||||||
|
|
||||||
|
element = CardJitsuFireLogic.Board[tile_id]
|
||||||
|
|
||||||
|
await self.send_xt('zm', 'ub', self.current_player.seat_id, tile_ids, self.tab_id)
|
||||||
|
|
||||||
|
self.current_battle_type = 'bt'
|
||||||
|
self.battle_ninjas = self.ninjas
|
||||||
|
else:
|
||||||
|
tile_id = self.tile_ids[self.current_player.seat_id]
|
||||||
|
element = CardJitsuFireLogic.Board[tile_id]
|
||||||
|
|
||||||
|
ninjas_on_tile = self.get_ninjas_by_tile_id(tile_id)
|
||||||
|
|
||||||
|
if len(ninjas_on_tile) > 1:
|
||||||
|
self.current_battle_state = 2
|
||||||
|
self.current_battle_element = element
|
||||||
|
|
||||||
|
if is_auto_play:
|
||||||
|
ninjas_on_tile.remove(self.current_player)
|
||||||
|
opponent = random.choice(ninjas_on_tile)
|
||||||
|
await self.choose_opponent(opponent.seat_id)
|
||||||
|
else:
|
||||||
|
if len(ninjas_on_tile) > 2:
|
||||||
|
battle_seat_ids = ','.join(str(ninja.seat_id) for ninja in ninjas_on_tile)
|
||||||
|
await self.send_xt('zm', 'co', 0, battle_seat_ids)
|
||||||
|
else:
|
||||||
|
opponent = next(n for n in ninjas_on_tile if n != self.current_player)
|
||||||
|
await self.choose_opponent(opponent.seat_id)
|
||||||
|
elif element in CardJitsuFireLogic.Board[1:4]:
|
||||||
|
battle_seat_ids = ','.join(str(ninja.seat_id) for ninja in self.ninjas)
|
||||||
|
self.current_battle_element = element
|
||||||
|
self.current_battle_state = 3
|
||||||
|
|
||||||
|
await self.send_xt('zm', 'sb', self.current_battle_type, battle_seat_ids, element)
|
||||||
|
|
||||||
|
self.choose_board_timeout.cancel()
|
||||||
|
self.set_choose_card_timeout()
|
||||||
|
elif element == 'c':
|
||||||
|
if is_auto_play:
|
||||||
|
battle_seat_ids = ','.join(str(ninja.seat_id) for ninja in self.ninjas)
|
||||||
|
self.current_battle_element = random.choice(CardJitsuFireLogic.Board[1:4])
|
||||||
|
self.current_battle_state = 3
|
||||||
|
|
||||||
|
await self.send_xt('zm', 'sb', self.current_battle_type, battle_seat_ids,
|
||||||
|
self.current_battle_element)
|
||||||
|
|
||||||
|
self.choose_board_timeout.cancel()
|
||||||
|
self.set_choose_card_timeout()
|
||||||
|
else:
|
||||||
|
self.current_battle_state = 1
|
||||||
|
await self.send_xt('zm', 'ct')
|
||||||
|
elif element == 'b':
|
||||||
|
self.current_battle_element = element
|
||||||
|
self.current_battle_state = 2
|
||||||
|
|
||||||
|
if is_auto_play:
|
||||||
|
opponent = next(n for n in self.ninjas if n != self.current_player)
|
||||||
|
await self.choose_opponent(opponent.seat_id)
|
||||||
|
else:
|
||||||
|
if len(self.ninjas) > 2:
|
||||||
|
battle_seat_ids = ','.join(str(ninja.seat_id) for ninja in self.ninjas)
|
||||||
|
|
||||||
|
await self.send_xt('zm', 'co', 0, battle_seat_ids)
|
||||||
|
else:
|
||||||
|
opponent = next(n for n in self.ninjas if n != self.current_player)
|
||||||
|
await self.choose_opponent(opponent.seat_id)
|
||||||
|
|
||||||
|
async def choose_card(self, ninja, card_id):
|
||||||
|
if ninja.chosen is None and self.is_card_playable(ninja, card_id):
|
||||||
|
ninja.chosen = card_id
|
||||||
|
|
||||||
|
await self.send_xt('zm', 'ic', ninja.seat_id, f=lambda p: p != ninja.penguin)
|
||||||
|
|
||||||
|
if all(n.chosen is not None for n in self.battle_ninjas):
|
||||||
|
self.choose_card_timeout.cancel()
|
||||||
|
self.resolve_battle()
|
||||||
|
|
||||||
|
for n in self.ninjas:
|
||||||
|
if n.energy == 0:
|
||||||
|
self.podium[n.seat_id] = self.finish_position
|
||||||
|
self.finish_position -= 1
|
||||||
|
|
||||||
|
if self.finish_position == 1:
|
||||||
|
winner_seat_id = self.podium.index(0)
|
||||||
|
self.podium[winner_seat_id] = 1
|
||||||
|
|
||||||
|
battle_seat_ids = ','.join(str(n.seat_id) for n in self.battle_ninjas)
|
||||||
|
battle_card_ids = ','.join(str(n.deck[n.chosen].id) for n in self.battle_ninjas)
|
||||||
|
battle_energy = ','.join(str(n.energy) for n in self.battle_ninjas)
|
||||||
|
battle_states = ','.join(str(n.state) for n in self.battle_ninjas)
|
||||||
|
finish_positions = ','.join(str(position) for position in self.podium)
|
||||||
|
battle = f'{self.current_battle_type},{self.current_battle_element}'
|
||||||
|
|
||||||
|
for n in self.ninjas.copy():
|
||||||
|
deck = ','.join(str(card.id) for card in n.deck)
|
||||||
|
|
||||||
|
await n.penguin.send_xt(
|
||||||
|
'zm', 'rb',
|
||||||
|
battle_seat_ids,
|
||||||
|
battle_card_ids,
|
||||||
|
battle_energy,
|
||||||
|
battle_states,
|
||||||
|
battle,
|
||||||
|
deck,
|
||||||
|
finish_positions
|
||||||
|
)
|
||||||
|
|
||||||
|
if n.energy == 0 or self.finish_position == 1:
|
||||||
|
player_finish_position = self.podium[n.seat_id]
|
||||||
|
|
||||||
|
await end_game_stamps(n, player_finish_position)
|
||||||
|
await fire_ninja_progress(n.penguin, self.podium[n.seat_id])
|
||||||
|
|
||||||
|
finish_positions = ','.join(str(max(position, 1)) for position in self.podium)
|
||||||
|
await n.penguin.send_xt('zm', 'zo', finish_positions)
|
||||||
|
await self.remove_penguin(n.penguin, quit_early=False)
|
||||||
|
|
||||||
|
self.current_battle_state = 0
|
||||||
|
|
||||||
|
async def choose_opponent(self, seat_id):
|
||||||
|
if self.current_battle_state == 2 and seat_id != self.current_player.seat_id:
|
||||||
|
opponent = self.get_ninja_by_seat_id(seat_id)
|
||||||
|
self.battle_ninjas = [self.current_player, opponent]
|
||||||
|
|
||||||
|
self.current_battle_type = 'be'
|
||||||
|
self.current_battle_state = 3
|
||||||
|
|
||||||
|
battle_seat_ids = ','.join(str(ninja.seat_id) for ninja in self.battle_ninjas)
|
||||||
|
await self.send_xt('zm', 'sb', self.current_battle_type, battle_seat_ids, self.current_battle_element)
|
||||||
|
|
||||||
|
self.choose_board_timeout.cancel()
|
||||||
|
self.set_choose_card_timeout()
|
||||||
|
|
||||||
|
async def choose_trump(self, element):
|
||||||
|
if self.current_battle_state == 1 and element in CardJitsuFireLogic.Board[1:4]:
|
||||||
|
self.current_battle_element = element
|
||||||
|
self.current_battle_state = 3
|
||||||
|
|
||||||
|
battle_seat_ids = ','.join(str(ninja.seat_id) for ninja in self.ninjas)
|
||||||
|
await self.send_xt('zm', 'sb', self.current_battle_type, battle_seat_ids, self.current_battle_element)
|
||||||
|
|
||||||
|
self.choose_board_timeout.cancel()
|
||||||
|
self.set_choose_card_timeout()
|
||||||
|
|
||||||
|
async def remove_penguin(self, p, quit_early=True):
|
||||||
|
await super().remove_penguin(p)
|
||||||
|
ninja = self.get_ninja_by_penguin(p)
|
||||||
|
self.ninjas.remove(ninja)
|
||||||
|
|
||||||
|
if quit_early:
|
||||||
|
self.podium[ninja.seat_id] = self.finish_position
|
||||||
|
self.finish_position -= 1
|
||||||
|
await self.send_xt('zm', 'cz', ninja.seat_id)
|
||||||
|
|
||||||
|
if len(self.ninjas) == 1:
|
||||||
|
opponent = next(n for n in self.ninjas if n != ninja)
|
||||||
|
await opponent.penguin.send_xt('cz')
|
||||||
|
|
||||||
|
await self.remove_penguin(opponent.penguin)
|
||||||
|
elif len(self.ninjas) >= 2:
|
||||||
|
if ninja == self.current_player and 0 <= self.current_battle_state <= 2:
|
||||||
|
self.choose_board_timeout.cancel()
|
||||||
|
await self.auto_choose_board()
|
||||||
|
elif ninja.chosen is None and self.current_battle_state == 3:
|
||||||
|
playable_cards = self.get_playable_cards(ninja)
|
||||||
|
await self.choose_card(ninja, random.choice(playable_cards))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_battle_result(cls, first_card, second_card):
|
||||||
|
if first_card.element != second_card.element:
|
||||||
|
return 0 if cls.RuleSet[first_card.element] == second_card.element else 1
|
||||||
|
elif first_card.value > second_card.value:
|
||||||
|
return 0
|
||||||
|
elif second_card.value > first_card.value:
|
||||||
|
return 1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
class FireMatLogic(CardJitsuFireLogic):
|
||||||
|
|
||||||
|
RankSpeed = 0.5
|
||||||
|
|
||||||
|
|
||||||
class FireSenseiLogic(CardJitsuFireLogic):
|
class FireSenseiLogic(CardJitsuFireLogic):
|
||||||
|
|
||||||
def __init__(self, waddle):
|
def __init__(self, waddle):
|
||||||
super().__init__(waddle)
|
super().__init__(waddle)
|
||||||
|
|
||||||
|
sensei = FireNinja(
|
||||||
|
penguin=waddle.penguins[0],
|
||||||
|
seat_id=1
|
||||||
|
)
|
||||||
|
self.ninjas.append(sensei)
|
||||||
|
self.tile_ids.append(CardJitsuFireLogic.DefaultTiles[1])
|
||||||
|
|
||||||
|
async def auto_choose_card(self):
|
||||||
|
ninja = self.ninjas[0]
|
||||||
|
playable_cards = self.get_playable_cards(ninja)
|
||||||
|
await self.choose_card(ninja, random.choice(playable_cards))
|
||||||
|
|
||||||
|
async def ready_ninja(self, ninja):
|
||||||
|
if self.current_battle_state == 0:
|
||||||
|
self.next()
|
||||||
|
self.spin()
|
||||||
|
self.deal()
|
||||||
|
|
||||||
|
ninja.chosen = None
|
||||||
|
|
||||||
|
deck = ','.join(str(card.id) for card in ninja.deck)
|
||||||
|
spin = f'{self.spin_amount},{self.move_clockwise},{self.move_anticlockwise}'
|
||||||
|
|
||||||
|
await ninja.penguin.send_xt('zm', 'nt', self.current_player.seat_id, spin, deck)
|
||||||
|
|
||||||
|
if self.current_player == ninja:
|
||||||
|
self.set_choose_board_timeout()
|
||||||
|
else:
|
||||||
|
await self.auto_choose_board()
|
||||||
|
|
||||||
|
async def choose_card(self, ninja, card_id):
|
||||||
|
if ninja.chosen is None and self.is_card_playable(ninja, card_id):
|
||||||
|
self.choose_card_timeout.cancel()
|
||||||
|
|
||||||
|
sensei = self.ninjas[1]
|
||||||
|
ninja.chosen = card_id
|
||||||
|
card = ninja.deck[ninja.chosen]
|
||||||
|
|
||||||
|
can_beat_sensei = ninja.penguin.fire_ninja_rank >= 4
|
||||||
|
sensei_card = random.choice(list(ninja.penguin.server.cards.values())) \
|
||||||
|
if can_beat_sensei else self.get_win_card(card)
|
||||||
|
sensei.chosen = 0
|
||||||
|
sensei.deck = [sensei_card]
|
||||||
|
|
||||||
|
await ninja.penguin.send_xt('zm', 'ic', 1)
|
||||||
|
|
||||||
|
self.resolve_battle()
|
||||||
|
|
||||||
|
if ninja.energy == 0:
|
||||||
|
self.podium = [2, 1]
|
||||||
|
if sensei.energy == 0:
|
||||||
|
self.podium = [1, 2]
|
||||||
|
|
||||||
|
battle_seat_ids = ','.join(str(n.seat_id) for n in self.battle_ninjas)
|
||||||
|
battle_card_ids = ','.join(str(n.deck[n.chosen].id) for n in self.battle_ninjas)
|
||||||
|
battle_energy = ','.join(str(n.energy) for n in self.battle_ninjas)
|
||||||
|
battle_states = ','.join(str(n.state) for n in self.battle_ninjas)
|
||||||
|
finish_positions = ','.join(str(position) for position in self.podium)
|
||||||
|
deck = ','.join(str(card.id) for card in ninja.deck)
|
||||||
|
battle = f'{self.current_battle_type},{self.current_battle_element}'
|
||||||
|
|
||||||
|
await ninja.penguin.send_xt(
|
||||||
|
'zm', 'rb',
|
||||||
|
battle_seat_ids,
|
||||||
|
battle_card_ids,
|
||||||
|
battle_energy,
|
||||||
|
battle_states,
|
||||||
|
battle,
|
||||||
|
deck,
|
||||||
|
finish_positions
|
||||||
|
)
|
||||||
|
|
||||||
|
player_finish_position = self.podium[ninja.seat_id]
|
||||||
|
if player_finish_position > 0:
|
||||||
|
await end_game_stamps(ninja, player_finish_position)
|
||||||
|
await fire_ninja_progress(ninja.penguin, player_finish_position)
|
||||||
|
|
||||||
|
await ninja.penguin.send_xt('zm', 'zo', finish_positions)
|
||||||
|
await self.remove_penguin(ninja.penguin, quit_early=False)
|
||||||
|
|
||||||
|
self.current_battle_state = 0
|
||||||
|
|
||||||
|
def get_win_card(self, card):
|
||||||
|
cards_to_pick = self.penguins[0].server.cards
|
||||||
|
cards_iter = cards_to_pick.values()
|
||||||
|
cards_end_to_end = itertools.chain(cards_iter, cards_iter)
|
||||||
|
start_position = random.randint(0, len(cards_to_pick))
|
||||||
|
cards_random_start = itertools.islice(cards_end_to_end, start_position, start_position+len(cards_to_pick))
|
||||||
|
|
||||||
|
if self.current_battle_type == 'bt':
|
||||||
|
return next(card_check for card_check in cards_random_start
|
||||||
|
if card_check.element == self.current_battle_element
|
||||||
|
and card_check.value >= card.value)
|
||||||
|
elif self.current_battle_type == 'be':
|
||||||
|
return next(card_check for card_check in cards_random_start
|
||||||
|
if FireSenseiLogic.beats_card(card_check, card))
|
||||||
|
|
||||||
|
async def remove_penguin(self, p, quit_early=True):
|
||||||
|
ninja = self.get_ninja_by_penguin(p)
|
||||||
|
await super().remove_penguin(p, False)
|
||||||
|
|
||||||
|
if ninja == self.current_player and 0 <= self.current_battle_state <= 2:
|
||||||
|
self.choose_board_timeout.cancel()
|
||||||
|
elif ninja.chosen is None and self.current_battle_state == 3:
|
||||||
|
self.choose_card_timeout.cancel()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def beats_card(cls, card_check, card_play):
|
||||||
|
if card_check.element != card_play.element:
|
||||||
|
return True if cls.RuleSet[card_check.element] == card_play.element else False
|
||||||
|
elif card_check.value > card_play.value:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
async def fire_ninja_rank_up(p, ranks=1):
|
||||||
|
if p.fire_ninja_rank + ranks > len(CardJitsuFireLogic.ItemAwards):
|
||||||
|
return False
|
||||||
|
for rank in range(p.fire_ninja_rank, p.fire_ninja_rank+ranks):
|
||||||
|
await p.add_inventory(p.server.items[CardJitsuFireLogic.ItemAwards[rank]], notify=False)
|
||||||
|
if rank in CardJitsuFireLogic.StampAwards:
|
||||||
|
await p.add_stamp(p.server.stamps[CardJitsuFireLogic.StampAwards[rank]])
|
||||||
|
await p.update(
|
||||||
|
fire_ninja_rank=p.fire_ninja_rank + ranks,
|
||||||
|
fire_ninja_progress=p.fire_ninja_progress % 100
|
||||||
|
).apply()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def fire_ninja_progress(p, finish_position=1):
|
||||||
|
if p.fire_ninja_rank < 4:
|
||||||
|
speed = type(p.waddle).RankSpeed
|
||||||
|
points = math.floor((25 / (p.fire_ninja_rank+1) / finish_position) * speed)
|
||||||
|
await p.update(fire_ninja_progress=p.fire_ninja_progress+points).apply()
|
||||||
|
elif p.fire_ninja_rank == 4 and finish_position == 1:
|
||||||
|
await p.update(fire_ninja_progress=100).apply()
|
||||||
|
if p.fire_ninja_progress >= 100:
|
||||||
|
await fire_ninja_rank_up(p)
|
||||||
|
await p.send_xt('zm', 'nr', 0, p.fire_ninja_rank)
|
||||||
|
|
||||||
|
|
||||||
|
async def end_game_stamps(ninja, finish_position):
|
||||||
|
if finish_position == 1:
|
||||||
|
await ninja.penguin.update(fire_matches_won=ninja.penguin.fire_matches_won + 1).apply()
|
||||||
|
if ninja.penguin.fire_matches_won >= 10:
|
||||||
|
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[252])
|
||||||
|
if ninja.penguin.fire_matches_won >= 50:
|
||||||
|
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[268])
|
||||||
|
if ninja.energy >= 6:
|
||||||
|
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[260])
|
||||||
|
|
||||||
|
if ninja.energy_won >= 1:
|
||||||
|
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[254])
|
||||||
|
if ninja.energy_won >= 3:
|
||||||
|
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[266])
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('gz', ext='z'))
|
||||||
|
@handlers.waddle(CardJitsuFireLogic, FireMatLogic)
|
||||||
|
async def handle_get_game(p):
|
||||||
|
seat_id = p.waddle.get_seat_id(p)
|
||||||
|
await p.send_xt('gz', p.waddle.seats, len(p.waddle.penguins))
|
||||||
|
await p.send_xt('jz', seat_id)
|
||||||
|
|
||||||
|
nicknames = ','.join(penguin.safe_name for penguin in p.waddle.penguins)
|
||||||
|
colors = ','.join(str(penguin.color) for penguin in p.waddle.penguins)
|
||||||
|
energy = ','.join(str(ninja.energy) for ninja in p.waddle.ninjas)
|
||||||
|
tile_ids = ','.join(map(str, p.waddle.tile_ids))
|
||||||
|
deck = ','.join(str(card.id) for card in p.waddle.ninjas[seat_id].deck)
|
||||||
|
spin = f'{p.waddle.spin_amount},{p.waddle.move_clockwise},{p.waddle.move_anticlockwise}'
|
||||||
|
ninja_ranks = ','.join(str(penguin.fire_ninja_rank) for penguin in p.waddle.penguins)
|
||||||
|
|
||||||
|
await p.send_xt('sz', 0, nicknames, colors, energy, tile_ids, deck, spin, ninja_ranks)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('gz', ext='z'))
|
||||||
|
@handlers.waddle(FireSenseiLogic)
|
||||||
|
async def handle_get_sensei_game(p):
|
||||||
|
await p.send_xt('gz', p.waddle.seats, len(p.waddle.penguins))
|
||||||
|
await p.send_xt('jz', 0)
|
||||||
|
|
||||||
|
nicknames = f'{p.safe_name},Sensei'
|
||||||
|
colors = f'{p.color},-1'
|
||||||
|
energy = ','.join(str(ninja.energy) for ninja in p.waddle.ninjas)
|
||||||
|
tile_ids = ','.join(map(str, p.waddle.tile_ids))
|
||||||
|
deck = ','.join(str(card.id) for card in p.waddle.ninjas[0].deck)
|
||||||
|
spin = f'{p.waddle.spin_amount},{p.waddle.move_clockwise},{p.waddle.move_anticlockwise}'
|
||||||
|
ninja_ranks = ','.join(str(penguin.fire_ninja_rank) for penguin in p.waddle.penguins)
|
||||||
|
|
||||||
|
await p.send_xt('sz', 0, nicknames, colors, energy, tile_ids, deck, spin, ninja_ranks)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('zm', ext='z'), match=['is'])
|
||||||
|
@handlers.waddle(CardJitsuFireLogic, FireMatLogic, FireSenseiLogic)
|
||||||
|
async def handle_info_click_spinner(p, *, tab_id: int):
|
||||||
|
seat_id = p.waddle.get_seat_id(p)
|
||||||
|
|
||||||
|
if seat_id == p.waddle.current_player.seat_id:
|
||||||
|
await p.waddle.click_spinner(tab_id)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('zm', ext='z'), match=['cb'])
|
||||||
|
@handlers.waddle(CardJitsuFireLogic, FireMatLogic, FireSenseiLogic)
|
||||||
|
async def handle_choose_board(p, *, tile_id: int):
|
||||||
|
seat_id = p.waddle.get_seat_id(p)
|
||||||
|
if seat_id == p.waddle.current_player.seat_id:
|
||||||
|
await p.waddle.choose_board(tile_id)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('zm', ext='z'), match=['co'])
|
||||||
|
@handlers.waddle(CardJitsuFireLogic, FireMatLogic, FireSenseiLogic)
|
||||||
|
async def handle_choose_opponent(p, *, opponent_seat_id: int):
|
||||||
|
seat_id = p.waddle.get_seat_id(p)
|
||||||
|
if seat_id == p.waddle.current_player.seat_id:
|
||||||
|
await p.waddle.choose_opponent(opponent_seat_id)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('zm', ext='z'), match=['ct'])
|
||||||
|
@handlers.waddle(CardJitsuFireLogic, FireMatLogic, FireSenseiLogic)
|
||||||
|
async def handle_choose_trump(p, *, element: str):
|
||||||
|
seat_id = p.waddle.get_seat_id(p)
|
||||||
|
if seat_id == p.waddle.current_player.seat_id:
|
||||||
|
await p.waddle.choose_trump(element)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('zm', ext='z'), match=['cc'])
|
||||||
|
@handlers.waddle(CardJitsuFireLogic, FireMatLogic, FireSenseiLogic)
|
||||||
|
async def handle_choose_card(p, *, card_id: int):
|
||||||
|
ninja = p.waddle.get_ninja_by_penguin(p)
|
||||||
|
await p.waddle.choose_card(ninja, card_id)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('zm', ext='z'), match=['ir'])
|
||||||
|
@handlers.waddle(CardJitsuFireLogic, FireMatLogic, FireSenseiLogic)
|
||||||
|
async def handle_info_ready_sync(p):
|
||||||
|
ninja = p.waddle.get_ninja_by_penguin(p)
|
||||||
|
await p.waddle.ready_ninja(ninja)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('lz', ext='z'))
|
||||||
|
@handlers.player_in_room(CardJitsuFireLogic.room_id)
|
||||||
|
async def handle_leave_game(p):
|
||||||
|
await ninja_stamps_earned(p)
|
||||||
|
Loading…
Reference in New Issue
Block a user