bots
This commit is contained in:
parent
4e41ceb343
commit
0ed906fc39
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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}')
|
||||||
|
if not self.is_bot:
|
||||||
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:
|
||||||
|
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__))
|
||||||
|
if not self.is_bot:
|
||||||
self.sio.emit('self', room=self.sid, data=json.dumps(
|
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:
|
||||||
|
Loading…
Reference in New Issue
Block a user