This commit is contained in:
Alberto Xamin 2020-12-05 17:11:27 +01:00
parent 4e41ceb343
commit 0ed906fc39
No known key found for this signature in database
GPG Key ID: 4F026F48309500A2
3 changed files with 90 additions and 14 deletions

View File

@ -120,6 +120,11 @@ def join_room(sid, room):
def chat_message(sid, msg): def chat_message(sid, msg):
ses: Player = sio.get_session(sid) ses: Player = sio.get_session(sid)
sio.emit('chat_message', room=ses.game.name, data=f'[{ses.name}]: {msg}') 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 @sio.event
def start_game(sid): def start_game(sid):

View File

@ -124,6 +124,7 @@ class Game:
if p != attacker: if p != attacker:
if p.get_banged(attacker=attacker): if p.get_banged(attacker=attacker):
self.waiting_for += 1 self.waiting_for += 1
p.notify_self()
if self.waiting_for == 0: if self.waiting_for == 0:
attacker.pending_action = players.PendingAction.PLAY attacker.pending_action = players.PendingAction.PLAY
attacker.notify_self() attacker.notify_self()
@ -137,23 +138,26 @@ class Game:
if p != attacker: if p != attacker:
if p.get_indians(attacker=attacker): if p.get_indians(attacker=attacker):
self.waiting_for += 1 self.waiting_for += 1
p.notify_self()
if self.waiting_for == 0: if self.waiting_for == 0:
attacker.pending_action = players.PendingAction.PLAY attacker.pending_action = players.PendingAction.PLAY
attacker.notify_self() attacker.notify_self()
def attack(self, attacker: players.Player, target_username:str, double:bool=False): 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.readyCount = 0
self.waiting_for = 1 self.waiting_for = 1
attacker.pending_action = players.PendingAction.WAIT attacker.pending_action = players.PendingAction.WAIT
attacker.notify_self() attacker.notify_self()
self.get_player_named(target_username).notify_self()
def duel(self, attacker: players.Player, target_username:str): 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.readyCount = 0
self.waiting_for = 1 self.waiting_for = 1
attacker.pending_action = players.PendingAction.WAIT attacker.pending_action = players.PendingAction.WAIT
attacker.notify_self() attacker.notify_self()
self.get_player_named(target_username).notify_self()
def emporio(self): def emporio(self):
self.available_cards = [self.deck.draw() for i in range(len(self.players))] 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): def handle_disconnect(self, player: players.Player):
print(f'player {player.name} left the game {self.name}') print(f'player {player.name} left the game {self.name}')
self.player_death(player=player, disconnected=True) 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}') print(f'no players left in game {self.name}')
return True return True
else: return False else: return False

View File

@ -1,6 +1,6 @@
from enum import IntEnum from enum import IntEnum
import json import json
from random import randrange from random import random, randrange, sample, uniform
import socketio import socketio
import bang.deck as deck import bang.deck as deck
import bang.roles as r import bang.roles as r
@ -8,6 +8,7 @@ import bang.cards as cs
import bang.expansions.dodge_city.cards as csd import bang.expansions.dodge_city.cards as csd
import bang.characters as chars import bang.characters as chars
import bang.expansions.dodge_city.characters as chd import bang.expansions.dodge_city.characters as chd
import eventlet
class PendingAction(IntEnum): class PendingAction(IntEnum):
PICK = 0 PICK = 0
@ -19,7 +20,7 @@ class PendingAction(IntEnum):
class Player: class Player:
def __init__(self, name, sid, sio): def __init__(self, name, sid, sio, bot=False):
import bang.game as g import bang.game as g
super().__init__() super().__init__()
self.name = name self.name = name
@ -47,6 +48,7 @@ class Player:
self.is_drawing = False self.is_drawing = False
self.mancato_needed = 0 self.mancato_needed = 0
self.molly_discarded_cards = 0 self.molly_discarded_cards = 0
self.is_bot = bot
def reset(self): def reset(self):
self.hand: cs.Card = [] self.hand: cs.Card = []
@ -108,8 +110,12 @@ class Player:
def set_available_character(self, available): def set_available_character(self, available):
self.available_characters = available self.available_characters = available
print(f'I {self.name} have to choose between {available}') print(f'I {self.name} have to choose between {available}')
self.sio.emit('characters', room=self.sid, data=json.dumps( if not self.is_bot:
available, default=lambda o: o.__dict__)) 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): def notify_card(self, player, card):
mess = { mess = {
@ -151,12 +157,75 @@ class Player:
if self.lives <= 0 and self.max_lives > 0: if self.lives <= 0 and self.max_lives > 0:
self.pending_action = PendingAction.WAIT self.pending_action = PendingAction.WAIT
self.game.player_death(self) self.game.player_death(self)
else: elif not self.is_bot:
self.sio.emit('self_vis', room=self.sid, data=json.dumps( self.sio.emit('self_vis', room=self.sid, data=json.dumps(
self.game.get_visible_players(self), default=lambda o: o.__dict__)) 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__)) 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): def play_turn(self):
if self.lives == 0: if self.lives == 0:
@ -405,7 +474,6 @@ class Player:
if isinstance(self.character, chd.ElenaFuente): if isinstance(self.character, chd.ElenaFuente):
self.expected_response = self.game.deck.all_cards_str self.expected_response = self.game.deck.all_cards_str
self.on_failed_response_cb = self.take_damage_response self.on_failed_response_cb = self.take_damage_response
self.notify_self()
return True return True
def get_indians(self, attacker): def get_indians(self, attacker):
@ -420,7 +488,6 @@ class Player:
self.expected_response = [cs.Bang(0, 0).name] self.expected_response = [cs.Bang(0, 0).name]
self.event_type = 'indians' self.event_type = 'indians'
self.on_failed_response_cb = self.take_damage_response self.on_failed_response_cb = self.take_damage_response
self.notify_self()
return True return True
def get_dueled(self, attacker): def get_dueled(self, attacker):
@ -435,7 +502,6 @@ class Player:
self.expected_response = [cs.Bang(0, 0).name] self.expected_response = [cs.Bang(0, 0).name]
self.event_type = 'duel' self.event_type = 'duel'
self.on_failed_response_cb = self.take_damage_response self.on_failed_response_cb = self.take_damage_response
self.notify_self()
return True return True
def take_damage_response(self): def take_damage_response(self):
@ -467,6 +533,7 @@ class Player:
self.attacker = None self.attacker = None
def respond(self, hand_index): def respond(self, hand_index):
if self.pending_action != PendingAction.RESPOND: return
self.pending_action = PendingAction.WAIT self.pending_action = PendingAction.WAIT
if hand_index != -1 and ( if hand_index != -1 and (
((hand_index < len(self.hand) and self.hand[hand_index].name in self.expected_response)) or ((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: if len(self.hand) > self.max_lives and not forced:
print( print(
f"I {self.name} have to many cards in my hand and I can't end the turn") 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 self.is_my_turn = False
for i in range(len(self.equipment)): for i in range(len(self.equipment)):
if self.equipment[i].usable_next_turn and not self.equipment[i].can_be_used_now: if self.equipment[i].usable_next_turn and not self.equipment[i].can_be_used_now: