Skip to content

Commit

Permalink
Added potions to the message bus(playable ones!).
Browse files Browse the repository at this point in the history
  • Loading branch information
Vesper-arch committed Mar 31, 2024
1 parent 3274053 commit f03c16a
Show file tree
Hide file tree
Showing 6 changed files with 380 additions and 127 deletions.
14 changes: 13 additions & 1 deletion definitions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import copy
from enum import StrEnum, auto


# Convienience classes so I don't have to deepcopy every time I want to get a card.
class DeepCopyList(list):
def __getitem__(self, index):
item = super().__getitem__(index)
return copy.deepcopy(item)

class DeepCopyTuple(tuple):
def __getitem__(self, index):
item = super().__getitem__(index)
return copy.deepcopy(item)

class CombatTier(StrEnum):
NORMAL = 'Normal'
ELITE = 'Elite'
Expand Down Expand Up @@ -56,7 +68,7 @@ class CardCategory(StrEnum):
POTION = 'Potion'
RELIC = 'Relic'

class EnemyState(StrEnum):
class State(StrEnum):
ALIVE = 'alive'
DEAD = 'dead'
ESCAPED = 'escaped'
Expand Down
41 changes: 25 additions & 16 deletions entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import items
from ansi_tags import ansiprint
from definitions import CardType, EnemyState, TargetType
from definitions import CardType, State, TargetType
from helper import active_enemies, ei, view
from message_bus_tools import Card, Message, Registerable, Relic, bus

Expand Down Expand Up @@ -38,6 +38,7 @@ def __init__(self, health: int, block: int, max_energy: int, deck: list[Card], p
self.name: str = "Ironclad"
self.player_class: str = "Ironclad"
self.in_combat = False
self.state = State.ALIVE
self.floors = 1
self.fresh_effects: list[str] = [] # Shows what effects were applied after the player's turn
self.max_health: int = health
Expand Down Expand Up @@ -133,7 +134,7 @@ def use_card(self, card, exhaust, pile, target: "Enemy"=None) -> None:
return
if card.target == TargetType.SINGLE:
card.apply(origin=self, target=target)
elif card.target == TargetType.AREA:
elif card.target in (TargetType.AREA, TargetType.ANY):
card.apply(origin=self, enemies=active_enemies)
elif card.target == TargetType.YOURSELF:
card.apply(origin=self)
Expand Down Expand Up @@ -161,28 +162,28 @@ def use_card(self, card, exhaust, pile, target: "Enemy"=None) -> None:
sleep(0.5)
view.clear()

def draw_cards(self, middle_of_turn: bool, draw_cards: int = 0):
def draw_cards(self, middle_of_turn: bool=True, cards: int = 0):
"""Draws [draw_cards] cards."""
if draw_cards == 0:
draw_cards = self.draw_strength
if cards == 0:
cards = self.draw_strength
while True:
self.discard_pile.extend(self.hand)
self.hand.clear()
if self.debuffs["No Draw"] is True:
print("You can't draw any more cards")
break
if middle_of_turn is False:
draw_cards += self.buffs["Draw Up"]
if len(player.draw_pile) < draw_cards:
cards += self.buffs["Draw Up"]
if len(player.draw_pile) < cards:
player.draw_pile.extend(random.sample(player.discard_pile, len(player.discard_pile)))
player.discard_pile = []
ansiprint("<bold>Discard pile shuffled into draw pile.</bold>")
self.hand.extend(player.draw_pile[-draw_cards:])
self.hand.extend(player.draw_pile[-cards:])
# Removes those cards
player.draw_pile = player.draw_pile[:-draw_cards]
player.draw_pile = player.draw_pile[:-cards]
for card in self.hand:
card.register(bus=bus)
print(f"Drew {draw_cards} cards.")
print(f"Drew {cards} cards.")
# bus.publish(Message.ON_DRAW, (pl))
break

Expand Down Expand Up @@ -242,7 +243,7 @@ def card_actions(self, subject_card: dict, action: str, card_pool: list[dict] =
ansiprint(f"{new_card['Name']} | <yellow>{new_card['Info']}</yellow>")
return new_card

def move_card(self, card, move_to, from_location, cost_energy, shuffle=False):
def move_card(self, card, move_to, from_location, cost_energy=False, shuffle=False):
if cost_energy is True:
self.energy -= max(card.energy_cost, 0)
from_location.remove(card)
Expand Down Expand Up @@ -286,6 +287,14 @@ def take_sourceless_dmg(self, dmg):

def die(self):
view.clear()
self.health = max(self.health, 0)
if items.FairyInABottle() in self.potions:
try:
potion_index = self.potions.index(items.FairyInABottle())
except ValueError:
potion_index = -1
player.health_actions(math.floor(player.max_health * self.potions[potion_index].hp_percent), "Heal")
return
ansiprint("<red>You Died</red>")
input("Press enter > ")
sys.exit()
Expand Down Expand Up @@ -345,7 +354,7 @@ def __init__(self, health_range: list, block: int, name: str, powers: dict = Non
self.past_moves = ["place"] * 3
self.intent: str = ""
self.next_move: list[tuple[str, str, tuple] | tuple[str, tuple]] = ""
self.state = EnemyState.ALIVE
self.state = State.ALIVE
self.buffs = ei.init_effects("Enemy Buffs") | powers
self.debuffs = ei.init_effects("Enemy Debuffs")
self.stolen_gold = 0
Expand Down Expand Up @@ -455,7 +464,7 @@ def misc_move(self):
sleep(0.6)
if func_name == "Cowardly":
ansiprint("<italic>Hehe. Thanks for the money.<italic>")
self.state = EnemyState.ESCAPED
self.state = State.ESCAPED
ansiprint(f"<italic><red>{self.name} has escaped</red></italic>")
elif func_name == "Sleeping":
sleeptalk = parameters[0]
Expand Down Expand Up @@ -508,7 +517,7 @@ def die(self):
Dies.
"""
print(f"{self.name} has died.")
self.state = EnemyState.DEAD
self.state = State.DEAD

def debuff_and_buff_check(self):
"""
Expand Down Expand Up @@ -588,7 +597,7 @@ def summon(self, enemy, amount: int, random_enemy: bool):
def callback(self, message, data):
if message == Message.START_OF_TURN:
ansiprint(f"{self.name}'s current state: {self.state}")
if self.state == EnemyState.ALIVE:
if self.state == State.ALIVE:
ansiprint(f"<underline><bold>{self.name}</bold></underline>:")
if "Block" not in self.intent: # Checks the last move(its intent hasn't been updated yet) used to see if the enemy Blocked last turn
if self.buffs["Barricade"] is False:
Expand All @@ -600,7 +609,7 @@ def callback(self, message, data):
print()
self.set_intent()
elif message == Message.END_OF_TURN:
if self.state == EnemyState.ALIVE:
if self.state == State.ALIVE:
self.execute_move()
# Needs to be expanded at some point
elif message == Message.ON_DEATH_OR_ESCAPE:
Expand Down
36 changes: 21 additions & 15 deletions game.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import game_map
import items
from ansi_tags import ansiprint
from definitions import CombatTier, EncounterType, EnemyState
from definitions import CombatTier, EncounterType, State, TargetType
from enemy_catalog import (
create_act1_boss,
create_act1_elites,
Expand Down Expand Up @@ -57,7 +57,7 @@ def __init__(self, tier: CombatTier, player: Player, game_map, all_enemies: list
self.tier = tier
self.player = player
self.all_enemies = all_enemies if all_enemies else []
self.active_enemies = [enemy for enemy in self.all_enemies if enemy.state == EnemyState.ALIVE]
self.active_enemies = [enemy for enemy in self.all_enemies if enemy.state == State.ALIVE]
self.previous_enemy_states = ()
self.death_messages = []
self.turn = 1
Expand All @@ -72,8 +72,8 @@ def combat(self, current_map) -> None:
while True:
self.update_death_messages()
self.previous_enemy_states = tuple(enemy.state for enemy in self.all_enemies)
self.active_enemies = [enemy for enemy in self.all_enemies if enemy.state == EnemyState.ALIVE] # Updates the list
if all((enemy.state == EnemyState.DEAD for enemy in self.all_enemies)):
self.active_enemies = [enemy for enemy in self.all_enemies if enemy.state == State.ALIVE] # Updates the list
if all((enemy.state == State.DEAD for enemy in self.all_enemies)):
self.end_combat(killed_enemies=True)
break

Expand All @@ -91,7 +91,7 @@ def combat(self, current_map) -> None:
),
"s": lambda: view.view_piles(player.discard_pile, end=True),
"x": lambda: view.view_piles(player.exhaust_pile, end=True),
"p": play_potion,
"p": self.play_potion,
"f": lambda: ei.full_view(player, self.active_enemies),
"m": lambda: view.view_map(current_map),
}
Expand All @@ -112,6 +112,8 @@ def combat(self, current_map) -> None:
continue
sleep(1)
view.clear()
if player.state == State.ESCAPED:
self.end_combat(self, escaped=True)
bus.publish(Message.END_OF_TURN, data=None) # So far I don't need to have anything passed for data
self.turn += 1

Expand All @@ -126,7 +128,6 @@ def end_combat(self, killed_enemies=False, escaped=False, robbed=False):
else:
player.potion_dropchance += 10
gen.card_rewards(self.tier, True, self.player, items.cards)
sleep(1.5)
view.clear()
elif escaped is True:
print("Escaped...")
Expand Down Expand Up @@ -165,7 +166,7 @@ def start_combat(self) -> list[Enemy]:
enemy.register(bus=bus)

bus.publish(Message.START_OF_COMBAT, (self.tier, self.active_enemies, player))
self.active_enemies = [enemy for enemy in self.all_enemies if enemy.state == EnemyState.ALIVE]
self.active_enemies = [enemy for enemy in self.all_enemies if enemy.state == State.ALIVE]
self.previous_enemy_states = tuple(enemy.state for enemy in self.all_enemies)

def select_target(self):
Expand Down Expand Up @@ -212,6 +213,19 @@ def update_death_messages(self):
if self.previous_enemy_states[i] != current_states[i]:
self.death_messages.append(current_states[i])

def play_potion(self):
if len(player.potions) == 0:
ansiprint("<red>You have no potions.</red>")
return
chosen_potion = view.list_input("Choose a potion to play", player.potions, view.view_potions, lambda potion: potion.playable, "That potion is not playable.")
potion = player.potions.pop(chosen_potion)
if potion.target == TargetType.YOURSELF:
potion.apply(player)
elif potion.target == TargetType.SINGLE:
target = self.select_target()
potion.apply(player, self.active_enemies[target])
elif potion.target in (TargetType.AREA, TargetType.ANY):
potion.apply(player, self.active_enemies)

def rest_site():
"""
Expand Down Expand Up @@ -340,11 +354,3 @@ def unknown(game_map) -> None:
chosen_event = choose_event(game_map)
chosen_event()


def play_potion():
if len(player.potions) == 0:
ansiprint("<red>You have no potions.</red>")
return
view.view_potions(player.potions, player.max_potions)
input("This is currently not implemented. Press enter to leave > ")

Loading

0 comments on commit f03c16a

Please sign in to comment.