Jump to content

KaladinsSenseOfHumourSpren

Members
  • Posts

    3052
  • Joined

  • Last visited

  • Days Won

    5

Everything posted by KaladinsSenseOfHumourSpren

  1. "Why? Even if these Ephrussians haven't taken Alpha Centauri yet, it'll take four years so send a message to that system, and it's the closest."
  2. Wow this is beyond my Python skill Is this fully automatic? Like does it need the GM to say what actions players are taking?
  3. No there was also the Mindscape, way back before Before any of my clones existed Edit:
  4. Used to say I'd make the storm clouds cry for you Used to say I'd capture wind and sky for you
  5. Starseeker, New Hallandren, New Hallandren Garrison "Nothing else major happened," Starseeker said. "Kai had gotten Ebon some... voidlight, and he left shortly after. When you showed up, Lux left too." Crimson remained silent.
  6. There used to be a Mindscape in BftS a long time ago But it got destroyed
  7. I've only taken a cursory look, but this looks really good! You know you can do this, right? import random import os def clear_screen(): os.system('cls' if os.name == 'nt' else 'clear') class Player: def __init__(self, name, alignment, role=None, radiant_target=None): self.name = name self.alignment = alignment self.role = role self.is_alive = True self.is_roleblocked = False self.protected = False self.role_action_type = None self.role_action_target = None self.faction_action_type = None self.faction_action_target = None self.radiant_target = radiant_target self.spren_prot_used = False def __repr__(self): status = "" if self.is_alive else "[DEAD] " return f"{status}{self.name} ({self.alignment} {self.role if self.role else ''})" # --- ABILITY CONFIGURATION --- # Defines exactly which roles can do which actions ROLE_ABILITIES = { 'Direform': ['block'], 'Stormform': ['redirect'], 'Envoyform': ['decrease'], 'Inspiring': ['increase', 'block_conv'], 'Heroic': ['protect'], 'Spren': ['protect_radiant'], 'Shardbearer': ['kill'], 'Discerning': ['scan'], 'Sneaky': ['sneaky'], 'Willful': [] # Passive role } # --- GLOBAL GAME STATE --- conversion_charges = 2 def display_graveyard(players): dead_players = [f"{p.name} ({p.alignment} {p.role})" for p in players if not p.is_alive] print("\n=== GRAVEYARD (ELIMINATED) ===") if dead_players: for entry in dead_players: print(f"• {entry}") else: print("No one has died yet.") print("==============================") def simulate_cycle(players): global conversion_charges alive_at_start = [p.name for p in players if p.is_alive] for p in players: p.is_roleblocked = False p.protected = False # 1. Stormform Redirect for p in [x for x in players if x.role == 'Stormform' and not x.is_roleblocked and x.is_alive]: if p.role_action_type == 'redirect' and p.role_action_target: storm_target = p.role_action_target actors_to_redirect = [a for a in players if (a.role_action_target == storm_target or a.faction_action_target == storm_target) and a != p] for actor in actors_to_redirect: new_dest = random.choice([x for x in players if x != storm_target and x.is_alive]) if actor.role_action_target == storm_target: actor.role_action_target = new_dest if actor.faction_action_target == storm_target: actor.faction_action_target = new_dest print(f"STORM: {p.name} redirected {actor.name} to {new_dest.name}!") # 2. Direform Roleblock for p in [x for x in players if x.role == 'Direform' and not x.is_roleblocked and x.is_alive]: if p.role_action_type == 'block' and p.role_action_target: p.role_action_target.is_roleblocked = True print(f"BLOCK: {p.name} (Direform) roleblocked {p.role_action_target.name}") # 4. Protections (Heroic & Spren) protected_list = [p.role_action_target for p in players if p.role == 'Heroic' and not p.is_roleblocked and p.is_alive] for p in [x for x in players if x.role == 'Spren' and x.is_alive and not x.is_roleblocked]: if p.role_action_type == 'protect_radiant' and not p.spren_prot_used and p.role_action_target == p.radiant_target: protected_list.append(p.radiant_target) p.spren_prot_used = True print(f"SUCCESS: {p.name} (Spren) protected {p.radiant_target.name}!") # 5. Conversion (Regals) conv_blocked = [p.role_action_target for p in players if p.role == 'Inspiring' and p.role_action_type == 'block_conv' and not p.is_roleblocked and p.is_alive] for p in [x for x in players if x.alignment == 'Regal' and x.faction_action_type == 'convert' and not x.is_roleblocked and x.is_alive]: if conversion_charges <= 0: continue target = p.faction_action_target if target and target.alignment.capitalize() == 'Singer' and target not in conv_blocked and target.role != 'Willful': target.alignment = 'Regal' conversion_charges -= 1 print(f"CONVERSION: {target.name} has joined the Regals!") # 6. Kills targets_to_die = [] for p in [x for x in players if (x.faction_action_type == 'kill' or x.role == 'Shardbearer') and not x.is_roleblocked and x.is_alive]: target = p.faction_action_target if p.alignment == 'Regal' else p.role_action_target if target and target not in protected_list: targets_to_die.append(target) for target in list(set(targets_to_die)): target.is_alive = False # 7. Spren Death Logic for s in [x for x in players if x.role == 'Spren' and x.is_alive]: if s.radiant_target and not s.radiant_target.is_alive: s.is_alive = False print(f"LOSS: {s.name}'s Radiant ({s.radiant_target.name}) died. {s.name} is eliminated.") print("\n--- NIGHT DEATH REPORT ---") deaths = [n for n in alive_at_start if not next(pl for pl in players if pl.name == n).is_alive] if deaths: for d in deaths: print(f"DIED: {d}") else: print("No one died tonight.") display_graveyard(players) return players def simulate_day_phase(players, votes): tally = {p.name: 0 for p in players if p.is_alive} penalized = [p.role_action_target.name for p in players if p.role == 'Envoyform' and p.role_action_type == 'decrease' and not p.is_roleblocked and p.is_alive and p.role_action_target] buffed = [p.role_action_target.name for p in players if p.role == 'Inspiring' and p.role_action_type == 'increase' and not p.is_roleblocked and p.is_alive and p.role_action_target] for v_name, t_name in votes.items(): if t_name in tally: weight = 1 if v_name in penalized: weight = 0 elif v_name in buffed: weight = 2 tally[t_name] += weight if tally: victim_name = max(tally, key=tally.get) if tally[victim_name] > 0: victim = next(p for p in players if p.name == victim_name) victim.is_alive = False print(f"\n--- DAY PHASE: {victim_name} voted out with {tally[victim_name]} votes ---") display_graveyard(players) return players def check_winner(players): living = [p for p in players if p.is_alive] singers = [p for p in living if p.alignment == "Singer"] regals = [p for p in living if p.alignment == "Regal"] shard = [p for p in living if p.role == "Shardbearer"] if shard and len(shard) >= (len(singers) + len(regals)): return "SHARDBEARER" if not regals and not shard: return "SINGERS" if len(regals) > len(singers) and not shard: return "REGALS" return None # --- SETUP --- players = [ Player("Rudy", "Regal", "Direform"), Player("Lucias", "Singer", "Discerning"), Player("Jolene", "Singer", "Heroic"), Player("Mariana", "Singer", "Willful"), Player("Aiden", "Shardbearer", "Shardbearer"), Player("Bailey", "Singer", "Spren", radiant_target="Vivienne"), Player("Kai", "Singer", "Inspiring"), Player("Tadashi", "Regal", "Stormform"), Player("Abraham", "Singer", "Sneaky"), Player("Neil", "Regal", "Envoyform"), ] p = {player.name: player for player in players} p['Bailey'].radiant_target = p['Vivienne'] # --- MAIN GAME LOOP --- cycle = 1 while True: clear_screen() print(f"=== CYCLE {cycle} ===") # 1. REGAL TEAM ACTION (Kill/Convert) regals_alive = [r for r in players if r.alignment == 'Regal' and r.is_alive] if regals_alive: print("\n--- REGAL FACTION ACTION (TEAM) ---") while True: t_act = input("Action (kill/convert) or blank: ").strip().lower() if not t_act or t_act in ['kill', 'convert']: break print("Invalid faction action!") if t_act: t_target_name = input("Target Name: ").strip() t_target = p.get(t_target_name) for r in regals_alive: r.faction_action_type, r.faction_action_target = t_act, t_target # 2. INDIVIDUAL ROLE ACTIONS (RESTRICTED) for name, actor in p.items(): if not actor.is_alive: continue allowed = ROLE_ABILITIES.get(actor.role, []) if not allowed: print(f"\n{name} ({actor.role}) has no active abilities.") continue print(f"\n{name} ({actor.role}) Turn:") print(f"Available abilities: {', '.join(allowed)}") while True: act = input("Enter ability or blank to skip: ").strip().lower() if not act or act in allowed: break print(f"Invalid! {name} can only use: {', '.join(allowed)}") if act: target_name = input(f"Target for {name}: ").strip() actor.role_action_type = act actor.role_action_target = p.get(target_name) clear_screen() players = simulate_cycle(players) winner = check_winner(players) if winner: print(f"\n*** {winner} WIN! ***") break input("\nPress Enter to begin Voting Phase...") clear_screen() print("=== VOTING PHASE ===") votes = {} for n, v in p.items(): if v.is_alive: vote = input(f"{n}, vote for someone: ").strip() votes[n] = vote players = simulate_day_phase(players, {k: v for k, v in votes.items() if v in p}) winner = check_winner(players) if winner: print(f"\n*** {winner} WIN! ***") break cycle += 1 for player in players: player.role_action_type = player.role_action_target = None player.faction_action_type = player.faction_action_target = None input("\nPress Enter for next cycle...") There's a code option next to the spoiler box one. You know, I might do something like this for the Tyrean ruleset Who need spreadsheets when you have code
  8. I can't help but wonder What your world must be If we're like each other If I have your strength in me
  9. Sandy nodded. "If you need more, just say so. We'll have a sophon following you; we'll know, no matter where you are. Well, there are some places we can't contact you from, but those are really rare."
  10. Yep Reminding me of a board game, One Deck Dungeon
  11. "How did they communicate with you?"
  12. For twenty years I've dreamed of how I'd greet you ohhh And now you're here I can't find the words
  13. Renamed nodded. "I do not know of anything that had happened here after Named left. Is there anything important I should know?" Thank you!
  14. Ah okay. What's going to be like, the player's main goal?
  15. Starseeker and Crimson, New Hallandren, New Hallandren Garrison Crimson reluctantly showed himself. He remained small, however, and stood on Starseeker's shoulder. Both spren and Radiant said nothing.
×
×
  • Create New...