diff --git a/backend/__init__.py b/backend/__init__.py index c25285c..2bb0999 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -58,13 +58,38 @@ def get_me(sid, room): de_games = [g for g in games if g.name == room['name']] if len(de_games) == 1 and not de_games[0].started: join_room(sid, room) + elif len(de_games) == 1 and de_games[0].started: + print('room exists') + if room['username'] != None and any([p.name == room['username'] for p in de_games[0].players if p.is_bot]): + print('getting inside the bot') + bot = [p for p in de_games[0].players if p.is_bot][0] + bot.sid = sid + bot.is_bot = False + sio.enter_room(sid, de_games[0].name) + sio.save_session(sid, bot) + de_games[0].notify_room(sid) + eventlet.sleep(0.1) + de_games[0].notify_all() + sio.emit('role', room=sid, data=json.dumps(bot.role, default=lambda o: o.__dict__)) + bot.notify_self() + else: #spectate + de_games[0].dead_players.append(sio.get_session(sid)) + sio.get_session(sid).game = de_games[0] + sio.enter_room(sid, de_games[0].name) + de_games[0].notify_room(sid) else: create_room(sid, room['name']) if sio.get_session(sid).game == None: sio.emit('me', data={'error':'Wrong password/Cannot connect'}, room=sid) else: sio.emit('me', data=sio.get_session(sid).name, room=sid) - sio.emit('change_username', room=sid) + if room['username'] == None or any([p.name == room['username'] for p in sio.get_session(sid).game.players]): + sio.emit('change_username', room=sid) + else: + sio.get_session(sid).name = room['username'] + sio.emit('me', data=sio.get_session(sid).name, room=sid) + if not sio.get_session(sid).game.started: + sio.get_session(sid).game.notify_room() @sio.event def disconnect(sid): @@ -101,6 +126,14 @@ def toggle_expansion(sid, expansion_name): g = sio.get_session(sid).game g.toggle_expansion(expansion_name) +@sio.event +def toggle_comp(sid): + sio.get_session(sid).game.toggle_competitive() + +@sio.event +def toggle_replace_with_bot(sid): + sio.get_session(sid).game.toggle_disconnect_bot() + @sio.event def join_room(sid, room): room_name = room['name'] @@ -130,9 +163,13 @@ def chat_message(sid, msg): elif '/removebot' in msg and not ses.game.started: if any([p.is_bot for p in ses.game.players]): [p for p in ses.game.players if p.is_bot][-1].disconnect() - elif '/suicide' in msg and ses.game.started: + elif '/suicide' in msg and ses.game.started and ses.lives > 0: ses.lives = 0 ses.notify_self() + elif '/togglecomp' in msg and ses.game: + ses.game.toggle_competitive() + elif '/togglebot' in msg and ses.game: + ses.game.toggle_disconnect_bot() elif '/cancelgame' in msg and ses.game.started: ses.game.reset() elif '/gameinfo' in msg: diff --git a/backend/bang/cards.py b/backend/bang/cards.py index fe27d66..4a664bc 100644 --- a/backend/bang/cards.py +++ b/backend/bang/cards.py @@ -316,7 +316,7 @@ class Mancato(Card): import bang.characters as chars if (not player.has_played_bang and against != None and isinstance(player.character, chars.CalamityJanet)): player.sio.emit('chat_message', room=player.game.name, - data=f'_calamity_special|{player.name}|{self.name}|{against}') + data=f'_special_calamity|{player.name}|{self.name}|{against}') player.has_played_bang = True player.game.attack(player, against) return True diff --git a/backend/bang/expansions/dodge_city/characters.py b/backend/bang/expansions/dodge_city/characters.py index e9c3362..c5c6ea7 100644 --- a/backend/bang/expansions/dodge_city/characters.py +++ b/backend/bang/expansions/dodge_city/characters.py @@ -47,7 +47,7 @@ class MollyStark(Character): def __init__(self): super().__init__("Molly Stark", max_lives=4) self.desc = "Quando usa volontariamente una carta che ha in mano, fuori dal suo turno, ne ottiene un'altra dal mazzo" - self.desc_eng = "When she uses a card from her hand outside her turn, he draws a card." + self.desc_eng = "When she uses a card from her hand outside her turn, she draws a card." self.icon = '๐Ÿ™…โ€โ™€๏ธ' class ApacheKid(Character): diff --git a/backend/bang/game.py b/backend/bang/game.py index c9df987..780bd2f 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -24,14 +24,18 @@ class Game: self.password = '' self.expansions = [] self.shutting_down = False + self.is_competitive = False + self.disconnect_bot = True - def notify_room(self): - if len([p for p in self.players if p.character == None]) != 0: - self.sio.emit('room', room=self.name, data={ + def notify_room(self, sid=None): + 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={ 'name': self.name, 'started': self.started, 'players': [{'name':p.name, 'ready': p.character != None} for p in self.players], 'password': self.password, + 'is_competitive': self.is_competitive, + 'disconnect_bot': self.disconnect_bot, 'expansions': self.expansions, }) @@ -44,6 +48,14 @@ class Game: self.expansions.append(expansion_name) self.notify_room() + def toggle_competitive(self): + self.is_competitive = not self.is_competitive + self.notify_room() + + def toggle_disconnect_bot(self): + self.disconnect_bot = not self.disconnect_bot + self.notify_room() + def add_player(self, player: players.Player): if player.is_bot and len(self.players) >= 8: return @@ -73,7 +85,7 @@ class Game: print(self.name) print(self.players[i].name) print(self.players[i].character) - self.sio.emit('chat_message', room=self.name, data=f'_choose_character|{self.players[i].name}|{self.players[i].character.name}|{self.players[i].character.desc}') + self.sio.emit('chat_message', room=self.name, data=f'_choose_character|{self.players[i].name}|{self.players[i].character.name}|{self.players[i].character.desc}|{self.players[i].character.desc_eng}') self.players[i].prepare() for k in range(self.players[i].max_lives): self.players[i].hand.append(self.deck.draw()) @@ -102,9 +114,9 @@ class Game: available_roles: List[roles.Role] = [] if len(self.players) == 3: available_roles = [ - roles.Vice('Elimina il Rinnegato ๐Ÿฆ…, se non lo elimini tu elimina anche il Fuorilegge'), - roles.Renegade('Elimina il Fuorilegge ๐Ÿบ, se non lo elimini tu elimina anche il Vice'), - roles.Outlaw('Elimina il Vice ๐ŸŽ–, se non lo elimini tu elimina anche il Rinnegato') + roles.Vice('Elimina il Rinnegato ๐Ÿฆ…, se non lo elimini tu elimina anche il Fuorilegge', 'Kill the Renegade ๐Ÿฆ…, if you are not the one who kills him then kill the Outlaw!'), + roles.Renegade('Elimina il Fuorilegge ๐Ÿบ, se non lo elimini tu elimina anche il Vice', 'Kill the Outlaw ๐Ÿบ, if you are not the one who kills him then kill the Vice!'), + roles.Outlaw('Elimina il Vice ๐ŸŽ–, se non lo elimini tu elimina anche il Rinnegato', 'Kill the Vice ๐ŸŽ–, if you are not the one who kills him then kill the Renegade!') ] elif len(self.players) >= 4: available_roles = [roles.Sheriff(), roles.Renegade(), roles.Outlaw(), roles.Outlaw(), roles.Vice(), roles.Outlaw(), roles.Vice(), roles.Renegade(), roles.Outlaw(), roles.Vice(), roles.Outlaw()] @@ -215,7 +227,10 @@ class Game: def handle_disconnect(self, player: players.Player): print(f'player {player.name} left the game {self.name}') if player in self.players: - self.player_death(player=player, disconnected=True) + if self.disconnect_bot and self.started: + player.is_bot = True + else: + self.player_death(player=player, disconnected=True) else: self.dead_players.remove(player) if len([p for p in self.players if not p.is_bot])+len([p for p in self.dead_players if not p.is_bot]) == 0: @@ -228,9 +243,10 @@ class Game: else: return False def player_death(self, player: players.Player, disconnected=False): + if not player in self.players: return import bang.expansions.dodge_city.characters as chd print(player.attacker) - if player.attacker and isinstance(player.attacker, roles.Sheriff) and isinstance(player.role, roles.Vice): + if player.attacker and isinstance(player.attacker.role, roles.Sheriff) and isinstance(player.role, roles.Vice): for i in range(len(player.attacker.hand)): self.deck.scrap(player.attacker.hand.pop()) for i in range(len(player.attacker.equipment)): @@ -303,6 +319,7 @@ class Game: print('resetting lobby') self.players.extend(self.dead_players) self.dead_players = [] + self.players = [p for p in self.players if not p.is_bot] print(self.players) self.started = False self.waiting_for = 0 diff --git a/backend/bang/players.py b/backend/bang/players.py index 6c33e36..ad25c59 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -256,7 +256,11 @@ class Player: self.choose(randrange(0, len(self.available_cards))) else: target = self.game.get_player_named(self.target_p) - self.choose(randrange(0, len(target.hand)+len(target.equipment))) + if len(target.hand)+len(target.equipment) == 0: + self.pending_action = PendingAction.PLAY + self.notify_self() + else: + self.choose(randrange(0, len(target.hand)+len(target.equipment))) def play_turn(self): if self.lives == 0: @@ -470,7 +474,7 @@ class Player: if self.mancato_needed <= 0: self.game.responders_did_respond_resume_turn() return - if len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\ + if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\ and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0: self.take_damage_response() self.game.responders_did_respond_resume_turn() @@ -488,7 +492,7 @@ class Player: for i in range(len(self.equipment)): if self.equipment[i].can_be_used_now: print('usable', self.equipment[i]) - if len([c for c in self.equipment if isinstance(c, cs.Barile)]) == 0 and not isinstance(self.character, chars.Jourdonnais)\ + if not self.game.is_competitive and len([c for c in self.equipment if isinstance(c, cs.Barile)]) == 0 and not isinstance(self.character, chars.Jourdonnais)\ and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\ and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0: print('Cant defend') @@ -510,7 +514,7 @@ class Player: def get_indians(self, attacker): self.attacker = attacker - if len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0: + if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0: print('Cant defend') self.take_damage_response() return False @@ -524,7 +528,7 @@ class Player: def get_dueled(self, attacker): self.attacker = attacker - if len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0: + if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0: print('Cant defend') self.take_damage_response() self.game.responders_did_respond_resume_turn() diff --git a/backend/bang/roles.py b/backend/bang/roles.py index 66c9204..449de58 100644 --- a/backend/bang/roles.py +++ b/backend/bang/roles.py @@ -28,11 +28,12 @@ class Sheriff(Role): class Vice(Role): - def __init__(self, alternative_goal=None): + def __init__(self, alternative_goal=None, alternative_goal_eng=None): super().__init__("Vice", "Proteggi lo Sceriffo! Elimina tutti i Fuorilegge e il Rinnegato!") self.goal_eng = "Protect the Sheriff! Kill the Outlaws and the Renegade!" if alternative_goal: self.goal = alternative_goal + self.goal_eng = alternative_goal_eng self.max_players = 2 self.icon = '๐ŸŽ–' @@ -47,11 +48,12 @@ class Vice(Role): return False class Outlaw(Role): - def __init__(self, alternative_goal=None): + def __init__(self, alternative_goal=None, alternative_goal_eng=None): super().__init__("Fuorilegge", "Elimina lo Sceriffo!") - self.goal_eng = "Kill the Sheriff!" + self.goal_eng = "Kill the sSheriff!" if alternative_goal: self.goal = alternative_goal + self.goal_eng = alternative_goal_eng self.max_players = 3 self.icon = '๐Ÿบ' @@ -66,11 +68,12 @@ class Outlaw(Role): return False class Renegade(Role): - def __init__(self, alternative_goal=None): + def __init__(self, alternative_goal=None, alternative_goal_eng=None): super().__init__("Rinnegato", "Rimani l'ultimo personaggio in gioco!") self.goal_eng = "Be the last man standing!" if alternative_goal: self.goal = alternative_goal + self.goal_eng = alternative_goal_eng self.max_players = 1 self.icon = '๐Ÿฆ…' diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 36179cc..43eac7f 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -7,7 +7,7 @@

{{$t("warning")}}

{{$t("connection_error")}}

-