Discuss Scratch

ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

PyRPG (working title)

I'm working on making a text adventure in python (using a base by imfh that I expanded apon) using my own base.

It's not even close to done, but I'm excited about it

However, my spaghetti code is probably not very efficient, so please give feedback on how i could improve this.

note: the map is not complete, and is mostly for testing
#PyRPG(v3): Beta 0.2
import os
import random
from difflib import SequenceMatcher
from rich import print as rprint
from rich import align
version = "0.2 (BETA)"
#blue   = inventory
#red    = error/invalid command
#orange = combat?
#green  = outside-game messages (changelog, clearing, quit prompt)
class Room:
    """
    Represents a room.
    Attributes
    ----------
    name : str
        the room name (used in dev mode)
    passive : str
        the description that displays after each turn
    detail : str
        the description that displays when you type "look"
    directions : list
        a list of directions a player in the room can move
    items : dict
        a list of item objects
    ents : dict
        a list of entity objects
    Methods
    -------
    ritem(itemname):
        removes an item by name
    rent(entname):
        removes an entity by name
    str(room):
        converts a room into a string listing attributes
    """
    def __init__(room, name, descriptions, directions, items, ents):
        room.name = name
        room.passive = descriptions[0]
        room.detail = descriptions[1]
        room.directions = directions
        room.items = items
        room.ents = ents
    def __str__(room):
        tmpstr = f"{room.name} "
        for item in room.items:
            tmpstr += f"D There is a {item.name}.\n"
        for ent in room.ents:
            tmpstr += f"D A {ent.name} is standing here.\n"
        return tmpstr
    def ritem(room, itemname):
        room.items.pop(itemname)
    def rent(room, entname):
        room.items.pop(entname)
class Item:
    """
    Represents an item.
    Attributes
    ----------
    name : str
        the item name
    short : str
        short description of the item
    long : str
        detailed description of the item
    stats : dict
        a list of stats
        structure is as follows:
        {
            "dmg": 10, #damage of the item
            "critdmg": 15, #damage of the item when it hits something critically
            "sellprice": 30, #sell value
            "buyprice": 35, #buy value
            "atkeffect": randomdmg #executes a function when you use the item to attack
        }
    weapon : bool
        False -> not a weapon
        True -> a weapon
        defaults to False
    """
    def __init__(item, name, descriptions, stats, weapon=False):
        item.name = name
        item.d = descriptions
        item.short = descriptions[0] #brief
        item.long = descriptions[1] #detail
        item.stats = stats
        item.weapon = weapon
class Ent:
    """
    Represents an entity.
    Attributes
    ----------
    name : str
        the entity name
    inv : dict
        the inventory of the entity. consists of a dict of Item objects
    stats : dict
        the stats of the entity
        structure is as follows:
        {
            "hp": 10, #current health
            "maxhp": 10, #full health
            "dmg": 5, #its damage in combat
            "acc": 2, #entity will hit (1/acc)*100 percent of the time
            "crit": 5, #entity will crit (1/crit)*100 percent of the time
            "critdmg": 7, #damage of a critical hit
        }
    hostilemode : int
        whether an entity will attack unprovoked
        2: the entity will attack when the player enters the room it's in
        1: the entity won't fight unprovoked
        0: the entity won't fight
    """
    def __init__(ent, name, inv, stats, hostilemode=1):
        ent.name = name
        ent.inv = inv
        ent.stats = stats
        ent.hostilemode = hostilemode
    def giveitem(ent, player, itemname):
        player["inv"][itemname] = ent.inv[itemname]
        ent.inv[itemname].pop()
    def damage(ent, amount):
        if ent.stats["hp"] - amount < 0:
            ent.stats["hp"] = 0
        else:
            ent.stats["hp"] -= amount
    def heal(ent, amount):
        if ent.stats["hp"] + amount > ent.stats["maxhp"]:
            ent.stats["hp"] = ent.stats["maxhp"]
        else:
            ent.stats["hp"] += amount
    def attack(ent):
        stats = ent.stats
        hitper = (1/stats["acc"])*100
        critper = (1/stats["crit"])*100
        if bool(random.choices([1, 0], weights=[hitper, 100-hitper])[0]):
            if bool(random.choices([1, 0], weights=[critper, 100-critper])[0]):
                rprint(f"!![bold red]The {ent.name} critically hit you, doing {stats['critdmg']} damage!")
                return stats["critdmg"]
            else:
                rprint(f"! [bold]The {ent.name} hit you, doing {stats['dmg']} damage!")
                return stats["dmg"]
        else:
            rprint(f"  [italic]The {ent.name} missed!")
            return 0
title = """      :::::::::  :::   ::: :::::::::  :::::::::   ::::::::
     :+:    :+: :+:   :+: :+:    :+: :+:    :+: :+:    :+:
    +:+    +:+  +:+ +:+  +:+    +:+ +:+    +:+ +:+
   +#++:++#+    +#++:   +#++:++#:  +#++:++#+  :#:
  +#+           +#+    +#+    +#+ +#+        +#+   +#+#
 #+#           #+#    #+#    #+# #+#        #+#    #+#
###           ###    ###    ### ###         ########       """
versions = {
    "0.1 (BETA)": """[b green]0.1[/]\n - first version of game\n - added look, help, movement commands, grab/drop, inventory, inspect, clear, quit\n - added first map (two rooms with an item in one)\n""",
    "0.2 (BETA)": """[green][b]0.2[/]\n[i dim]The Feedback and Consistency Update[/][/green]\n - added changelog\n - fixed typos\n - consistent capitalization\n - 'inventory' now tells you when your inventory is empty\n - 'grab' and 'drop' now warn you when the item isn't in the room or your inventory, respectively.\n"""
}
commands = {
    "help": ["print list of commands and descriptions.", "[b]=HELP=[/]\nPrints a list of command and simple descriptions.\n[b]USAGE[/]\nhelp - print list of commands and descriptions\n    command (opt) - print detailed description of the specified command."],
    "help <command>": ["print detailed explanation of <command>."],
    "quit": ["quit game.", "[b]=QUIT=[/]\nExits the game.\n[b]USAGE[/]\nquit - end game\nq - end game"],
    "look": ["look around at the current room.", "[b]=LOOK=[/]\nPrints a detailed description of the current room.\n[b]USAGE[/]\nlook - see description of current room"],
    "north": ["go north.", "[b]=NORTH=[/]\nMoves the player north.\n[b]USAGE[/]\nnorth - move player north\nn - move player north"],
    "west": ["go west.", "[b]=WEST=[/]\nMoves the player west.\n[b]USAGE[/]\nwest - move player west\nw - move player west"],
    "east": ["go east.", "[b]=EAST=[/]\nMoves the player east.\n[b]USAGE[/]\neast - move player east\ne - move player east"],
    "south": ["go south.", "[b]=WEST=[/]\nMoves the player south.\n[b]USAGE[/]\nwest - move player south\ns - move player south"],
    "grab": ["grab item from room.", "[b]=GRAB=[/]\nGrab an item out of the room and place it in your inventory.\n[b]USAGE[/]\ngrab - grab an item\n    item - name of item to grab."],
    "drop": ["drop item into room.", "[b]=DROP=[/]\nDrop an item from your inventory and place it in the room.\n[b]USAGE[/]\ndrop - drop an item\n    item - name of item to drop."],
    "inventory": ["list items in inventory.", "[b]=INVENTORY=[/]\nPrint a list of items in the player's inventory.\n[b]USAGE[/]\ninventory/i - read inventory"],
    "inspect": ["show detailed description of an item.", "[b]=INSPECT=[/]\nShow a detailed description of an item in your inventory.\n[b]USAGE[/]\ninspect - show long item description"],
    "clear": ["clear cmd prompt/terminal.", "[b]=CLEAR=[/]\nClear screen (for when the terminal has a lot of text in it).\n[b]USAGE[/]\nclear - clear cmd/terminal"],
    "changelog": ["show changelog for the current rpg version.", "[b]=CHANGELOG=[/]\nShow version changelog.\n[b]USAGE[/]\nchangelog - show changelog for the current version\n    version (opt) - print changelog for specific version"],
    "changelog <version>": ["show changelog for a specific rpg version."]
}
#find the item of a list that is closest to a string
def findsimilar(thing, inlist):
    similar = {}
    for item in inlist:
        similar[item] = SequenceMatcher(None, item, thing).ratio()
    return list(reversed(sorted(similar.items(),key=lambda x:x[1])))[0][0]
player = {}
def initplayer(name, startroom):
    global player
    player = {
        "name": name,
        "loc": startroom,
        "hp": 30,
        "maxhp": 30,
        "inventory": {}
    }
def noeffect():
    pass
box = Item("box", ["An odd box", "There are no markings on the cardboard box. It looks like it's been sitting in the forest for a while."], {"sellprice": 100, "buyprice": 150})
startroom = Room("Crossroads", ["A crossroads between a mountain, a forest, a town, and a plains.", "To the west is a mountain that looms in the distance.\nTo the north is a town named <TODO: name town>.\nTo the east is a bridge over a river, leading to a path that trails off into the distance.\nTo the south is the dark forest you came out of."], {"s": "ft1"}, {}, {})
foresttrail1 = Room("Forest Trail", ["A dark trail that leads to a clearing to the south and a crossroads to the north.", "This place gives you the chills.\nTo the north is a crossroads between two trails.\nTo the south is a rocky clearing."], {"n": "sr"}, {"bx": box}, {})
allrooms = {
    "sr": startroom,
    "ft1": foresttrail1,
}
rprint(align.Align(f"[b green]{title}[/]", "center").center(f"[bold green]{title}[/]"))
rprint(align.Align(f"[b]V{version}[/]", "center").center(f"[b]V{version}[/]"))
name = input("What is your adventurer's name? ")
initplayer(name, startroom)
while True:
    room = player["loc"]
    rprint(room.passive)
    command = input(f"\n{player['name']}> ").split()
    #list commands
    if command == ["help"]:
        for command in commands:
            rprint(f"{command} - {commands[command][0]}")
        print()
    #detailed help for specific command
    elif command[0] == "help" and len(command) >= 2:
        rprint(f"{commands[command[1]][1]}\n")
    #look around
    elif command == ["look"]:
        rprint(room.detail)
        for item in room.items:
            rprint(f"There is a {room.items[item].name} here.")
        rprint()
    #movement
    elif command[0][0] in list(room.directions.keys()) and command[0] in ["north", "west", "east", "south", "up", "down", "n", "w", "e", "s", "u", "d"]:
        player["loc"] = allrooms[room.directions[command[0][0]]]
    #if the player tries to move in a direction that they can't
    elif command[0] in ["north", "west", "east", "south", "up", "down", "n", "w", "e", "s", "u", "d"]:
        if len(command[0]) == 1:
            tmpconvert = {"n": "north", "w": "west", "e": "east", "s": "south", "u": "up", "d": "down"}
            rprint(f"[red]You cannot go {tmpconvert[command[0]]}.")
        else:
            rprint(f"[red]You cannot go {command[0]}.")
    #grab items
    elif command[0] == "grab" and len(command) >= 2:
        items = {room.items[item].name:room.items[item] for item in room.items}
        if command[1] in items:
            item = items[command[1]]
            internalname = list(room.items.keys())[list(items.values()).index(item)]
            player["inventory"][internalname] = item
            room.items.pop(internalname)
            rprint(f"[blue_violet]{command[1]} grabbed!")
        else:
            if not len(items) == 0:
                rprint(f"[red]There is no {command[1]} here! There [i]is[/] a {findsimilar(command[1], items)} here. Did you mean that?")
            else:
                rprint(f"[red]There are no items here!")
        #let this code stand as a memorial of what not to do
        #item = [room.items[item] for item in room.items][[room.items[item].name for item in room.items].index(command[1].lower())]
        #itemname = list(room.items.keys())[list(room.items.values()).index(item)]
        #player["inventory"][itemname] = item
        #room.items[itemname].pop()
    #unspecified item
    elif command == ["grab"]:
        rprint("[red]Grab what?")
    #drop items
    elif command[0] == "drop" and len(command) >= 2:
        items = {player["inventory"][item].name:player["inventory"][item] for item in player["inventory"]}
        if command[1] in items:
            item = items[command[1]]
            internalname = list(player["inventory"].keys())[list(items.values()).index(item)]
            room.items[internalname] = item
            player["inventory"].pop(internalname)
            rprint(f"[blue_violet]{command[1]} dropped!")
        else:
            if not len(items) == 0:
                rprint(f"[red]There is no {command[1]} in your inventory! There [i]is[/] a {findsimilar(command[1], items)} in your inventory. Did you mean that?")
            else:
                rprint(f"[red]You don't have any items to drop!")
    #unspecified item
    elif command == ["drop"]:
        rprint("[red]Drop what?")
    #see detailed description of item in inventory
    elif command[0] == "inspect" and len(command) == 2:
        items = {player["inventory"][item].name:player["inventory"][item] for item in player["inventory"]}
        if command[1] in items:
            rprint(f"[b blue_violet]{items[command[1]].name.upper()}[/]\n[pale_turquoise1]{items[command[1]].long}[/]")
    #unspecified item
    elif command == ["inspect"]:
        rprint("[red]Inspect what?")
    #see inventory
    elif command == ["inventory"] or command == ["i"]:
        for i in player["inventory"]:
            item = player["inventory"][i]
            rprint(f"[b blue_violet]{item.name}[/] [b]-[/] [i pale_turquoise1]{item.short}[/]")
        if len(player["inventory"]) == 0:
            rprint("[red]Your inventory is empty!")
    #clear terminal/cmd prompt
    elif command == ["clear"]:
        os.system("cls||clear") #multiplatform clear command!
        rprint("[green]Cleared!")
    #changelog
    elif command == ["changelog"]:
        rprint(versions[version])
    #access specific changelog
    elif command[0] == "changelog" and len(command) >= 2:
        #reassamble version names that have spaces
        name = " ".join(command[1:len(command)])
        try:
            rprint(versions[name])
        #if the version doesn't exist, find a similar one
        except KeyError:
            rprint(f"[red]'{name}' is not a valid version name. Did you mean '{findsimilar(name, list(versions.keys()))}'?")
    #quit game
    elif command == ["quit"] or command == ["q"]:
        rprint("[b green]Are you [i]sure[/i]?[/b green] (Y/n)")
        ynprompt = input().lower()
        if ynprompt in ["y", "yes"]:
            rprint("[green]Quitting game...")
            break
        elif ynprompt in ["n", "no", "nevermind"]:
            continue
        else:
            rprint("[red]Sorry, I don't understand. Can you try again? Valid answers are 'Y', 'Yes', 'N', 'No' (Case insensitive).")
    #find a similar command
    else:
        rprint(f"[red]Command not found. Did you mean '{findsimilar(command[0], list(commands.keys()))}'?")
for a (older) version that has a larger map, go here

Last edited by ScratchCatHELLO (June 24, 2021 18:06:22)






ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
gosoccerboy5
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

Wow, this is cool. I'd never be un-lazy enough to actually write all this code

ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

gosoccerboy5 wrote:

Wow, this is cool. I'd never be un-lazy enough to actually write all this code

thanks!
I should probably rewrite this so I don't have to write the code to grab items every time there's an item. I should finally stop being lazy and learn how classes work.





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
gosoccerboy5
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

ScratchCatHELLO wrote:

learn how classes work.
Whatever you're doing, classes are certainly a good investment to learn

ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

gosoccerboy5 wrote:

ScratchCatHELLO wrote:

learn how classes work.
Whatever you're doing, classes are certainly a good investment to learn

here's an expiremental class-based system with movement and two levels of descriptions:
#expiremental version that uses classes
class Room:
    def __init__(self, name, directions, descriptions, items, creatures):
        self.name = name
        self.directions = directions
        self.descriptions = descriptions
        self.items = items
        self.creatures = creatures
F_E = Room(
        "Forest_Exit",
        {},
        {
        "normal": "The trail on which you came.",
        "detail": "A dark, thin forest trail."
        },
        {},
        {}
)
F_C = Room(
        "Forest_Clearing",
        {},
        {
        "normal": "A rocky clearing in the forest.",
        "detail": "The trail widens out into a clearing. \nThere's a hole in the ground a few feet deep with a small pond in the center of the clearing."
        },
        {},
        {}
    )
F_P = Room(
        "Forest_Pond",
        {},
        {
        "normal": "A pond in the center of the clearing.",
        "detail": "A frog sits on a lily pad in the pond."
        },
        {},
        {}
    )
F_E.directions["south"] = F_C
F_C.directions["north"] = F_E
F_C.directions["down"] = F_P
F_P.directions["up"] = F_C
place = F_E
while True:
    #print(place.name)
    print(place.descriptions["normal"])
    command = input(">")
    if command in place.directions:
        place = place.directions[command]
    elif command == "look":
        print(place.descriptions["detail"])

the only problem with this is I need to define directions separately from the initialization of the rooms. otherwise, python gets angry at me for referencing variables before assigning them.





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
himanmario
Scratcher
15 posts

PyRPG (Python Text Adventure)

why are you discussing this on scratch when your using Java? could you not find another thing to discuss java? (if so, thats fine im just wondering)
also, is that c+/c++ cuz if so, sorry for calling it Java.
ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

himanmario wrote:

why are you discussing this on scratch when your using Java? could you not find another thing to discuss java? (if so, thats fine im just wondering)
also, is that c+/c++ cuz if so, sorry for calling it Java.

it's python
also, Things I'm Making and Creating is for things you're making outside of scratch
also, I don't have accounts anywhere else where I could share this, sorry





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

question: is it okay to put Object 1 inside of Object 2 when Object 2 is also in Object 1? It doesn't seem to be breaking anything, but objects that contain each other infinitely is a kinda sketchy thing to do.





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

ScratchCatHELLO wrote:

here's an expiremental class-based system with movement and two levels of descriptions:

update: now with objects, a “grab” command and inventory
#expiremental version that uses classes
#player class (make it a subclass of a "creature" class?)
class Player:
    def __init__(self, name, flags, inventory, stats):
        self.name = name
        self.flags = flags
        self.inventory = inventory
        self.stats = stats
#item class
class Item:
    def __init__(self, name, detail):
        self.name = name
        self.detail = detail
#weapon subclass of item
class Weapon(Item):
    def __init__(self, name, detail, atkstr):
        super().__init__(name, attitude, behaviour, face)
        self.atkstr = atkstr
#room class definition
class Room:
    def __init__(self, name, directions, descriptions, items, creatures):
        self.name = name
        self.directions = directions
        self.descriptions = descriptions
        self.items = items
        self.creatures = creatures
F_E = Room(
        "Forest_Exit",
        {},
        {
        "normal": "The trail on which you came.",
        "detail": "A dark, thin forest trail."
        },
        {},
        {}
)
F_C = Room(
        "Forest_Clearing",
        {},
        {
        "normal": "A rocky clearing in the forest.",
        "detail": "The trail widens out into a clearing. \nThere's a hole in the ground a few feet deep with a small pond in the center of the clearing."
        },
        {},
        {}
    )
F_P = Room(
        "Forest_Pond",
        {},
        {
        "normal": "A pond in the center of the clearing.",
        "detail": "A frog sits on a lily pad in the pond."
        },
        {},
        {}
    )
#add links between rooms
F_E.directions["south"] = F_C
F_C.directions["north"] = F_E
F_C.directions["down"] = F_P
F_P.directions["up"] = F_C
#make a box and place it in the main room
box = Item("Box", "mysterious box")
F_E.items["box"] = box
player = Player("Johnus Doeus", {}, {})
#starting room
place = F_E
while True:
    #show the normal description of the room
    print(place.descriptions["normal"])
    #list items in the room
    for item in place.items:
        print("There is a " + place.items[item].name + " here")
    
    #get input
    command = input(player.name + ">")
    #allow player to move
    if command in place.directions:
        place = place.directions[command]
    #deeper descriptions
    elif command == "look":
        print(place.descriptions["detail"])
    #grabbing objects
    elif command[0:4] == "grab":
        #figure out what they're grabbing
        for item in place.items:
            if place.items[item].name == command.replace("grab ", ""):
                #python gets upset when I put the code in this loop
                tmpitem = item
                break
        if tmpitem:
            print(place.items[tmpitem].name + " grabbed!")
            #copy item into inventory and remove item from room
            player.inventory[tmpitem] = place.items[tmpitem]
            place.items.pop(tmpitem)
            tmpitem = ""
    #show the player's inventory (make this better later)
    elif command == "inventory":
        print(player.inventory)





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

#expiremental version that uses classes
import pickle
from difflib import SequenceMatcher
def findsimilar(thing, inlist):
    similar = {}
    for item in inlist:
        similar[item] = SequenceMatcher(None, item, thing).ratio()
    return list(reversed(sorted(similar.items(),key=lambda x:x[1])))[0][0]
#player class (make it a subclass of a "creature" class?)
class Player:
    def __init__(self, name, flags, inventory, stats):
        self.name = name
        self.flags = flags
        self.inventory = inventory
        self.stats = stats
#item class
class Item:
    def __init__(self, name, description, detail):
        self.name = name
        self.description = description
        self.detail = detail
#weapon subclass of item
class Weapon(Item):
    def __init__(self, name, detail, atkstr):
        super().__init__(name, attitude, behaviour, face)
        self.atkstr = atkstr
#room class definition
class Room:
    def __init__(self, name, directions, descriptions, items, creatures):
        self.name = name
        self.directions = directions
        self.descriptions = descriptions
        self.items = items
        self.creatures = creatures
F_Ex = Room(
        "Forest Exit",
        {
        "south": "Forest Clearing"
        },
        {
        "normal": "The trail on which you came.",
        "detail": "A dark, thin forest trail."
        },
        {},
        {}
    )
F_C = Room(
        "Forest Clearing",
        {
        "north": "Forest Exit",
        "down": "Forest Pond"
        },
        {
        "normal": "A rocky clearing in the forest.",
        "detail": "The trail widens out into a clearing. \nThere's a hole in the ground a few feet deep with a small pond in the center of the clearing. There is a door to the south."
        },
        {},
        {}
    )
F_P = Room(
        "Forest Pond",
        {
        "up": "Forest Clearing"
        },
        {
        "normal": "A pond in the center of the clearing.",
        "detail": "A frog sits on a lily pad in the pond."
        },
        {},
        {}
    )
F_En = Room(
        "Forest Entrance",
        {
        "north": "Forest Clearing"
        },
        {
        "normal": "The entrance to the forest.",
        "detail": "A dark, thin forest trail. The forest gradually thins into a plains."
        },
        {},
        {}
    )
allrooms = {
    "Forest Exit": F_Ex,
    "Forest Clearing": F_C,
    "Forest Pond": F_P,
    "Forest Entrance": F_En
}
allcommands = ["load", "save", "inspect", "inventory", "drop", "grab", "look", "north", "south", "east", "west"]
#make a box and place it in the main room
box = Item("Box", "mysterious box", "an unmarked cardboard box.")
F_Ex.items["box"] = box
player = Player("Johnus Doeus", {}, {}, {})
#starting room
place = F_Ex
while True:
    #print(place.directions)
    #show the normal description of the room
    print(place.descriptions["normal"])
    #list items in the room
    for item in place.items:
        print("There is a " + place.items[item].name + " here")
    #get input
    command = input(player.name + ">")
    #allow player to move
    if command in place.directions:
        place = allrooms[place.directions[command]]
    elif place == allrooms["Forest Clearing"] and command == "south":
        print("The door is locked by a password.")
        if input("What is the password?\n") == "password":
            place.directions["south"] = 'Forest Entrance'
            print("The door shudders open.")
        else:
            print("Incorrect password.")
    #deeper descriptions
    elif command == "look":
        print(place.descriptions["detail"])
    #grabbing objects
    elif command[0:4] == "grab":
        if command.replace("grab", ""):
            #figure out what they're grabbing
            tmpitem = ""
            for item in place.items:
                if place.items[item].name == command.replace("grab ", ""):
                    #python gets upset when I put the code in this loop
                    tmpitem = item
                    break
            if tmpitem:
                print(place.items[tmpitem].name + " grabbed!")
                #copy item into inventory and remove item from room
                player.inventory[tmpitem] = place.items[tmpitem]
                place.items.pop(tmpitem)
                tmpitem = ""
        else:
            print("grab what?")
    elif command[0:4] == "drop":
        if command.replace("drop", ""):
            tmpitem = ""
            for item in player.inventory:
                if player.inventory[item].name == command.replace("drop ", ""):
                    tmpitem = item
                    break
            if tmpitem:
                print(player.inventory[tmpitem].name + " dropped!")
                #copy item into inventory and remove item from room
                place.items[tmpitem] = player.inventory[tmpitem]
                player.inventory.pop(tmpitem)
        else:
            print("drop what?")
    #show the player's inventory (make this better later)
    elif command == "inventory":
        for item in player.inventory:
            print(player.inventory[item].name)
            print(player.inventory[item].description)
    elif command[0:8] == "inspect ":
        for item in player.inventory:
            if player.inventory[item].name == command.replace("inspect ", ""):
                print(player.inventory[item].detail)
    elif command == "save":
        save = {}
        save["player"] = player
        save["place"] = place.name
        save["rooms"] = {}
        for room in allrooms:
            save["rooms"][room] = allrooms[room]
        with open('savedat2.txt', 'wb') as fh:
            pickle.dump(save, fh)
        print("Saved.")
    elif command == "load":
        savefile = open("savedat2.txt", "rb")
        loadedsave = pickle.load(savefile)
        player = loadedsave["player"]
        for room in loadedsave["rooms"]:
            allrooms[room] = loadedsave["rooms"][room]
        place = allrooms[loadedsave["place"]]
        print(F_C)
        print("Loaded.")
        savefile.close()
    elif command in allcommands:
        print("You cannot do that here.")
    else:
        print("command '" + command + "' not found.")
        print("did you mean: " + findsimilar(command, allcommands))
added:
save, load
giving user feedback when the command is not found
added dropping items





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

dialog system test:
dialog = {
   "ribbit": {
       "text": "Ribbit",
       "responses": {
           "A": {
               "text": "What?",
               "newdialog": "croak"
           },
           "B": {
               "text": "Why am I talking to a frog??",
               "newdialog": "shrug"
           }
       }
   },
   "croak": {
       "text": "Crrrroak",
       "responses": {
           "A": {
               "text": "What??",
               "newdialog": "ribbit"
           }
       }
   },
   "shrug": {
       "text": "¯\_(ツ)_/¯",
       "responses": {
           "A": {
               "text": "uh... bye"
           }
       }
   }
}
userresp = ""
currentdialog = "ribbit"
while not userresp == "goodbye":
    print("Frog says " + dialog[currentdialog]["text"])
    if dialog[currentdialog]["responses"]:
        responses = dialog[currentdialog]["responses"]
        for response in responses:
            print(response + ": " + responses[response]["text"])
    else:
        break
    userresp = input(">")
    if userresp in responses:
        try:
            currentdialog = dialog[currentdialog]["responses"][userresp]["newdialog"]
        except:
            break
    elif not userresp == "goodbye":
        print(userresp + " is not a valid response")

instructions:
respond by inputting one of the choices given to you
input “goodbye” to exit

The only problem with this is that the dialog dicts are massive, even for short conversations.
But it works, and I don't know how I could make this much smaller.





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
Delta135
Scratcher
100+ posts

PyRPG (Python Text Adventure)

Do you know of Repl.it? It supports HTML, CSS, JS, Java, Python 3, Python 2, and more. You can run them inside of a spotlight page, create a post, and even run it outside of the main website! You could upload your text adventure there!

I am Kizuo

Delta135
Scratcher
100+ posts

PyRPG (Python Text Adventure)


mybearworld
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

ScratchCatHELLO wrote:

[View post]
dialog system test:
print("Snip")

instructions:
respond by inputting one of the choices given to you
input “goodbye” to exit

The only problem with this is that the dialog dicts are massive, even for short conversations.
But it works, and I don't know how I could make this much smaller.
I'm gonna check it out!
I'm going to copy and paste my game in here…
The trail on which you came.
There is a Box here
Johnus Doeus>box
command 'box' not found.
did you mean: look
The trail on which you came.
There is a Box here
Johnus Doeus>look
A dark, thin forest trail.
The trail on which you came.
There is a Box here
Johnus Doeus>look box
command 'look box' not found.
did you mean: look
The trail on which you came.
There is a Box here
Johnus Doeus>WHAT DO I DO
command 'WHAT DO I DO' not found.
did you mean: west
The trail on which you came.
There is a Box here
Johnus Doeus>west
You cannot do that here.
The trail on which you came.
There is a Box here
Johnus Doeus>north
You cannot do that here.
The trail on which you came.
There is a Box here
Johnus Doeus>east
You cannot do that here.
The trail on which you came.
There is a Box here
Johnus Doeus>south
A rocky clearing in the forest.
Johnus Doeus>what do i do now
command 'what do i do now' not found.
did you mean: inventory
A rocky clearing in the forest.
Johnus Doeus>inventory
A rocky clearing in the forest.
Johnus Doeus>uh
command 'uh' not found.
did you mean: south
A rocky clearing in the forest.
Johnus Doeus>south
The door is locked by a password.
What is the password?
1234
Incorrect password.
A rocky clearing in the forest.
Johnus Doeus>south
The door is locked by a password.
What is the password?
123456
Incorrect password.
A rocky clearing in the forest.
Johnus Doeus>south
The door is locked by a password.
What is the password?
password
The door shudders open.
A rocky clearing in the forest.
Johnus Doeus>south
The entrance to the forest.
Johnus Doeus>south
You cannot do that here.
The entrance to the forest.
Johnus Doeus>okay uh
command 'okay uh' not found.
did you mean: south
The entrance to the forest.
Johnus Doeus>inventory
The entrance to the forest.
Johnus Doeus>south
You cannot do that here.
The entrance to the forest.
Johnus Doeus>i'm confused
command 'i'm confused' not found.
did you mean: inspect
The entrance to the forest.
Johnus Doeus>inspect
You cannot do that here.
The entrance to the forest.
Johnus Doeus>goodbye
command 'goodbye' not found.
did you mean: look
The entrance to the forest.
Johnus Doeus> goodbye
command ' goodbye' not found.
did you mean: look
The entrance to the forest.
Johnus Doeus>UH
command 'UH' not found.
did you mean: west
The entrance to the forest.
Johnus Doeus>
Traceback (most recent call last):
File "e.py", line 105, in <module>
command = input(player.name + ">")
KeyboardInterrupt
Please look at this xD

Signatures are the only place where assets links still work.
ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

mybearworld wrote:

ScratchCatHELLO wrote:

[View post]
dialog system test:
print("Snip")

instructions:
respond by inputting one of the choices given to you
input “goodbye” to exit

The only problem with this is that the dialog dicts are massive, even for short conversations.
But it works, and I don't know how I could make this much smaller.
I'm gonna check it out!
I'm going to copy and paste my game in here…
Please look at this xD

yeah, I should probably include instructions. It didn't occur to me because the script was meant to be a test.

also, you were running the wrong script. the “goodbye” command is only for dialog, which I just implemented and haven't posted yet

Delta135 wrote:

Do you know of Repl.it? It supports HTML, CSS, JS, Java, Python 3, Python 2, and more. You can run them inside of a spotlight page, create a post, and even run it outside of the main website! You could upload your text adventure there!

I am Kizuo

I know about replit, but I don't have an account :(





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
Delta135
Scratcher
100+ posts

PyRPG (Python Text Adventure)

ScratchCatHELLO wrote:

mybearworld wrote:

ScratchCatHELLO wrote:

[View post]
dialog system test:
print("Snip")

instructions:
respond by inputting one of the choices given to you
input “goodbye” to exit

The only problem with this is that the dialog dicts are massive, even for short conversations.
But it works, and I don't know how I could make this much smaller.
I'm gonna check it out!
I'm going to copy and paste my game in here…
Please look at this xD

yeah, I should probably include instructions. It didn't occur to me because the script was meant to be a test.

also, you were running the wrong script. the “goodbye” command is only for dialog, which I just implemented and haven't posted yet

Delta135 wrote:

Do you know of Repl.it? It supports HTML, CSS, JS, Java, Python 3, Python 2, and more. You can run them inside of a spotlight page, create a post, and even run it outside of the main website! You could upload your text adventure there!

I am Kizuo

I know about replit, but I don't have an account :(

Make one, it's free!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

Delta135 wrote:

Make one, it's free!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
…real estate

I can't yet
believe me, I want to





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
-EmeraldThunder-
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

I really like this idea. I might actually make a text adventure for my next tutorial.

Nothing here.
ScratchCatHELLO
Scratcher
1000+ posts

PyRPG (Python Text Adventure)

-EmeraldThunder- wrote:

I really like this idea. I might actually make a text adventure for my next tutorial.

thanks!

update with dialog and instructions (you may have to fix the instructions, because the string was so long my code editor may have inserted linebreaks):
#expiremental version that uses classes
import pickle
from difflib import SequenceMatcher
#find the item of a list that is closest to a string
def findsimilar(thing, inlist):
    similar = {}
    for item in inlist:
        similar[item] = SequenceMatcher(None, item, thing).ratio()
    return list(reversed(sorted(similar.items(),key=lambda x:x[1])))[0][0]
#frog's dialog
frogdialog = {
   "INITIAL": "ribbit",
   "ribbit": {
       "text": "Ribbit",
       "responses": {
           "A": {
               "text": "What?",
               "newdialog": "croak"
           },
           "B": {
               "text": "Why am I talking to a frog??",
               "newdialog": "shrug"
           }
       }
   },
   "croak": {
       "text": "Crrrroak",
       "responses": {
           "A": {
               "text": "What??",
               "newdialog": "ribbit"
           }
       }
   },
   "shrug": {
       "text": "¯\_(ツ)_/¯",
       "responses": {
           "A": {
               "text": "uh... bye"
           }
       }
   }
}
class Creature:
    def __init__(self, name, dialog, stats, attackable):
        self.name = name
        self.dialog = dialog
        self.stats = stats
        self.attackable = attackable
class Player:
    def __init__(self, name, flags, inventory, stats):
        self.name = name
        self.flags = flags
        self.inventory = inventory
        self.stats = stats
#item class
class Item:
    def __init__(self, name, description, detail):
        self.name = name
        self.description = description
        self.detail = detail
#weapon subclass of item
class Weapon(Item):
    def __init__(self, name, description, detail, atkstr):
        super().__init__(name, description, detail)
        self.atkstr = atkstr
#room class definition
class Room:
    def __init__(self, name, directions, descriptions, items, creatures):
        self.name = name
        self.directions = directions
        self.descriptions = descriptions
        self.items = items
        self.creatures = creatures
F_Ex = Room(
        "Forest Exit",
        {
        "south": "Forest Clearing"
        },
        {
        "normal": "The trail on which you came.",
        "detail": "A dark, thin forest trail. The trail continues south."
        },
        {},
        {}
    )
F_C = Room(
        "Forest Clearing",
        {
        "north": "Forest Exit",
        "down": "Forest Pond"
        },
        {
        "normal": "A rocky clearing in the forest.",
        "detail": "The trail widens out into a clearing. \nThere's a hole in the ground a few feet deep with a small pond in the center of the clearing that you can climb into. \nThere is a door to the south.\n There is a trail to the north."
        },
        {},
        {}
    )
F_P = Room(
        "Forest Pond",
        {
        "up": "Forest Clearing"
        },
        {
        "normal": "A pond in the center of the clearing.",
        "detail": "A frog sits on a lily pad in the pond.\n You can climb back out of the hole."
        },
        {},
        {}
    )
F_En = Room(
        "Forest Entrance",
        {
        "north": "Forest Clearing"
        },
        {
        "normal": "The entrance to the forest.",
        "detail": "A dark, thin forest trail. The forest gradually thins into a plains.\nYou may go north back into the clearing."
        },
        {},
        {}
    )
allrooms = {
    "Forest Exit": F_Ex,
    "Forest Clearing": F_C,
    "Forest Pond": F_P,
    "Forest Entrance": F_En
}
allcommands = ["load", "save", "inspect", "inventory", "help", "instructions", "drop", "grab", "look at", "look", "up", "down", "north", "south", "east", "west"]
#make a box and place it in the start room
box = Item("box", "a mysterious box", "an unmarked cardboard box.")
F_Ex.items["box"] = box
#make a frog and place it in the pond room
frog = Creature("frog", frogdialog, {}, False)
F_P.creatures["frog"] = frog
name = input("What is your name?\n")
if name:
    player = Player(name, {}, {}, {})
else:
    player = Player("Johnus Doeus", {}, {}, {})
#starting room
place = F_Ex
#allow user to quit
command = ""
while not command == "quit":
    #show the normal description of the room
    print(place.descriptions["normal"])
    #list items in the room
    for item in place.items:
        print("There is a " + place.items[item].name + " here.")
    #list creatures in the room
    for creature in place.creatures:
        print("There is a " + place.creatures[creature].name + " in the room.")
    #get input
    command = input(player.name + ">")
    #allow player to move
    if command in place.directions:
        place = allrooms[place.directions[command]]
    #door
    elif place == allrooms["Forest Clearing"] and command == "south":
        print("The door is locked by a password.")
        if input("What is the password?\n") == "password":
            place.directions["south"] = 'Forest Entrance'
            print("The door shudders open.")
        else:
            print("Incorrect password.")
    #print all command names (add descriptions?)
    elif command == "help":
        for command in allcommands:
            print(command)
    #print instuctions
    elif command == "instructions":
        print("This is just a test level, and there isn't much to just yet.\nYou can type 'help' for a list of commands.\nYou can type 'quit' to quit.\nYou can look around with 'look'\nYou can pick up and drop items with 'grab ___' and 'drop ___'\nYou can open your inventory with 'inventory'\nYou can inspect items you are holding with 'inspect ___'\nYou can look at items you aren't holding with 'look at ___'\nYou can talk to creatures by typing 'talk to ___'\nYou can load and save (EXPIREMENTAL) with 'load' and 'save'")
    #allow player to look at items they aren't holding
    elif command[0:7] == "look at":
        if command.replace("look at", ""):
            for item in place.items:
                if place.items[item].name == command.replace("look at ", ""):
                    print(place.items[item].description)
        else:
            print("look at what?")
    #deeper descriptions
    elif command == "look":
        print(place.descriptions["detail"])
    #allow player to grab items
    elif command[0:4] == "grab":
        if command.replace("grab", ""):
            #figure out what they're grabbing
            tmpitem = ""
            for item in place.items:
                if place.items[item].name == command.replace("grab ", ""):
                    #python gets upset when I put the code in this loop
                    tmpitem = item
                    break
            if tmpitem:
                print(place.items[tmpitem].name + " grabbed!")
                #copy item into inventory and remove item from room
                player.inventory[tmpitem] = place.items[tmpitem]
                place.items.pop(tmpitem)
                tmpitem = ""
            else:
                print("There is no " + command.replace("grab ", "") + " in this room.")
        else:
            print("Grab what?")
    #allow player to drop items (does the inverse of "grab")
    elif command[0:4] == "drop":
        if command.replace("drop", ""):
            tmpitem = ""
            for item in player.inventory:
                if player.inventory[item].name == command.replace("drop ", ""):
                    tmpitem = item
                    break
            if tmpitem:
                print(player.inventory[tmpitem].name + " dropped!")
                #copy item into inventory and remove item from room
                place.items[tmpitem] = player.inventory[tmpitem]
                player.inventory.pop(tmpitem)
            else:
                print("There is no " + command.replace("drop ", "") + " in your inventory.")
        else:
            print("Drop what?")
    #show the player's inventory (make this better later)
    elif command == "inventory":
        for item in player.inventory:
            print(player.inventory[item].name)
            print(player.inventory[item].description)
    #show detailed description for items in inventory
    elif command[0:7] == "inspect":
        if command.replace("inspect ", ""):
            for item in player.inventory:
                if player.inventory[item].name == command.replace("inspect ", ""):
                    print(player.inventory[item].detail)
        else:
            print("Inspect what?")
    #allow player to talk to creatures
    elif command[0:7] == "talk to":
        activecreature = ""
        #figure out what creature the player is talking to
        for creature in place.creatures:
            if place.creatures[creature].name == command.replace("talk to ", ""):
                activecreature = place.creatures[creature]
                break
        if activecreature:
            userresp = ""
            #get the initial dialog snippet
            currentdialog = activecreature.dialog[activecreature.dialog["INITIAL"]]
            while not userresp == "goodbye":
                print("The " + activecreature.name + " says '" + currentdialog["text"] + "'")
                #print possible responses
                for response in currentdialog["responses"]:
                    print(response + ": " + currentdialog["responses"][response]["text"])
                userresp = input(">").upper()
                if userresp in currentdialog["responses"]:
                    try:
                        print("You say '" + currentdialog["responses"][userresp]["text"] + "' to the " + activecreature.name)
                        #set the current dialog snippet to the new dialog snippet
                        currentdialog = activecreature.dialog[currentdialog["responses"][userresp]["newdialog"]]
                    except:
                        break
                elif not userresp == "goodbye":
                    #tell user if they didn't type a valid response
                    print("'" + userresp + "' is not a valid response.")
    #save (not updated)
    elif command == "save":
        save = {}
        save["player"] = player
        save["place"] = place.name
        save["rooms"] = {}
        for room in allrooms:
            save["rooms"][room] = allrooms[room]
        with open('savedat2.txt', 'wb') as fh:
            pickle.dump(save, fh)
        print("Saved.")
    #load (not updated)
    elif command == "load":
        savefile = open("savedat2.txt", "rb")
        loadedsave = pickle.load(savefile)
        player = loadedsave["player"]
        for room in loadedsave["rooms"]:
            allrooms[room] = loadedsave["rooms"][room]
        place = allrooms[loadedsave["place"]]
        print(F_C)
        print("Loaded.")
        savefile.close()
    #if the command is valid, but cannot be done in the current room
    elif command in allcommands:
        print("You cannot do that here.")
    #if the command is not valid (and is not "quit"), print a similar command
    elif not command == "quit":
        print("command '" + command + "' not found.")
        print("did you mean: " + findsimilar(command, allcommands))

truely ground-breaking dialog





ScratchCatHELLO
I have 5600+ posts, I've been on scratch for 5 1/2 years, I'm a Forum Helper™ and I have a Scratch Wiki account!
I like: Python, CSS, Javascript, Rust



Python 3 Text Adventure
cool new browser game - cursed laughing-crying emoji - Illuminati - you know waterbenders, but do you know stock-imagebenders? - snek - vibin' - Bump song (vevo) - Speed bump - yee - fred - m i c k e y
Delta135
Scratcher
100+ posts

PyRPG (Python Text Adventure)

Want me to host it on Replit?

Powered by DjangoBB