make a plantuml: import random

class Card:
    def __init__(self, name, cost=0, is_sustainable=False):
        self.name = name
        self.cost = cost
        self.rotated = False
        self.is_sustainable = is_sustainable
        self.damage = 0
        self.severe_damage = 0

    def rotate(self):
        if not self.rotated:
            self.rotated = True
            return True
        return False

    def ready(self):
        self.rotated = False

    def heal(self, amount=None):
        if amount is None:
            self.damage = 0
        else:
            self.damage = max(0, self.damage - amount)

    def heal_severe(self):
        if self.severe_damage > 0:
            self.severe_damage -= 1
        else:
            self.rotated = False

    def inflict_damage(self, amount):
        self.damage += amount

    def inflict_severe_damage(self, amount):
        self.severe_damage += amount

    def is_neutralized(self):
        return self.damage >= self.get_max_ability()

    def get_max_ability(self):
        # Placeholder for actual ability logic
        return 3


class ConflictCard:
    def __init__(self, name, target=None):
        self.name = name
        self.target = target
        self.face_down = True

    def reveal(self):
        self.face_down = False


class AgendaCard(Card):
    def __init__(self, name, cost=0, is_major=False, hidden=False):
        super().__init__(name, cost)
        self.is_major = is_major
        self.hidden = hidden

    def can_be_sponsored(self):
        # Placeholder for actual logic
        return True

    def reveal(self):
        self.hidden = False
        print(f"Agenda '{self.name}' is now revealed.")


class MercenaryCard(Card):
    def __init__(self, name, cost=0):
        super().__init__(name, cost)
        self.bids = {}

    def bid(self, player, amount):
        if player in self.bids:
            self.bids[player] += amount
        else:
            self.bids[player] = amount

    def highest_bidder(self):
        if self.bids:
            return max(self.bids, key=self.bids.get)
        return None


class Player:
    def __init__(self, name, influence_rating, cards=[], ambassador=None):
        self.name = name
        self.influence_rating = influence_rating
        self.current_influence = influence_rating
        self.cards = cards
        self.ambassador = ambassador
        self.initiative = 0
        self.conflict_card = None
        self.passed = False
        self.agenda = None
        self.mercenaries = []
        self.conflicts_initiated = []
        self.draw_deck = self.initialize_draw_deck()
        self.inner_circle = []  # Assuming inner_circle needs initialization as an empty list

    def initialize_draw_deck(self):
        # Placeholder method to create an initial draw deck
        return [Card(f"DrawCard{i}", cost=random.randint(1, 5)) for i in range(10)]

    def ready_cards(self):
        for card in self.cards:
            if card.is_sustainable and card.rotated:
                continue
            card.ready()

    def restore_influence(self):
        self.current_influence = self.influence_rating

    def determine_initiative(self, players):
        players.sort(key=lambda p: p.influence_rating)
        for i, player in enumerate(players):
            player.initiative = i
            print(f"{player.name} initiative: {player.initiative}")

    def declare_conflict(self, conflict_card):
        if self.conflict_card is None:
            self.conflict_card = conflict_card
            self.conflicts_initiated.append(conflict_card)
            print(f"{self.name} declares a conflict: {conflict_card.name}")

    def perform_action(self, action_type, *args):
        if action_type == "rotate":
            self.use_card_effect(*args)
        elif action_type == "play_event":
            self.play_event(*args)
        elif action_type == "build_influence":
            self.build_influence(*args)
        elif action_type == "sponsor":
            self.sponsor(*args)
        elif action_type == "promote":
            self.promote(*args)
        elif action_type == "replace":
            self.replace_character(*args)
        elif action_type == "support":
            self.support_conflict(*args)
        elif action_type == "oppose":
            self.oppose_conflict(*args)
        elif action_type == "attack":
            self.attack(*args)
        elif action_type == "heal":
            self.heal_character(*args)
        elif action_type == "repair":
            self.repair_location_or_fleet(*args)
        elif action_type == "lead_fleet":
            self.lead_fleet(*args)
        elif action_type == "discard_agenda":
            self.discard_agenda()
        elif action_type == "play_agenda":
            self.play_agenda(*args)
        elif action_type == "reveal_agenda":
            self.reveal_agenda()
        elif action_type == "replace_agenda":
            self.replace_agenda(*args)
        elif action_type == "bid_mercenary":
            self.bid_mercenary(*args)
        elif action_type == "pass":
            self.pass_action()
        else:
            print(f"Unknown action type: {action_type}")

    def use_card_effect(self, card):
        if card in self.cards and card.rotate():
            print(f"{self.name} uses effect of {card.name}")

    def play_event(self, event_card):
        print(f"{self.name} plays event card: {event_card.name}")

    def build_influence(self):
        if self.influence_rating <= 9:
            self.influence_rating += 1
            self.current_influence += 1
            print(f"{self.name} builds influence. New influence rating: {self.influence_rating}")

    def sponsor(self, new_card):
        if self.current_influence >= new_card.cost:
            self.current_influence -= new_card.cost
            self.cards.append(new_card)
            print(f"{self.name} sponsors new card: {new_card.name}")
        else:
            print(f"{self.name} cannot afford to sponsor {new_card.name}")

    def promote(self, supporting_card):
        if supporting_card in self.cards:
            print(f"{self.name} promotes {supporting_card.name} to Inner Circle")

    def replace_character(self, old_card, new_card):
        if old_card in self.cards:
            self.cards.remove(old_card)
            self.cards.append(new_card)
            new_card.ready()
            print(f"{self.name} replaces {old_card.name} with {new_card.name}")

    def support_conflict(self, conflict, supporting_card):
        if supporting_card in self.cards and supporting_card.rotate():
            print(f"{self.name} supports conflict {conflict.name} with {supporting_card.name}")

    def oppose_conflict(self, conflict, opposing_card):
        if opposing_card in self.cards and opposing_card.rotate():
            print(f"{self.name} opposes conflict {conflict.name} with {opposing_card.name}")

    def attack(self, target_card, attacker):
        if attacker in self.cards and attacker.rotate():
            target_card.inflict_damage(attacker.get_max_ability())
            print(f"{self.name} attacks {target_card.name} with {attacker.name}")

    def heal_character(self, card):
        if card in self.cards and card.rotate():
            if card.is_neutralized():
                card.heal_severe()
            else:
                card.heal()
            print(f"{self.name} heals {card.name}")

    def repair_location_or_fleet(self, card):
        if card in self.cards and card.rotate():
            repair_cost = card.damage
            if self.current_influence >= repair_cost:
                self.current_influence -= repair_cost
                card.heal(card.damage)
                print(f"{self.name} repairs {card.name}")
            else:
                print(f"{self.name} cannot afford to repair {card.name}")

    def lead_fleet(self, fleet, leader):
        if leader in self.cards and fleet in self.cards and leader.rotate():
            print(f"{self.name} leads {fleet.name} with {leader.name}")

    def discard_agenda(self):
        if self.agenda and not self.agenda.is_major:
            print(f"{self.name} discards agenda: {self.agenda.name}")
            self.agenda = None
        else:
            print(f"{self.name} cannot discard a major agenda or has no agenda.")

    def play_agenda(self, new_agenda, character):
        if character in self.cards and character.rotate():
            self.agenda = new_agenda
            if new_agenda.hidden:
                print(f"{self.name} plays a hidden agenda.")
            else:
                print(f"{self.name} plays agenda: {new_agenda.name}")

    def reveal_agenda(self):
        if self.agenda and self.agenda.hidden:
            self.agenda.reveal()
            if not self.agenda.can_be_sponsored():
                print(f"{self.name}'s agenda {self.agenda.name} cannot be sponsored and is discarded.")
                self.agenda = None
        else:
            print(f"{self.name} has no hidden agenda to reveal.")

    def replace_agenda(self, new_agenda):
        if self.agenda and self.agenda.is_major and new_agenda.is_major:
            print(f"{self.name} replaces agenda {self.agenda.name} with {new_agenda.name}")
            self.agenda = new_agenda
        else:
            print(f"{self.name} can only replace a major agenda with another major agenda.")

    def bid_mercenary(self, mercenary, amount):
        if self.current_influence >= amount:
            self.current_influence -= amount
            mercenary.bid(self, amount)
            print(f"{self.name} bids {amount} influence on mercenary {mercenary.name}")
        else:
            print(f"{self.name} does not have enough influence to bid on mercenary {mercenary.name}")

    def pass_action(self):
        self.passed = True
        print(f"{self.name} passes their action.")


class Game:
    def __init__(self, players):
        self.players = players
        self.mercenaries = []
        self.conflicts = []

    def ready_round(self):
        print("Ready Round…")
        for player in self.players:
            player.ready_cards()
            player.restore_influence()
        print("All cards are ready, and influence is restored.")

    def conflict_round(self):
        print("Conflict Round…")
        self.declare_conflicts()
        self.reveal_conflicts()

    def declare_conflicts(self):
        print("Declare Conflicts…")
        for player in sorted(self.players, key=lambda p: p.initiative):
            if player.conflicts_initiated:
                conflict_card = player.conflicts_initiated.pop(0)
                self.conflicts.append(conflict_card)
                print(f"{player.name} declares a conflict: {conflict_card.name}")

    def reveal_conflicts(self):
        print("Reveal and Initiate Conflicts…")
        for conflict in self.conflicts:
            conflict.reveal()
            print(f"Conflict revealed: {conflict.name}")

    def action_round(self):
        print("Action Round…")
        for player in self.players:
            player.passed = False
        while not all(player.passed for player in self.players):
            for player in sorted(self.players, key=lambda p: p.initiative):
                if not player.passed:
                    action_choice = self.choose_action(player)
                    if action_choice:
                        player.perform_action(*action_choice)
                    else:
                        player.pass_action()

        # Heal Ambassador if all Inner Circle cards are rotated
        for player in self.players:
            if all(card.rotated for card in player.cards):
                if player.ambassador:
                    player.ambassador.damage = 0
                    player.ambassador.severe_damage = 0
                    player.ambassador.ready()
                    print(f"{player.name}'s ambassador is fully healed.")

    def choose_action(self, player):
        actions = ["rotate", "play_event", "build_influence", "sponsor", "promote", "replace", "support", "oppose",
                   "attack", "heal", "repair", "lead_fleet", "discard_agenda", "play_agenda", "reveal_agenda",
                   "replace_agenda", "bid_mercenary", "pass"]
        action_type = random.choice(actions)

        if action_type == "rotate" and player.cards:
            return action_type, player.cards[0]
        elif action_type == "play_event" and player.cards:
            return action_type, player.cards[0]
        elif action_type == "build_influence":
            return action_type,
        elif action_type == "sponsor" and player.current_influence >= 3:
            return action_type, Card("New Supporting Card", cost=3)  # Example cost
        elif action_type == "promote" and player.cards:
            return action_type, player.cards[0]
        elif action_type == "replace" and len(player.cards) >= 2:
            return action_type, player.cards[0], Card("Replacement Card", cost=5)  # Example
        elif action_type == "support" and self.conflicts and player.cards:
            return action_type, self.conflicts[0], player.cards[0]
        elif action_type == "oppose" and self.conflicts and player.cards:
            return action_type, self.conflicts[0], player.cards[0]
        elif action_type == "attack" and player.cards:
            for opponent in self.players:
                if opponent != player and opponent.cards:
                    return action_type, opponent.cards[0], player.cards[0]
        elif action_type == "heal" and player.cards:
            return action_type, player.cards[0]
        elif action_type == "repair" and player.cards:
            return action_type, player.cards[0]
        elif action_type == "lead_fleet" and len(player.cards) >= 2:
            return action_type, player.cards[0], player.cards[1]  # Placeholder fleet and leader
        elif action_type == "discard_agenda" and player.agenda:
            return action_type,
        elif action_type == "play_agenda" and player.cards:
            return action_type, AgendaCard("New Agenda", cost=2), player.cards[0]  # Example cost and character
        elif action_type == "reveal_agenda" and player.agenda and player.agenda.hidden:
            return action_type,
        elif action_type == "replace_agenda":
            return (action_type,
                    AgendaCard("Replacement Agenda", cost=3, is_major=True))  # Example for major agenda replacement
        elif action_type == "bid_mercenary" and self.mercenaries:
            return action_type, self.mercenaries[0], 1  # Example bid amount
        else:
            return "pass",

    def resolution_round(self):
        print("Resolution Round…")
        for conflict in self.conflicts:  # Resolve conflicts in the order they were declared
            self.resolve_conflict(conflict)

    def resolve_conflict(self, conflict):
        print(f"Resolving conflict: {conflict.name}")
        # Placeholder for resolving conflict logic
        support = 0
        opposition = 0
        for player in self.players:
            for card in player.cards:
                if card.rotated:
                    support += card.get_max_ability()  # Placeholder for actual logic
                else:
                    opposition += card.get_max_ability()  # Placeholder for actual logic

        if support > opposition:
            print(f"Conflict {conflict.name} succeeded with support {support} vs. opposition {opposition}.")
            # Apply success effects
        else:
            print(f"Conflict {conflict.name} failed with support {support} vs. opposition {opposition}.")
            # Apply failure effects

        self.play_aftermath()

        # Discard conflict and aftermath cards
        self.conflicts.remove(conflict)
        print(f"Conflict {conflict.name} is discarded.")

    def play_aftermath(self):
        print("Playing aftermath cards…")
        for player in sorted(self.players, key=lambda p: p.initiative):
            # Placeholder for playing aftermath logic
            print(f"{player.name} plays aftermath card.")

    def draw_round(self):
        print("Draw Round…")

        # Step 1: Discarding neutralized supporting cards
        print("Step 1: Discarding neutralized supporting cards")
        for player in sorted(self.players, key=lambda p: p.initiative):
            neutralized_cards = [card for card in player.cards if card.is_neutralized() and not isinstance(card, Card)]
            for card in neutralized_cards:
                player.cards.remove(card)
                print(f"{player.name} discards neutralized card: {card.name}")

        # Step 2: Discarding cards from hand
        print("Step 2: Discarding cards from hand")
        for player in sorted(self.players, key=lambda p: p.initiative):
            # Allowing every player to discard as many cards as they wish
            # For simplicity, let's assume they discard any card
            for card in player.cards[:]:
                player.cards.remove(card)
                print(f"{player.name} discards card: {card.name}")

        # Step 3: Drawing cards
        print("Step 3: Drawing cards")
        for player in sorted(self.players, key=lambda p: p.initiative):
            if player.cards:
                if not player.draw_deck:
                    if hasattr(player, 'inner_circle') and player.inner_circle:
                        ic_card = player.inner_circle.pop()
                        print(f"{player.name} must discard Inner Circle card: {ic_card.name} due to empty draw deck.")
                    else:
                        print(
                            f"{player.name} cannot draw and has no Inner Circle cards left (game lost scenario not fully implemented).")
                        continue
                else:
                    new_card = player.draw_deck.pop()
                    player.cards.append(new_card)
                    print(f"{player.name} draws card: {new_card.name}")

            for _ in range(player.current_influence // 3):
                if not player.draw_deck:
                    if hasattr(player, 'inner_circle') and player.inner_circle:
                        ic_card = player.inner_circle.pop()
                        print(f"{player.name} must discard Inner Circle card: {ic_card.name} due to empty draw deck.")
                    else:
                        print(
                            f"{player.name} cannot draw and has no Inner Circle cards left (game lost scenario not fully implemented).")
                        break
                else:
                    new_card = player.draw_deck.pop()
                    player.cards.append(new_card)
                    print(f"{player.name} drawsanother card: {new_card.name}")

        # Step 4: Victory Check
        self.victory_check()

        # Step 5: End of Turn
        self.end_of_turn_cleanup()

    def end_of_turn_cleanup(self):
        print("End of turn cleanup…")
        # Placeholder for any end of turn cleanup logic
        pass

    def process_mercenaries(self):
        for mercenary in self.mercenaries:
            highest_bidder = mercenary.highest_bidder()
            if highest_bidder:
                highest_bidder.mercenaries.append(mercenary)
                print(f"{highest_bidder.name} wins control of mercenary {mercenary.name}")
            mercenary.bids = {}  # Reset bids for the next turn

    def victory_check(self):
        print("Victory Check…")
        for player in sorted(self.players, key=lambda p: p.current_influence, reverse=True):
            # Placeholder for a proper power check and determining a winner
            if player.current_influence >= 20:
                others = [p for p in self.players if p != player]
                if all(player.current_influence > other.current_influence for other in others):
                    print(f"{player.name} wins with a Standard Victory by having 20 or more power!")
                    return True

        return False

    def play_turn(self):
        print("New Turn Begins…")
        self.ready_round()
        for player in self.players:
            player.determine_initiative(self.players)
        self.conflict_round()
        self.action_round()
        self.resolution_round()
        self.draw_round()
        if self.victory_check():
            print("We have a winner!")
            return False
        print("Turn Ends.\n")
        return True


def main():
    # Example game setup
    players = [
        Player("Alice", influence_rating=10, cards=[Card("Card1", cost=2), Card("Card2", cost=3)]),
        Player("Bob", influence_rating=8, cards=[Card("Card3", cost=1), Card("Card4", cost=4)]),
        Player("Eve", influence_rating=12, cards=[Card("Card5", cost=5), Card("Card6", cost=6)])
    ]

    game = Game(players)

    # Loop through turns until a player wins
    while game.play_turn():
        pass


if __name__ == "__main__":
    main()