Home

Sunday, December 19, 2021

Python: Text RPG - Entry 1 - Map Grid and Movement

Python Text RPG

-Map Grid and Movement-

 
So to get going we need some were for the player to be. A sort of world we can display to the player and keep track of their location. We will need to lay a good bit of ground work for this. But before that Lets go a really simple way as a demo.
 
 
- I'll update / finish this post at my earliest opportunity -
 
Last update: ` 2021/12/20 - 23:47 `  
 
 
Until then I do encourage you to look at and try out the code in your own project.
 
 

SIMPLE DEMO:

_______________________________________________________________
 
# Setup the player with information about the world and their choices.
print("Welcome to this game of text walls!")
print("You are in an empty room; on the wast wall is a door, on the east wall is a small window.\n")
print("What do you do?")
answer = input(">")
print() # add a new line after the players answer in the console


# A dictionary of the choices and their text pairing.
paths = { "west" : "The door is locked!", "east" : "It's to dark to see anything out the window.", "none" :  "you stand still, still as a board." }


# A list is returned from the comprehension comparison. We want the 1st (aka the 0th) element, IF there is anything in the list.
player_action = [ opt for ind, opt in enumerate( paths ) if opt.lower() in answer.lower() or answer == str( ind+1 ) ]


# We want to print out the results of the players choice.
action_result = paths[player_action[0]] if 0 < len( player_action ) else path["none"]
print( action_result )


# Rinse repeat a million times. This concludes the short demo.
 
# This is the kind of text RPG programming I have found on the web. But not quite what I was looking for. I'm going for a more object oriented and easy to maintain project file. So hopefully this train wreck will be of interest to you.

- END -

 
_______________________________________________________________
section status: WIP -  ` 2021/12/20 - 16:21
" W.I.P. Disclaimer: I have yet to test run this code it's just out of my brain so It may not work. " 
 
 
# On to the kind of Object Oriented Programming! First lets make a class that will handle changing the currently active map.

class Game_Manager():

current_node = None
previous_node = None

def __init__( self, **kewargs ):
current_node = None
previous_node = None
attrs_list = [ p for p in dir(self) if not p.startswith( "_" ) and not callable(getattr( self, p )) ] 
catch = [ setattr(self, k, kewargs[k] ) for k in kewargs if k in attrs_list ]
 
def travel( self, next_node ):
if not next: return self.current_node

self.previous_node = self.current_node
self.current_node = next_node
return self.current_node
 
travel_manager = Travel_Manager()
 

_______________________________________________________________
section status: WIP -  ` 2021/12/19 - 23:08 ` 
 
 
 # This class will handle printing information about maps and the players actions to the console.

 class Display_Manger():

# Get a list of places the player can go from the current map; [ "Bar", "shop", "soldiers office" ]
read_travel( self ): pass
 
# Get a list of actions the player can take. Go, Leave, Inspect, Open
read_options( self ): pass

# Format and print out the gathered information to the console
display( self ): pass


_______________________________________________________________
section status: WIP -  ` 2021/12/19 - 22:52 ` 


class Tile():

xy_pose = ()
walkable = False
contents = []
 
def __init__( self, xy_pose, walkable ):
self.xy_pose = xy_pose
self.walkable = walkable
self.status()
 
def __repr__( self ):
return f"{self.xy_pose}, {self.walkable}"
 
def status( self ):
print( self.__repr__() )


_______________________________________________________________
section status: WIP -  ` 2021/12/19 - 23:27 `  
 

class Grid():

height = 10
width = 10
map_grid = [] # The main container for the gird
 
def __init__( self, width, height ):
# Initialize a flat 10x10 grid of Tile objects

for row in range( 0, height ):
    map_grid.append( [] ) # Append an empty 'row' array.

    # Create new Tile object for every 'square' in the grid row.
    for column in range( 0, width ):
        map_grid[row].append( Tile( ( row, column ), True ) )

_______________________________________________________________
section status: WIP -  ` 2021/12/20 - 23:47 ` 
 
# This one is getting a wee long, I might break it out into a seperate post so I can add commentary on how the class works otuside of the inline comments.


class Location():

location_name = ""
    simple_tag = ""
    sublocations = []
    play_grid = None
    contents = {
        "occupants" : {
            "player" : [],
            "NPC" : [],
            "monster" : []
        },
        "structure" : [],
        "props" : {
            "general" : [],
            "envy" : [],
            "utility" : [],
            "media" : [],
            "consumable" : [],
            "tableware" : [],
            "lights" : [],
            "appliance" : [],
            "furniture" : [],
            "drapery" : [],
            "containers" : []
        }
    }

    def __init__( self, name, simple_tag, width=0, height=0, contents ):
        self.location_name = name.lower()
        self.simple_tag = simple_tag.lower()
        self.sublocations = []
        self.play_grid = Grid( width, height ) if width != 0 and height != 0 else None
        self.contents = contents if contents else self.__class__.contents.copy()
    
    def _child_index( self, child ):
        return self.sublocations.index( child )

    def _sortby_tag( self, tag ): pass

    def _search_child_name( self, name ):
        out = [ loc for loc in self.sublocations if loc.location_name in name ]
        return out[0] if 0 < len( out ) else None

    def _search_child_object( self, child ):
        if child in self.sublocations or child.location_name in ''.join( f"{self.sublocations}" ):
            return child
        return None

    def _add_child_location( self, newChild ):
        if self._search_child_object( newChild ):
            return None
        self.sublocations.append( newChild )
        return newChild, self._child_index( newChild )

    def children( self, *children ):
        # Sort Lists of Valid Data
        return self, [ self._add_child_location( child ) if Location is type( child ) else self._search_child_name( child ) if str is type( child ) else None for child in children ]
    
    def __str__( self ):
        return f"{self.location_name, self.simple_tag}"
    
    def __repr__( self ):
        return f"{self.location_name, self.simple_tag, str(self.play_grid)}"
 
 
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
 
 
# The general overmap
overmap_setup = Location("overmap", "map")

# The town of Varnum
varnum_setup = Location("Varnum", "zone")
print( overmap_setup.children( varnum_setup ) ) # Add Varnum to the Overmap

# Sites in Varnum
print( varnum_setup.children( Location("the broken kettle", 'bar'), Location("tyvan's quality goods", 'shop') ) )
print( varnum_setup.children( Location("silver heron guild", 'recruitment office') ) )
approuch = varnum_setup.children( Location("town approach", 'battle map', 10, 10) )
print( approuch )

# Duplicate validation
print( f"DUPLICATE - Nothing added to {varnum_setup.location_name}: { varnum_setup.children( Location('silver heron guild', 'recruitment office') ) }" )

# search for a location by name
print( f"NAME SEARCH: { varnum_setup._search_child_name( 'the broken kettle' ) }" )
print( f"NAME SEARCH: { varnum_setup.children( 'the broken kettle') }" )

# End result validation
print( varnum_setup.sublocations )


vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
 
 

# Example of how to use Location in practice:

# please note all variables; (Zone, Subzone, etc.) are all Location objects, just named for clarity.

Zone = "Elwynn Forest"
Subzone = ["Goldshire"]

Subzone = "Goldshire"
Site = [ "blacksmith", "inn"]

Site = "inn"
Map = [ "floor_0", "floor_1", "floor_2", "roof"]

Map = "floor_2"
Room = ["room_1"]

Room = "room_1"
# Contents have an { object : ( x_pos, y_pos ) }
Contents = {
    "occupants" : {
        "player_id" : [ "player_id" ],
        "NPC" : ["barkeep", "cook", "barmaid", "wine steward"],
        "monster" : ["chicken_1", "rat_1", "rat_2"]
    },
    "structure" : ["wall", "wall", "wall", "wall", "door_1", "window_1"],
    "props" : {
        "media" : ["book"],
        "consumable" : ["meat on bone"],
        "kitchen" : ["bowel_wood", "cup_tin", "bottle_glass_empty"],
        "lights" : ["tri_candle_stand"],
        "furniture" : ["shoe_wrack", "table", "wardrobe_wood", "chair_wood", "bed_queen", "table_side_wood"],
        "drapery" : ["rug_large", "bed_canopy", "shirt_brown"],
        "containers" : ["chest_foot_locked"]
    }
}
 

-END-

No comments:

Post a Comment

Conduct: Be nice and don't advertise or plug without adding value to the conversation.