Begin writing ai interfacing

master
En Yi 2019-06-03 15:45:33 +01:00
parent ce520a63cf
commit 4cfda05982
2 changed files with 75 additions and 5 deletions

44
ai_comp/ai.py 100644
View File

@ -0,0 +1,44 @@
"""
This file contains the AI used in the game, which is called
during decision making procedure.
All AI procedure should ending up producing a valid option,
never an invalid one.
AI also possess information on the table to facilitate decision making.
AI should output the card play as int, and the actual Card is played in the Player class
AI possesses the table knowledge and the hand
"""
import random
class randomAI:
def __init__(self, table_status, player=None):
self.player = player
self.table_status = table_status
def connect_to_player(self, player):
self.player = player
def get_valid_plays(self):
pass
def request_reshuffle(self):
if random.randint(0, 1):
return True
return False
def make_a_bid(self):
if self.player:
current_round_bid = self.table_status["bid"] // 10
current_suit_bid = self.table_status["bid"] % 10
gen_bid = random.randint(1, 7)*10 + random.randint(1, 5)
if gen_bid > self.table_status["bid"]:
if current_suit_bid == 5:
return (current_round_bid+1)*10 + 1
else:
return self.table_status["bid"]+1
def call_partner(self):
pass
def make_a_play(self, sub_state):
pass

View File

@ -5,7 +5,7 @@ import random
import copy import copy
import time import time
from signalslot import Signal from signalslot import Signal
from ai_comp import ai
from enum import Enum from enum import Enum
NUM_OF_PLAYERS = 4 NUM_OF_PLAYERS = 4
@ -114,6 +114,8 @@ class Table:
deck_reveal=cards.DeckReveal.HIDE_ALL)) deck_reveal=cards.DeckReveal.HIDE_ALL))
self.players[i].connect_to_table(self.table_status) self.players[i].connect_to_table(self.table_status)
self.players[3].add_ai(ai.randomAI(self.table_status))
playfield_margins = 10 playfield_margins = 10
margins_with_w_deck = w_deck + playfield_margins margins_with_w_deck = w_deck + playfield_margins
playfield_x = margins_with_w_deck playfield_x = margins_with_w_deck
@ -212,7 +214,7 @@ class Table:
for i, player in enumerate(self.players): for i, player in enumerate(self.players):
print("Player {0:d}: {1:d}".format(i, player.get_card_points())) print("Player {0:d}: {1:d}".format(i, player.get_card_points()))
if player.get_card_points() < 4: if player.get_card_points() < 4:
print("Starting Player: {0:d}".format(i)) print("Player: {0:d}".format(i))
return player.make_decision(self.game_state, 0) return player.make_decision(self.game_state, 0)
def start_bidding(self): def start_bidding(self):
@ -343,7 +345,6 @@ class Table:
self.update_table.emit() self.update_table.emit()
def reset_game(self): def reset_game(self):
# TODO: Reset the game
for player in self.players: for player in self.players:
print(len(player.cards)) print(len(player.cards))
while not player.is_empty(): while not player.is_empty():
@ -366,6 +367,9 @@ class Player(cards.Deck):
- Attempt to play a card - Attempt to play a card
- Play the validate move - Play the validate move
The player also implements method to play from the terminal
if it is not a bot.
""" """
def __init__(self, *args, ai_component=None, **kwargs): def __init__(self, *args, ai_component=None, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -377,23 +381,36 @@ class Player(cards.Deck):
def connect_to_table(self, table): def connect_to_table(self, table):
self._table_status = table self._table_status = table
def add_ai(self, ai_comp):
self.AI = ai_comp
ai_comp.connect_to_player(self)
def make_decision(self, game_state, sub_state): def make_decision(self, game_state, sub_state):
""" """
The player will need to make a decision depending on the game state and sub-state The player will need to make a decision depending on the game state and sub-state
:param game_state: Current game state :param game_state: Current game state
:param sub_state: Sub-state which affects the output for the current game state :param sub_state: Sub-state which affects the output for the current game state
:return: For Bidding: Either a bid or a partner call :return: For Bidding: Either a bid or a partner call, int
For Playing: A Card For Playing: A Card
For Reshuffle: bool, True to reshuffle, False otherwise
""" """
if game_state == GameState.POINT_CHECK: if game_state == GameState.POINT_CHECK:
if self.AI:
self.AI.request_reshuffle()
if input("Low points hand detected! Reshuffle?").lower() == 'y': if input("Low points hand detected! Reshuffle?").lower() == 'y':
return True return self.request_reshuffle()
if game_state == GameState.BIDDING: if game_state == GameState.BIDDING:
if sub_state == 0: if sub_state == 0:
if self.AI:
return self.AI.make_a_bid()
return self.make_a_bid() return self.make_a_bid()
else: else:
#if self.AI:
# pass
return self.call_partner() return self.call_partner()
if game_state == GameState.PLAYING: if game_state == GameState.PLAYING:
#if self.AI:
# pass
return self.make_a_play(sub_state) return self.make_a_play(sub_state)
def make_a_bid(self): def make_a_bid(self):
@ -402,6 +419,7 @@ class Player(cards.Deck):
:return: A valid bid number :return: A valid bid number
""" """
while True: while True:
# TODO: Make a more natural input parsing
bid = input("Please input a bid in the format 'number' + 'suit' \n" bid = input("Please input a bid in the format 'number' + 'suit' \n"
"To pass, enter nothing. \n" "To pass, enter nothing. \n"
"i.e. 42 is 4 Diamond, 65 is 6 No Trump \n" "i.e. 42 is 4 Diamond, 65 is 6 No Trump \n"
@ -434,6 +452,7 @@ class Player(cards.Deck):
""" """
current_card_values = self.get_deck_values() current_card_values = self.get_deck_values()
while True: while True:
# TODO: Make a more natural input parsing
partner = input("Please call your partner card. Enter suit number + card number\n" partner = input("Please call your partner card. Enter suit number + card number\n"
"i.e 412 is Spade Queen, 108 is Clubs 8, 314 is Hearts Ace\n") "i.e 412 is Spade Queen, 108 is Clubs 8, 314 is Hearts Ace\n")
try: try:
@ -453,6 +472,7 @@ class Player(cards.Deck):
:return: A valid Card :return: A valid Card
""" """
while True: while True:
# TODO: Make a more natural input parsing
play = input("Please play a card. Enter suit number + card number\n" play = input("Please play a card. Enter suit number + card number\n"
"i.e 412 is Spade Queen, 108 is Clubs 8, 314 is Hearts Ace\n") "i.e 412 is Spade Queen, 108 is Clubs 8, 314 is Hearts Ace\n")
if play: if play:
@ -472,6 +492,12 @@ class Player(cards.Deck):
pass pass
def check_for_valid_plays(self, card, leading): def check_for_valid_plays(self, card, leading):
"""
Check if the card played is valid
:param card: int
:param leading: bool
:return:
"""
if not self.check_card_in(card): if not self.check_card_in(card):
return False return False
card_suit = cards.get_card_suit(card) card_suit = cards.get_card_suit(card)