work on replays

Co-authored-by: GM <giulio.migani@studenti.unitn.it>
This commit is contained in:
Alberto Xamin 2021-10-07 16:53:53 +03:00
parent fa983d44dc
commit 7f9e0bd964
No known key found for this signature in database
GPG Key ID: 4F026F48309500A2
4 changed files with 84 additions and 47 deletions

View File

@ -1,7 +1,6 @@
import os import os
import json import json
import random import random
from tests.dummy_socket import DummySocket
from typing import List from typing import List
import eventlet import eventlet
import socketio import socketio
@ -335,7 +334,7 @@ def chat_message(sid, msg, pl=None):
bot.bot_spin() bot.bot_spin()
return return
if '/report' in msg and not ses.game.is_replay: if '/report' in msg and not ses.game.is_replay:
data = "\n".join(ses.game.rpc_log).strip() data = "\n".join(ses.game.rpc_log[:-1]).strip()
response = requests.post("http://hastebin.com/documents", data) response = requests.post("http://hastebin.com/documents", data)
key = json.loads(response.text).get('key') key = json.loads(response.text).get('key')
webhook = DiscordWebhook(url=os.environ['DISCORD_WEBHOOK'], content=f'New bug report, replay at https://hastebin.com/{key}') webhook = DiscordWebhook(url=os.environ['DISCORD_WEBHOOK'], content=f'New bug report, replay at https://hastebin.com/{key}')
@ -348,47 +347,13 @@ def chat_message(sid, msg, pl=None):
response = requests.get(f"http://hastebin.com/raw/{replay_id}") response = requests.get(f"http://hastebin.com/raw/{replay_id}")
log = response.text.splitlines() log = response.text.splitlines()
ses.game.spectators.append(ses) ses.game.spectators.append(ses)
ses.game.players = [] ses.game.replay(log)
ses.game.is_replay = True return
for i in range(len(log)): if '/replayspeed' in msg:
print('replay:', i, 'of', len(log)) _cmd = msg.split()
cmd = log[i].split(';') if len(_cmd) == 2:
if cmd[1] == 'players': ses.game.replay_speed = float(cmd[1])
ses.game.expansions = json.loads(cmd[4].replace("'",'"')) return
pnames = json.loads(cmd[3].replace("'",'"'))
for p in pnames:
ses.game.add_player(Player(p, p, DummySocket(), bot=False))
continue
if cmd[1] == 'start_game':
ses.game.start_game(int(cmd[2]))
continue
player = [p for p in ses.game.players if p.name == cmd[0]][0]
if cmd[1] == 'set_character':
player.set_character(cmd[2])
if cmd[1] == 'draw':
player.draw(cmd[2])
if cmd[1] == 'pick':
player.pick()
if cmd[1] == 'end_turn':
player.end_turn()
if cmd[1] == 'play_card':
data = json.loads(cmd[2])
player.play_card(data['index'], data['against'], data['with'])
if cmd[1] == 'respond':
player.respond(int(cmd[2]))
if cmd[1] == 'choose':
player.choose(int(cmd[2]))
if cmd[1] == 'scrap':
player.scrap(int(cmd[2]))
if cmd[1] == 'special':
player.special(json.loads(cmd[2]))
if cmd[1] == 'gold_rush_discard':
player.gold_rush_discard()
if cmd[1] == 'buy_gold_rush_card':
player.buy_gold_rush_card(int(cmd[2]))
if cmd[1] == 'chat_message':
chat_message(None, cmd[2], player)
eventlet.sleep(1)
if '/startwithseed' in msg and not ses.game.started: if '/startwithseed' in msg and not ses.game.started:
if len(msg.split()) > 1: if len(msg.split()) > 1:
ses.game.start_game(int(msg.split()[1])) ses.game.start_game(int(msg.split()[1]))

View File

@ -13,7 +13,6 @@ import bang.expansions.fistful_of_cards.card_events as ce
import bang.expansions.high_noon.card_events as ceh import bang.expansions.high_noon.card_events as ceh
import bang.expansions.gold_rush.shop_cards as grc import bang.expansions.gold_rush.shop_cards as grc
import bang.expansions.gold_rush.characters as grch import bang.expansions.gold_rush.characters as grch
class Game: class Game:
def __init__(self, name, sio:socketio): def __init__(self, name, sio:socketio):
super().__init__() super().__init__()
@ -74,6 +73,52 @@ class Game:
eventlet.sleep(0.5) eventlet.sleep(0.5)
self.notify_room() self.notify_room()
def replay(self, log):
from tests.dummy_socket import DummySocket
self.players = []
self.is_hidden = True
self.is_replay = True
self.replay_speed = 1
for i in range(len(log)):
print('replay:', i, 'of', len(log))
cmd = log[i].split(';')
if cmd[1] == 'players':
self.expansions = json.loads(cmd[4].replace("'",'"'))
pnames = json.loads(cmd[3].replace("'",'"'))
for p in pnames:
self.add_player(pl.Player(p, p, DummySocket(self.sio), bot=False))
continue
if cmd[1] == 'start_game':
self.start_game(int(cmd[2]))
continue
player = [p for p in self.players if p.name == cmd[0]][0]
if cmd[1] == 'set_character':
player.set_character(cmd[2])
if cmd[1] == 'draw':
player.draw(cmd[2])
if cmd[1] == 'pick':
player.pick()
if cmd[1] == 'end_turn':
player.end_turn()
if cmd[1] == 'play_card':
data = json.loads(cmd[2])
player.play_card(data['index'], data['against'], data['with'])
if cmd[1] == 'respond':
player.respond(int(cmd[2]))
if cmd[1] == 'choose':
player.choose(int(cmd[2]))
if cmd[1] == 'scrap':
player.scrap(int(cmd[2]))
if cmd[1] == 'special':
player.special(json.loads(cmd[2]))
if cmd[1] == 'gold_rush_discard':
player.gold_rush_discard()
if cmd[1] == 'buy_gold_rush_card':
player.buy_gold_rush_card(int(cmd[2]))
# if cmd[1] == 'chat_message':
# chat_message(None, cmd[2], player)
eventlet.sleep(self.replay_speed)
def notify_room(self, sid=None): def notify_room(self, sid=None):
if len([p for p in self.players if p.character == None]) != 0 or sid: if len([p for p in self.players if p.character == None]) != 0 or sid:
self.sio.emit('room', room=self.name if not sid else sid, data={ self.sio.emit('room', room=self.name if not sid else sid, data={

View File

@ -135,7 +135,9 @@ class Player:
self.sio.emit('characters', room=self.sid, data=json.dumps( self.sio.emit('characters', room=self.sid, data=json.dumps(
available, default=lambda o: o.__dict__)) available, default=lambda o: o.__dict__))
else: else:
self.set_character(available[randrange(0, len(available))].name) char_name = available[randrange(0, len(available))].name
self.game.rpc_log.append(f'{self.name};set_character;{char_name}')
self.set_character(char_name)
def notify_card(self, player, card, message=''): def notify_card(self, player, card, message=''):
try: try:
@ -233,8 +235,10 @@ class Player:
else: else:
return return
if self.pending_action == PendingAction.PICK: if self.pending_action == PendingAction.PICK:
self.game.rpc_log.append(f'{self.name};pick;')
self.pick() self.pick()
elif self.pending_action == PendingAction.DRAW: elif self.pending_action == PendingAction.DRAW:
self.game.rpc_log.append(f'{self.name};draw;')
self.draw('') self.draw('')
elif self.pending_action == PendingAction.PLAY: elif self.pending_action == PendingAction.PLAY:
non_blocked_cards = [card for card in self.hand if (not self.game.check_event(ceh.Manette) or card.suit == self.committed_suit_manette)] non_blocked_cards = [card for card in self.hand if (not self.game.check_event(ceh.Manette) or card.suit == self.committed_suit_manette)]
@ -253,6 +257,7 @@ class Player:
if self.gold_nuggets > 0 and any([c.number <= self.gold_nuggets for c in self.game.deck.shop_cards]): if self.gold_nuggets > 0 and any([c.number <= self.gold_nuggets for c in self.game.deck.shop_cards]):
for i in range(len(self.game.deck.shop_cards)): for i in range(len(self.game.deck.shop_cards)):
if self.game.deck.shop_cards[i].number <= self.gold_nuggets: if self.game.deck.shop_cards[i].number <= self.gold_nuggets:
self.game.rpc_log.append(f'{self.name};buy_gold_rush_card;{i}')
self.buy_gold_rush_card(i) self.buy_gold_rush_card(i)
return return
if len(equippables) > 0 and not self.game.check_event(ce.IlGiudice): if len(equippables) > 0 and not self.game.check_event(ce.IlGiudice):
@ -305,26 +310,33 @@ class Player:
if maxcards == self.lives and len([c for c in self.gold_rush_equipment if isinstance(c, grc.Cinturone)]) > 0: if maxcards == self.lives and len([c for c in self.gold_rush_equipment if isinstance(c, grc.Cinturone)]) > 0:
maxcards = 8 maxcards = 8
if len(self.hand) > maxcards: if len(self.hand) > maxcards:
self.game.rpc_log.append(f'{self.name};scrap;{0}')
self.scrap(0) self.scrap(0)
else: else:
self.game.rpc_log.append(f'{self.name};end_turn')
self.end_turn() self.end_turn()
elif self.pending_action == PendingAction.RESPOND: elif self.pending_action == PendingAction.RESPOND:
did_respond = False did_respond = False
for i in range(len(self.hand)): for i in range(len(self.hand)):
if self.hand[i].can_be_used_now and (self.hand[i].name in self.expected_response or self.character.check(self.game, chd.ElenaFuente)): if self.hand[i].can_be_used_now and (self.hand[i].name in self.expected_response or self.character.check(self.game, chd.ElenaFuente)):
self.game.rpc_log.append(f'{self.name};respond;{i}')
self.respond(i) self.respond(i)
did_respond = True did_respond = True
break break
for i in range(len(self.equipment)): for i in range(len(self.equipment)):
if not self.game.check_event(ce.Lazo) and self.equipment[i].name in self.expected_response: if not self.game.check_event(ce.Lazo) and self.equipment[i].name in self.expected_response:
self.game.rpc_log.append(f'{self.name};respond;{len(self.hand)+i}')
self.respond(len(self.hand)+i) self.respond(len(self.hand)+i)
did_respond = True did_respond = True
break break
if not did_respond: if not did_respond:
self.game.rpc_log.append(f'{self.name};respond;{-1}')
self.respond(-1) self.respond(-1)
elif self.pending_action == PendingAction.CHOOSE: elif self.pending_action == PendingAction.CHOOSE:
if not self.target_p: if not self.target_p:
self.choose(randrange(0, len(self.available_cards))) card_index = randrange(0, len(self.available_cards))
self.game.rpc_log.append(f'{self.name};choose;{card_index}')
self.choose(card_index)
else: else:
target = self.game.get_player_named(self.target_p) target = self.game.get_player_named(self.target_p)
if len(target.hand)+len(target.equipment) == 0: if len(target.hand)+len(target.equipment) == 0:
@ -332,8 +344,11 @@ class Player:
self.notify_self() self.notify_self()
else: else:
try: try:
self.choose(randrange(0, len(target.hand)+len(target.equipment))) card_index = randrange(0, len(target.hand)+len(target.equipment))
self.game.rpc_log.append(f'{self.name};choose;{card_index}')
self.choose(card_index)
except: except:
self.game.rpc_log.append(f'{self.name};choose;{0}')
self.choose(0) self.choose(0)
@ -577,6 +592,13 @@ class Player:
return playable_cards return playable_cards
def play_card(self, hand_index: int, against=None, _with=None): def play_card(self, hand_index: int, against=None, _with=None):
if self.is_bot:
data = {
"index": hand_index,
"against": against,
"with": _with
}
self.game.rpc_log.append(f'{self.name};play_card;{json.dumps(data)}')
print(self.name, 'wants to play card ', hand_index, ' against:', against, ' with:', _with) print(self.name, 'wants to play card ', hand_index, ' against:', against, ' with:', _with)
if not self.is_my_turn or self.pending_action != PendingAction.PLAY or self.game.is_handling_death: if not self.is_my_turn or self.pending_action != PendingAction.PLAY or self.game.is_handling_death:
print('but cannot') print('but cannot')

View File

@ -1,6 +1,11 @@
class DummySocket(): class DummySocket():
def __init__(self, sio=None):
self.true_sio = sio
def emit(self, event, data=None, to=None, room=None, skip_sid=None, namespace=None, callback=None, **kwargs): def emit(self, event, data=None, to=None, room=None, skip_sid=None, namespace=None, callback=None, **kwargs):
# print(f'event: {event}, data: {data}, to: {to}, room: {room}') # print(f'event: {event}, data: {data}, to: {to}, room: {room}')
if self.true_sio and event == 'chat_message':
self.true_sio.emit(event, data, to, room, skip_sid, namespace, callback, **kwargs)
return True return True
is_fake = True is_fake = True