""" Text-Based Fighting Game Project started: 4/2/24 Last updated: 5/15/24 MY AWESOME WEBSITE: https://junes-awesome-website-10031969.codehs.me/index.html (cmd+click) Welcome to Text-Based Fighting Game! This is a little personal project I work on when I should be doing incomplete work but choose to do literally anything else instead. Please read the User's Guide before playing! **USER'S GUIDE** --WHAT EACH MOVE DOES-- 1. Punch - a low DMG move that's Garunteed to hit; deals 20 DMG normally, and 40 DMG on crit. 2. Kick - a higher DMG move that has a decent chance to miss; deaLs 35 DMG normally, and 50 on crit. 3. Defend - allows you to brace yourself for the oncoming attack; has a chance to heal HP and remove status effects. 4. Explosion - a magic move that costs 20 MP to cast; deals DMG to all enemies; deals 35 DMG normally, and 50 DMG on crit. --ENEMIES-- Fire Mage - A low HP magic-focused enemy. It can light the player on fire for 3 turns. Necromancer - A stronger enemy; it raises an undead army to do massive DMG all at once! --BOSSES-- Ice Guardian - An ancient guardian constructed with the intention to stop any trespassers. Has a moveset based on ice. --AS A REMINDER-- This game is still under heavy development, and do expect things to break every now and then. I do try to keep the stable build less buggy, but don't be surprised if something isn't working. --IF YOU ENCOUNTER A BUG-- Please let me know at orc1843@g.coppellisd.com, and include a screenshot of the error or copy the text from the console. Thanks for playing, and good luck! (If you're looking for the changelog, it's on the website!) """ print("TEXT-BASED FIGHTING GAME") print("version: 0.4-S") start = input("\nPress enter to start! ") print("\n\n") import random import time #game status vars turn_taken = False #holds if it's the player's turn or not playing = True #holds if the game is continuing or not; used to check if turns should continue global amt_of_turns #holds how many turns have passed amt_of_turns = 0 #debug vars global is_debug_active is_debug_active = False global GM_enabled #toggles god mode GM_enabled = False #health vars global p_hp #holds player HP p_hp = 100 global p_mp p_mp = 20 global turns_stuck turns_stuck = 0 global e_hp #holds enemy HP e_hp = 100 global e_type #holds enemy type global e_num #holds amount of enemies in the current encounter e_num = 1 #BOOKMARK1 global chosen_enem #holds which enemy is selected; is global for printing enemy health remaining global e_dmg_dealt #holds enemy damage amount #status check vars global is_defending #holds if player is defending is_defending = False global will_crit #holds if the next attack will be a critical hit will_crit = False global turns_on_fire #holds how many turns the player is on fire turns_on_fire = 0 global burn_cooldown burn_cooldown = 0 global is_boss #holds if the next encounter will be a boss is_boss = False move_inputted = False #holds if the player input a valid move #enemy status vars global e_slots #holds what enemies are in the slots e_slots = [] global fire_intensity #holds the multiplier for fire damage fire_intensity = 1 global undead_count #holds how many undead the enemy has summoned undead_count = 0 global freeze_cooldown #holds cooldown for b_freeze() freeze_cooldown = 0 global phys_atk_guard phys_atk_guard = False global turns_poisoned turns_poisoned = 0 global poison_strength poison_strength = 1 global explosion_unlocked explosion_unlocked = False global enemies_defeated enemies_defeated = 0 #BOOKMARK2 def lvl_check(): #ran when enemy is defeated global e_num global enemies_defeated global explosion_unlocked if(enemies_defeated == 1): e_num = 2 explosion_unlocked = True print("\nExplosion spell unlocked!\nAt the cost of 20 MP, deal 35 DMG to all enemies!") if(enemies_defeated >= 3): e_num = 3 def punch(): #basic attack: always hits global dmg_dealt global will_crit global phys_atk_guard global turns_poisoned dmg_dealt = 0 if(GM_enabled): print("**GM ENABLED** THE GRAND SLAM SMILES UPON YE") else: print("Punch chosen!") time.sleep(1) if(turns_poisoned > 0): print("The poison reduced the DMG dealt by 5!") dmg_dealt -= 5 if(GM_enabled == True): print("THE ENEMIES COLLAPSE FROM THE HOLY MIGHT OF THE GRAND SLAM") for i in range(e_num): e_hp[i] = 0 print("ALL SHALL KNEEL BEFORE THE GRAND SLAM") dmg_dealt = 0 return if(phys_atk_guard == False): if(will_crit == True): dmg_dealt = 40 print("CRITIAL HIT! Dealt " + str(dmg_dealt) + " damage!") else: dmg_dealt = 20 print("Punch landed! dealt " + str(dmg_dealt) + " damage!") else: print("The enemy was unaffected by the attack!") return(dmg_dealt) def kick(): #higher damage, lower chance of hitting global dmg_dealt global will_crit global turns_poisoned dmg_dealt = 0 print("\nKick chosen!") time.sleep(1) num_rolled = random.randint(1, 6) if(num_rolled <= 4): if(turns_poisoned > 0): print("The poison reduced the DMG dealt by 15!") dmg_dealt -= 15 if(will_crit): dmg_dealt += 50 print("CRITICAL HIT! Dealt " + str(dmg_dealt) + " damage!") else: dmg_dealt += 35 print("Kick landed! dealt " + str(dmg_dealt) + " damage!") else: print("Kick missed! dealt 0 damage!") return(dmg_dealt) def defend(): #heals player and reduces enemy attack dmg by a small amount global p_hp global turns_on_fire global turns_poisoned print("\nDefend chosen!") time.sleep(1) is_defending = True print("You're prepared for the enemy's attack!") time.sleep(1) print("Attempting to heal!") time.sleep(1) num_rolled =random.randint(1,6) if(num_rolled <= 5): #5/6 chance to heal player and recover from statuses print("Healed successfully!") if(turns_on_fire > 1): print("The healing extinguished the flames!") turns_on_fire = 0 fire_intensity = 1 if(turns_poisoned > 0): print("The healing rid your body of the poison!") turns_poisoned = 0 p_hp += 40 print("You are now at " + str(p_hp) + " HP!") else: print("Healing failed!") return(is_defending) def explosion(): global dmg_dealt global p_mp global e_num global e_slots global e_hp global will_crit global phys_atk_guard print("\nExplosion chosen!") time.sleep(1) p_mp -= 20 print("-20 MP! You are now at: " + str(p_mp) + " MP!") time.sleep(1) if(phys_atk_guard == True): print("The explosion broke the guard!") phys_atk_guard = False time.sleep(1) if(will_crit): print("CRITICAL HIT!") dmg_dealt = 50 else: dmg_dealt = 35 for i in range(e_num): e_hp[i] -= dmg_dealt print("Dealt " + str(dmg_dealt) + " DMG to all enemies!") #enemy functions def select_e_type(): #chooses which type of enemy appears global total_e_hp global e_hp global e_num global e_slots global enemies_defeated global is_boss #list of enemies: #Fire Mage (Burn, Melee) #Necromancer (Melee, Raise Dead, Horde Attack) #Cavern Spider (Melee, Poison) (Multi only: web wrap) #(multi only) Medic (Melee, Heal) #potential future enemies: #(multi only) Knight (Crush, Taunt) #potential boss enemies #Guardian of Ice (freeze, crush, ice wall) #Guardian of Fire (burn, smoke wall, flame guard) e_slots = ["empty", "empty", "empty"] e_hp = [0, 0, 0] if(enemies_defeated == 6): is_boss = True if(is_boss == False): for i in range(e_num): e_selected = random.randint(1,12) if(e_selected <= 3): e_type = "Fire Mage" e_slots[i] = "Fire Mage" e_hp[i] = 100 elif(e_selected <= 6): e_type = "Necromancer" e_slots[i] = "Necromancer" e_hp[i] = 120 elif(e_selected <= 9): e_type = "Cave Spider" e_slots[i] = "Cave Spider" e_hp[i] = 80 elif(e_selected <= 12 and e_num > 1): e_type = "Medic" e_slots[i] = "Medic" e_hp[i] = 80 else: e_type = "Cave Spider" e_slots[i] = "Cave Spider" e_hp[i] = 80 else: e_type = "Ice Gaurdian" e_slots[0] = "Ice Guardian" e_slots[1] = "empty" e_slots[2] = "empty" e_num = 1 e_hp[0] = 200 return(e_slots) #enemy attacks def e_melee(): global is_defending global e_dmg_dealt global p_hp print("\nThe enemy goes for a melee attack!") if(is_defending): e_dmg_dealt = 8 print("Defended the hit! Reduced DMG taken!") print("The melee hit! Dealt 8 DMG to player!") p_hp -= e_dmg_dealt is_defending = False time.sleep(2) else: e_dmg_dealt = 14 print("The melee hit! Dealt 14 DMG to player!") p_hp -= e_dmg_dealt time.sleep(2) def e_burn(): #applies DoT that can be removed by healing global turns_on_fire global burn_cooldown global fire_intensity global e_dmg_dealt print("\nThe enemy is preparing a spell!") if(turns_on_fire > 0): time.sleep(1) num_rolled = random.randint(1,10) if(e_num > 1): #if just more than 1 enemy, have chance to fail num_rolled = random.randint(1,10) if(num_rolled <= 7): #if check passes, light player ablaze print("The enemy casted fireball!") if(fire_intensity > 0): #if player wasnt alr on fire print("The fire grows in intensity!\nYou now take double fire damage!") turns_on_fire = 2 fire_intensity = 2 e_dmg_dealt = 4 burn_cooldown = 2 else: print("You are now on fire for the next 2 turns!") turns_on_fire = 2 e_dmg_dealt = 4 burn_cooldown = 2 time.sleep(2) else: print("But it failed!") e_dmg_dealt = 0 else: print("The enemy casted fireball!") print("You are now on fire for the next 2 turns!") turns_on_fire = 2 #lights player on fire for 2 turns e_dmg_dealt = 4 time.sleep(2) burn_cooldown = 4 return(e_dmg_dealt) def raise_dead(): #NECROMANCER: adds +1 undead; boosts horde attack dmg and base atk #NOTE: add chance for spell to fail ONLY IN MULTI-ENEMY ENCOUNTERS global undead_count print("\nThe enemy is preparing a spell!") time.sleep(1) print("The enemy raised the undead!") undead_count += 1 print("Current enemy undead raised: " + str(undead_count)) return(undead_count) def horde_atk(): #NECROMANCER: Uses all undead in a large attack; dmg scales with undead_count global undead_count global e_dmg_dealt global is_defending print("\nThe enemy is preparing their horde for an attack!") time.sleep(1) time.sleep(1) if(is_defending): print("The horde charges you, but you were defending!") e_dmg_dealt = 6 + undead_count else: print("The horde charges you!") e_dmg_dealt = 10 + (undead_count * 4) time.sleep(1) print("The horde dealt " + str(e_dmg_dealt) + " damage with " + str(undead_count) + " undead!") time.sleep(1) print("All the undead withered away...") undead_count = 0 time.sleep(2) return(e_dmg_dealt) def e_poison(): global e_dmg_dealt global turns_poisoned global poison_strength print("The enemy is preparing an attack!") time.sleep(1) print("The enemy bit you with poisonous fangs! Dealt 6 DMG!") e_dmg_dealt = 6 turns_poisoned += 2 print("You are now poisoned for " + str(turns_poisoned) + " turns!") return(e_dmg_dealt) def e_web_wrap(): global turns_stuck global e_dmg_dealt print("The enemy is preparing an attack!") time.sleep(1) print("The enemy trapped you in a web! You are unable to move!") turns_stuck += 1 def e_heal(): global e_hp global e_slots print("The enemy is preparing a spell!") time.sleep(1) for i in range(len(e_hp)): if(e_slots[i] != "Medic"): e_hp[i] += 30 print("Healed all other enemies by 30 HP!") #boss attacks def b_freeze(): global turns_stuck global freeze_cooldown print("The Ice Guardian is preparing a spell!") time.sleep(1) #freeze player for 1 turn; have 3 turn cooldown turns_stuck = 1 freeze_cooldown = 3 print("The Ice Guardian froze you!") time.sleep(1) return(turns_stuck) def b_crush(): global dmg_dealt print("The Ice Guardian raises their weapon!") if(is_defending): dmg_dealt = 15 print("Defended the hit! Reduced DMG taken!") else: dmg_dealt = 30 print("The Ice Guardian crushes you, dealing " + str(dmg_dealt) + " DMG!") return(dmg_dealt) def b_ice_wall(): global phys_atk_guard print("The Ice Guardian is preparing a spell!") time.sleep(1) phys_atk_guard = True print("The Ice Guardian raises a thick wall of ice, guarding against physical attacks!") time.sleep(1) def death_message(): print("\n\n\n\nYOU DIED\n\n\n\n") playing = False #beginning of game very_normal_variable = "GRANDSLAM" if(start == very_normal_variable): print("DEBUG MODE ENABLED!") enable_GM = input("Enable God Mode? (y/n) ") if(enable_GM == "y"): GM_enabled = True if(GM_enabled == True): print("**GM ENABLED**") p_hp = 999999 #*technically* you could still die. good luck doing that though. e_slots = select_e_type() for i in range(len(e_slots)): if(e_slots[i] != "empty"): print(str(e_slots[i]) + " approaches!"); while(playing == True): if(p_hp <= 0): death_message() break while(turn_taken == False): #finish/continue code if(e_hp[0] <= 0 and e_hp[1] <= 0 and e_hp[2] <= 0): time.sleep(2) if(is_boss): print("\n\nBoss slain! Congratulations!") is_boss = False else: print("\n\nAll enemies slain!") enemies_defeated += e_num print("Total enemies slain: " + str(enemies_defeated)) lvl_check() if(p_hp <= 50): print("You found a health potion on the ground.\n Healed 60 HP and removed all status effects!") p_hp += 60 turns_poisoned = 0 turns_on_fire = 0 turns_stuck = 0 print("you are now at " + str(p_hp) + " HP!") print("\n\nFinding new enemies…\n") time.sleep(2) e_slots = select_e_type() for i in range(len(e_slots)): if(e_slots[i] != "empty"): print(str(e_slots[i]) + " approaches!"); time.sleep(0.5) time.sleep(0.5) amt_of_turns = 0 move_inputted = False #player chooses move via 4 options time.sleep(1) amt_of_turns += 1 print("\n\n~~TURN " + str(amt_of_turns) + "~~\n\n") print("--PLAYER TURN--") if(p_mp < 20): p_mp += 10 print("\nRecovered 10 MP!") print("[" +str(p_mp) + " MP remaining]\n") if(turns_poisoned > 0): print("The poison weakened you…\nNext attack will do reduced DMG!") print("Poisoned for: " + str(turns_poisoned) + " turns!") if(turns_stuck == 0): while(move_inputted == False): print("Choose a move:") if(GM_enabled): print("1. CALL UPON THE MIGHT OF THE DENNY'S GRAND SLAM") elif(phys_atk_guard == True): print("1. punch (Will have no effect!)") print("2. kick (will have no effect!)") else: print("1. punch") print("2. kick") print("3. defend") if(explosion_unlocked and p_mp >= 20): print("4. explosion (-20 MP)") elif(explosion_unlocked and p_mp < 20): print("4. explosion (NOT ENOUGH MP)") try: chosen_move = int(input("Enter a number here: ")) except ValueError: print("\nInvalid input! Try again.\n") chosen_move = 0 continue if(chosen_move > 4 or chosen_move < 1): print("\nNot within valid range! Try again.\n") time.sleep(1) chosen_move = 0 continue elif(chosen_move == 4 and p_mp < 20): print("Not enough MP! Try again.\n") time.sleep(1) continue else: move_inputted = True num_rolled = random.randint(1,10) if(num_rolled >= 8): will_crit = True if(chosen_move < 3 and GM_enabled == False): #player chooses enemy using e_slots if(e_num > 1): print("\nChoose an enemy:") for i in range(len(e_slots)): #for each slot if(e_slots[i] != "empty"): #if the slot isn't empty if(e_hp[i] < 1): print(str(i+1) + ": " + str(e_slots[i]) + ", DEAD") else: print(str(i+1) + ": " + str(e_slots[i]) + ", " + str(e_hp[i]) + " HP") #print slot num + enemy in slot try: chosen_enem = int(input("Enter a number here: ")) except ValueError: print("\nInvalid input! Try again.") chosen_enem = 0 continue if(chosen_enem > e_num or chosen_enem <= 0): print("\nOutside of range! Try again.") amt_of_turns -= 1 continue if(e_hp[chosen_enem-1] <= 0): print("That enemy is already dead! Try again.") continue enem_selected = e_slots[chosen_enem-1] print("\nEnemy selected: " + enem_selected) print("\n--------------------------------------\n") else: chosen_enem = 1 #if there's only 1 enemy, skip over selection if(turns_on_fire >= 1): p_hp -= (6 * fire_intensity) print("\nYou're on fire! The burns dealt " + str(6 * fire_intensity) + " damage!") turns_on_fire -= 1 if(p_hp <= 0): death_message() print("You are now at: " + str(p_hp) + " HP!") time.sleep(1) if(chosen_move == 1): dmg_dealt = punch() if(GM_enabled == False): e_hp[chosen_enem-1] -= dmg_dealt #included here since it isn't returned by defend elif(chosen_move == 2): dmg_dealt = kick() e_hp[chosen_enem-1] -= int(dmg_dealt) #see comment above elif(chosen_move == 3): is_defending = defend() elif(chosen_move == 4): if(explosion_unlocked): explosion() else: print("Outside of range! Try again.") continue else: print("\nYou try to move, but you're stuck in place!\n") time.sleep(2) turns_stuck = 0 if(e_hp[0] > 0 or e_hp[1] > 0 or e_hp[2] > 0): #if any enemy has hp above 0 turn_taken = True #as long as the enemy isn't dead, make sure to give it a turn #enemy turn while(turn_taken == True): will_crit = False time.sleep(2) print("\n--------------------------------------\n") print("\n--ENEMY TURN--") if(is_boss == False): #if enemy isn't a boss for i in range(e_num): #for each enemy if(e_hp[i] > 1): #if enemy is alive if(e_slots[i] == "Fire Mage"): #if that enemy is a fire mage num_rolled = random.randint(1,6) if(num_rolled <= 2): e_melee() elif(burn_cooldown <= 0): e_burn() else: e_melee() burn_cooldown -= 1 elif(e_slots[i] == "Necromancer"): num_rolled = random.randint(1,9) if(num_rolled <= 5): raise_dead() elif(num_rolled <= 9 and undead_count >= 1): p_hp -= horde_atk() else: raise_dead() elif(e_slots[i] == "Cave Spider"): num_rolled = random.randint(1,9) if(num_rolled <= 3): e_poison() elif(num_rolled <= 6 and e_num > 1): #multi exclusive bc it'd b annoying in single-enemy encounters e_web_wrap else: e_melee() elif(e_slots[i] == "Medic"): num_rolled = random.randint(1,6) if(num_rolled <= 2): e_heal() else: e_melee() else: if(e_slots[0] == "Ice Guardian"): num_rolled = random.randint(1,9) if(num_rolled <= 3 and freeze_cooldown == 0): b_freeze() #(makes player immobile for a turn) elif(num_rolled <= 6): p_hp -= b_crush() #(does a large amt of DMG to player) elif(num_rolled <= 9): b_ice_wall() #(gives the enemy a shield that absorbs phys dmg) print("\n--------------------------------------\n") print("\nPlayer HP remaining: " + str(p_hp)) for i in range(e_num): #print remaining hp of all enemies if(e_hp[i] <= 0): print("Enemy " + str(i+1) + " HP remaining: DEAD") else: print("Enemy " + str(i+1) + " HP remaining: " + str(e_hp[i])) print("\n--------------------------------------") time.sleep(1) turn_taken = False move_inputted = False is_defending = False