From 0ed906fc390ba34a8bdeffd781b058fc91ac9245 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 5 Dec 2020 17:11:27 +0100 Subject: [PATCH 1/6] bots --- backend/__init__.py | 5 +++ backend/bang/game.py | 10 +++-- backend/bang/players.py | 89 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 90 insertions(+), 14 deletions(-) diff --git a/backend/__init__.py b/backend/__init__.py index 6737c95..2837a7b 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -120,6 +120,11 @@ def join_room(sid, room): def chat_message(sid, msg): ses: Player = sio.get_session(sid) sio.emit('chat_message', room=ses.game.name, data=f'[{ses.name}]: {msg}') + if '/addbot' in msg and not ses.game.started: + ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) + 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() @sio.event def start_game(sid): diff --git a/backend/bang/game.py b/backend/bang/game.py index 1c5531b..30b682c 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -124,6 +124,7 @@ class Game: if p != attacker: if p.get_banged(attacker=attacker): self.waiting_for += 1 + p.notify_self() if self.waiting_for == 0: attacker.pending_action = players.PendingAction.PLAY attacker.notify_self() @@ -137,23 +138,26 @@ class Game: if p != attacker: if p.get_indians(attacker=attacker): self.waiting_for += 1 + p.notify_self() if self.waiting_for == 0: attacker.pending_action = players.PendingAction.PLAY attacker.notify_self() def attack(self, attacker: players.Player, target_username:str, double:bool=False): - if self.players[self.players_map[target_username]].get_banged(attacker=attacker, double=double): + if self.get_player_named(target_username).get_banged(attacker=attacker, double=double): self.readyCount = 0 self.waiting_for = 1 attacker.pending_action = players.PendingAction.WAIT attacker.notify_self() + self.get_player_named(target_username).notify_self() def duel(self, attacker: players.Player, target_username:str): - if self.players[self.players_map[target_username]].get_dueled(attacker=attacker): + if self.get_player_named(target_username).get_dueled(attacker=attacker): self.readyCount = 0 self.waiting_for = 1 attacker.pending_action = players.PendingAction.WAIT attacker.notify_self() + self.get_player_named(target_username).notify_self() def emporio(self): self.available_cards = [self.deck.draw() for i in range(len(self.players))] @@ -207,7 +211,7 @@ class Game: def handle_disconnect(self, player: players.Player): print(f'player {player.name} left the game {self.name}') self.player_death(player=player, disconnected=True) - if len(self.players) == 0: + if len([p for p in self.players if not p.is_bot]) == 0: print(f'no players left in game {self.name}') return True else: return False diff --git a/backend/bang/players.py b/backend/bang/players.py index 055959b..8b901b5 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -1,6 +1,6 @@ from enum import IntEnum import json -from random import randrange +from random import random, randrange, sample, uniform import socketio import bang.deck as deck import bang.roles as r @@ -8,6 +8,7 @@ import bang.cards as cs import bang.expansions.dodge_city.cards as csd import bang.characters as chars import bang.expansions.dodge_city.characters as chd +import eventlet class PendingAction(IntEnum): PICK = 0 @@ -19,7 +20,7 @@ class PendingAction(IntEnum): class Player: - def __init__(self, name, sid, sio): + def __init__(self, name, sid, sio, bot=False): import bang.game as g super().__init__() self.name = name @@ -47,6 +48,7 @@ class Player: self.is_drawing = False self.mancato_needed = 0 self.molly_discarded_cards = 0 + self.is_bot = bot def reset(self): self.hand: cs.Card = [] @@ -108,8 +110,12 @@ class Player: def set_available_character(self, available): self.available_characters = available print(f'I {self.name} have to choose between {available}') - self.sio.emit('characters', room=self.sid, data=json.dumps( - available, default=lambda o: o.__dict__)) + if not self.is_bot: + self.sio.emit('characters', room=self.sid, data=json.dumps( + available, default=lambda o: o.__dict__)) + else: + eventlet.sleep(uniform(1, 2)) + self.set_character(available[randrange(0, len(available))].name) def notify_card(self, player, card): mess = { @@ -151,12 +157,75 @@ class Player: if self.lives <= 0 and self.max_lives > 0: self.pending_action = PendingAction.WAIT self.game.player_death(self) - else: + elif not self.is_bot: self.sio.emit('self_vis', room=self.sid, data=json.dumps( self.game.get_visible_players(self), default=lambda o: o.__dict__)) - self.sio.emit('self', room=self.sid, data=json.dumps( + if not self.is_bot: + self.sio.emit('self', room=self.sid, data=json.dumps( ser, default=lambda o: o.__dict__)) - self.game.notify_all() + self.game.notify_all() + else: + self.game.notify_all() + if self.pending_action != PendingAction.WAIT: + eventlet.sleep(uniform(0.6, 1.5)) + else: + return + if self.pending_action == PendingAction.PICK: + self.pick() + elif self.pending_action == PendingAction.DRAW: + self.draw('') + elif self.pending_action == PendingAction.PLAY: + has_played = False + if len([c for c in self.hand if c.is_equipment or c.usable_next_turn]) > 0: + for i in range(len(self.hand)): + if self.hand[i].is_equipment or self.hand[i].usable_next_turn: + self.play_card(i) + has_played = True + break + if len([c for c in self.hand if c.need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment]))]) > 0: + for i in range(len(self.hand)): + if self.hand[i].need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment])): + if self.hand[i].need_with and len(self.hand) < 2: + continue + _range = self.get_sight() if self.hand[i].name == 'Bang!' or self.hand[i].name == "Pepperbox" else self.hand[i].range + others = [p for p in self.game.get_visible_players(self) if _range <= p['dist']] + if len(others) == 0: + continue + target = others[randrange(0, len(others))] + len_before = len(self.hand) + if not self.hand[i].need_with: + self.play_card(i, against=target['name']) + else: + self.play_card(i, against=target['name'], _with=sample([j for j in range(len(self.hand)) if j != i], 1)[0]) + has_played = True + break + if any([isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or isinstance(c, cs.Birra) for c in self.hand]): + for i in range(len(self.hand)): + c = self.hand[i] + if isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or (isinstance(c, cs.Birra) and self.lives < self.max_lives): + self.play_card(i) + has_played = True + break + if not has_played and len(self.hand) > self.lives: + self.scrap(0) + else: + self.end_turn() + elif self.pending_action == PendingAction.RESPOND: + did_respond = False + for i in range(len(self.hand)): + if self.hand[i].name in self.expected_response: + self.respond(i) + did_respond = True + break + if not did_respond: + self.respond(-1) + elif self.pending_action == PendingAction.CHOOSE: + if not self.target_p: + 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))) + self.game.notify_all() def play_turn(self): if self.lives == 0: @@ -405,7 +474,6 @@ class Player: if isinstance(self.character, chd.ElenaFuente): self.expected_response = self.game.deck.all_cards_str self.on_failed_response_cb = self.take_damage_response - self.notify_self() return True def get_indians(self, attacker): @@ -420,7 +488,6 @@ class Player: self.expected_response = [cs.Bang(0, 0).name] self.event_type = 'indians' self.on_failed_response_cb = self.take_damage_response - self.notify_self() return True def get_dueled(self, attacker): @@ -435,7 +502,6 @@ class Player: self.expected_response = [cs.Bang(0, 0).name] self.event_type = 'duel' self.on_failed_response_cb = self.take_damage_response - self.notify_self() return True def take_damage_response(self): @@ -467,6 +533,7 @@ class Player: self.attacker = None def respond(self, hand_index): + if self.pending_action != PendingAction.RESPOND: return self.pending_action = PendingAction.WAIT if hand_index != -1 and ( ((hand_index < len(self.hand) and self.hand[hand_index].name in self.expected_response)) or @@ -540,7 +607,7 @@ class Player: if len(self.hand) > self.max_lives and not forced: print( f"I {self.name} have to many cards in my hand and I can't end the turn") - else: + elif self.pending_action == PendingAction.PLAY or forced: self.is_my_turn = False for i in range(len(self.equipment)): if self.equipment[i].usable_next_turn and not self.equipment[i].can_be_used_now: From 46239f9b30eb1206736c9a73abebe1171386e0b0 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 5 Dec 2020 21:57:53 +0100 Subject: [PATCH 2/6] bot improvements --- backend/__init__.py | 8 ++- backend/bang/game.py | 3 +- backend/bang/players.py | 140 ++++++++++++++++++++++++---------------- 3 files changed, 92 insertions(+), 59 deletions(-) diff --git a/backend/__init__.py b/backend/__init__.py index 2837a7b..27b167c 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -121,10 +121,16 @@ def chat_message(sid, msg): ses: Player = sio.get_session(sid) sio.emit('chat_message', room=ses.game.name, data=f'[{ses.name}]: {msg}') if '/addbot' in msg and not ses.game.started: - ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) + if len(msg.split()) > 1: + for _ in range(int(msg.split()[1])): + ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) + else: + ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) 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: + ses.game.player_death(player=ses) @sio.event def start_game(sid): diff --git a/backend/bang/game.py b/backend/bang/game.py index 30b682c..32ea89f 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -246,7 +246,8 @@ class Game: if self.started: self.sio.emit('chat_message', room=self.name, data=f'_died_role|{player.name}|{player.role.name}') for p in self.players: - p.notify_self() + if not p.is_bot: + p.notify_self() self.players_map = {c.name: i for i, c in enumerate(self.players)} if self.started: print('Check win status') diff --git a/backend/bang/players.py b/backend/bang/players.py index 8b901b5..7436c1d 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -114,7 +114,6 @@ class Player: self.sio.emit('characters', room=self.sid, data=json.dumps( available, default=lambda o: o.__dict__)) else: - eventlet.sleep(uniform(1, 2)) self.set_character(available[randrange(0, len(available))].name) def notify_card(self, player, card): @@ -166,66 +165,93 @@ class Player: self.game.notify_all() else: self.game.notify_all() - if self.pending_action != PendingAction.WAIT: - eventlet.sleep(uniform(0.6, 1.5)) - else: - return - if self.pending_action == PendingAction.PICK: - self.pick() - elif self.pending_action == PendingAction.DRAW: - self.draw('') - elif self.pending_action == PendingAction.PLAY: - has_played = False - if len([c for c in self.hand if c.is_equipment or c.usable_next_turn]) > 0: - for i in range(len(self.hand)): - if self.hand[i].is_equipment or self.hand[i].usable_next_turn: - self.play_card(i) - has_played = True - break - if len([c for c in self.hand if c.need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment]))]) > 0: - for i in range(len(self.hand)): - if self.hand[i].need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment])): - if self.hand[i].need_with and len(self.hand) < 2: - continue - _range = self.get_sight() if self.hand[i].name == 'Bang!' or self.hand[i].name == "Pepperbox" else self.hand[i].range - others = [p for p in self.game.get_visible_players(self) if _range <= p['dist']] + self.bot_logic() + self.game.notify_all() + + def bot_logic(self): + if self.pending_action != PendingAction.WAIT: + eventlet.sleep(uniform(0.6, 1.5)) + else: + return + if self.pending_action == PendingAction.PICK: + self.pick() + elif self.pending_action == PendingAction.DRAW: + self.draw('') + elif self.pending_action == PendingAction.PLAY: + has_played = False + if len([c for c in self.hand if c.is_equipment or c.usable_next_turn]) > 0: + for i in range(len(self.hand)): + if self.hand[i].is_equipment or self.hand[i].usable_next_turn: + self.play_card(i) + has_played = True + break + elif any([isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or isinstance(c, cs.Birra) for c in self.hand]): + for i in range(len(self.hand)): + c = self.hand[i] + if isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or (isinstance(c, cs.Birra) and self.lives < self.max_lives): + self.play_card(i) + has_played = True + break + elif len([c for c in self.hand if c.need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment]))]) > 0: + for i in range(len(self.hand)): + if self.hand[i].need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment])): + if self.hand[i].need_with and len(self.hand) < 2: + continue + _range = self.get_sight() if self.hand[i].name == 'Bang!' or self.hand[i].name == "Pepperbox" else self.hand[i].range + others = [p for p in self.game.get_visible_players(self) if _range >= p['dist'] and not (isinstance(self.role, r.Vice) and p['is_sheriff'])] + if len(others) == 0: + continue + target = others[randrange(0, len(others))] + if target['is_sheriff'] and isinstance(self.role, r.Renegade): + target = others[randrange(0, len(others))] + if not self.hand[i].need_with: + self.play_card(i, against=target['name']) + else: + self.play_card(i, against=target['name'], _with=sample([j for j in range(len(self.hand)) if j != i], 1)[0]) + has_played = True + break + elif any([not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now for c in self.equipment]): + print('hmm', [not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now for c in self.equipment]) + for i in range(len(self.equipment)): + c = self.equipment[i] + if not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now: + if not c.need_target: + self.play_card(len(self.hand)+i) + else: + _range = self.get_sight() if c.name == "Pepperbox" else self.hand[i].range + others = [p for p in self.game.get_visible_players(self) if _range >= p['dist'] and not (isinstance(self.role, r.Vice) and p['is_sheriff'])] if len(others) == 0: continue target = others[randrange(0, len(others))] - len_before = len(self.hand) - if not self.hand[i].need_with: - self.play_card(i, against=target['name']) - else: - self.play_card(i, against=target['name'], _with=sample([j for j in range(len(self.hand)) if j != i], 1)[0]) - has_played = True - break - if any([isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or isinstance(c, cs.Birra) for c in self.hand]): - for i in range(len(self.hand)): - c = self.hand[i] - if isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or (isinstance(c, cs.Birra) and self.lives < self.max_lives): - self.play_card(i) - has_played = True - break - if not has_played and len(self.hand) > self.lives: - self.scrap(0) - else: - self.end_turn() - elif self.pending_action == PendingAction.RESPOND: - did_respond = False - for i in range(len(self.hand)): - if self.hand[i].name in self.expected_response: - self.respond(i) - did_respond = True + if target['is_sheriff'] and isinstance(self.role, r.Renegade): + target = others[randrange(0, len(others))] + self.play_card(len(self.hand)+i, against=target['name']) + has_played = True break - if not did_respond: - self.respond(-1) - elif self.pending_action == PendingAction.CHOOSE: - if not self.target_p: - 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))) - self.game.notify_all() + if not has_played and len(self.hand) > self.lives: + self.scrap(0) + else: + self.end_turn() + elif self.pending_action == PendingAction.RESPOND: + did_respond = False + for i in range(len(self.hand)): + if self.hand[i].name in self.expected_response: + self.respond(i) + did_respond = True + break + for i in range(len(self.equipment)): + if self.equipment[i].name in self.expected_response: + self.respond(len(self.hand)+i) + did_respond = True + break + if not did_respond: + self.respond(-1) + elif self.pending_action == PendingAction.CHOOSE: + if not self.target_p: + 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))) def play_turn(self): if self.lives == 0: From 66c99574c927c218353fb0938dcb4f4404d08a63 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sun, 6 Dec 2020 15:20:44 +0100 Subject: [PATCH 3/6] fix multi-dynamite error --- backend/bang/players.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/bang/players.py b/backend/bang/players.py index 7436c1d..9020d91 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -334,6 +334,7 @@ class Player: self.sio.emit('chat_message', room=self.game.name, data=f'_special_bart_cassidy|{self.name}') print(f'{self.name} Boom, -3 hp') + break else: self.game.next_player().equipment.append(self.equipment.pop(i)) self.game.next_player().notify_self() From 153a5177e1a509e3b80f240a596758981804a8f6 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sun, 6 Dec 2020 15:40:28 +0100 Subject: [PATCH 4/6] fix death and room still playing with bots --- backend/__init__.py | 3 ++- backend/bang/game.py | 13 +++++++++++-- backend/bang/players.py | 7 ++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/backend/__init__.py b/backend/__init__.py index 27b167c..dd38d44 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -130,7 +130,8 @@ def chat_message(sid, msg): 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: - ses.game.player_death(player=ses) + ses.lives = 0 + ses.notify_self() @sio.event def start_game(sid): diff --git a/backend/bang/game.py b/backend/bang/game.py index 32ea89f..f95349e 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -23,6 +23,7 @@ class Game: self.initial_players = 0 self.password = '' self.expansions = [] + self.shutting_down = False def notify_room(self): if len([p for p in self.players if p.character == None]) != 0: @@ -197,6 +198,7 @@ class Game: self.players[self.turn].play_turn() def next_turn(self): + if self.shutting_down: return if len(self.players) > 0: self.turn = (self.turn + 1) % len(self.players) self.play_turn() @@ -210,9 +212,16 @@ class Game: def handle_disconnect(self, player: players.Player): print(f'player {player.name} left the game {self.name}') - self.player_death(player=player, disconnected=True) - if len([p for p in self.players if not p.is_bot]) == 0: + if player in self.players: + 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: print(f'no players left in game {self.name}') + self.shutting_down = True + self.players = [] + self.dead_players = [] + self.deck = None return True else: return False diff --git a/backend/bang/players.py b/backend/bang/players.py index 9020d91..4c976bb 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -155,6 +155,10 @@ class Player: randrange(0, len(self.hand)))) if self.lives <= 0 and self.max_lives > 0: self.pending_action = PendingAction.WAIT + ser['hand'] = [] + ser['equipment'] = [] + self.sio.emit('self', room=self.sid, data=json.dumps( + ser, default=lambda o: o.__dict__)) self.game.player_death(self) elif not self.is_bot: self.sio.emit('self_vis', room=self.sid, data=json.dumps( @@ -169,6 +173,7 @@ class Player: self.game.notify_all() def bot_logic(self): + if self.game.shutting_down: return if self.pending_action != PendingAction.WAIT: eventlet.sleep(uniform(0.6, 1.5)) else: @@ -218,7 +223,7 @@ class Player: if not c.need_target: self.play_card(len(self.hand)+i) else: - _range = self.get_sight() if c.name == "Pepperbox" else self.hand[i].range + _range = self.get_sight() if c.name == "Pepperbox" else c.range others = [p for p in self.game.get_visible_players(self) if _range >= p['dist'] and not (isinstance(self.role, r.Vice) and p['is_sheriff'])] if len(others) == 0: continue From 6abd3bfffe3ef840dafa7ffb48f49abb0b6d2fb5 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sun, 6 Dec 2020 18:46:03 +0100 Subject: [PATCH 5/6] fix herb notify --- backend/bang/game.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/bang/game.py b/backend/bang/game.py index f95349e..ee5daf8 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -292,6 +292,7 @@ class Game: if len(herb) > 0: herb[0].hand.append(self.deck.draw()) herb[0].hand.append(self.deck.draw()) + herb[0].notify_self() if died_in_his_turn: self.next_turn() From c356917ec2242bdca210ca5b624efde4f3ceb7b1 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sun, 6 Dec 2020 19:29:40 +0100 Subject: [PATCH 6/6] fix bot wait and add commands --- backend/__init__.py | 35 +++++++++++++++++++++++------------ backend/bang/game.py | 2 ++ backend/bang/players.py | 2 +- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/backend/__init__.py b/backend/__init__.py index dd38d44..c25285c 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -119,19 +119,30 @@ def join_room(sid, room): @sio.event def chat_message(sid, msg): ses: Player = sio.get_session(sid) - sio.emit('chat_message', room=ses.game.name, data=f'[{ses.name}]: {msg}') - if '/addbot' in msg and not ses.game.started: - if len(msg.split()) > 1: - for _ in range(int(msg.split()[1])): - ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) + if len(msg) > 0: + if msg[0] == '/': + if '/addbot' in msg and not ses.game.started: + if len(msg.split()) > 1: + for _ in range(int(msg.split()[1])): + ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) + else: + ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) + 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: + ses.lives = 0 + ses.notify_self() + elif '/cancelgame' in msg and ses.game.started: + ses.game.reset() + elif '/gameinfo' in msg: + sio.emit('chat_message', room=sid, data=f'info: {ses.game.__dict__}') + elif '/meinfo' in msg: + sio.emit('chat_message', room=sid, data=f'info: {ses.__dict__}') + else: + sio.emit('chat_message', room=sid, data=f'{msg} COMMAND NOT FOUND') else: - ses.game.add_player(Player(f'AI_{random.randint(0,100)}', 'bot', sio, bot=True)) - 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: - ses.lives = 0 - ses.notify_self() + sio.emit('chat_message', room=ses.game.name, data=f'[{ses.name}]: {msg}') @sio.event def start_game(sid): diff --git a/backend/bang/game.py b/backend/bang/game.py index ee5daf8..c9df987 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -45,6 +45,8 @@ class Game: self.notify_room() def add_player(self, player: players.Player): + if player.is_bot and len(self.players) >= 8: + return if player in self.players or len(self.players) >= 10: return if len(self.players) > 7: diff --git a/backend/bang/players.py b/backend/bang/players.py index 4c976bb..6c33e36 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -174,7 +174,7 @@ class Player: def bot_logic(self): if self.game.shutting_down: return - if self.pending_action != PendingAction.WAIT: + if self.pending_action != None and self.pending_action != PendingAction.WAIT: eventlet.sleep(uniform(0.6, 1.5)) else: return