Why this Error? How should I fix it?

Hello Pcat11!
I’m writing to inform you that I’ve thought about how to change your movement system to make it automatically get the destinations of the moves instead of having to manually define them. I believe this is closer to what you were originally going for when you first asked for help.

the zonemap dictionary now looks like this:

Changes
zonemap = {
    'a1': {
      ZONENAME: "",
      DESCRIPTION: 'description',
      EXAMINATION: 'examine',
      SOLVED: False,
    },
  'a2': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,

instead of how it was before :

 'd4': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
    UP: "c4", <---- doesn't need this anymore┐
    DOWN:  "d4",  
    LEFT:  "d3",  
    RIGHT: "d4" <----------------------------┘

I’ve changed
def player_move(myAction): to

def player_move(myAction):
    ask = "Where would you like to go?\n"
    dest = input(ask)

    # Check if the input direction is valid
    if dest.lower() in ['up', 'down', 'left', 'right']:
        direction = dest.lower()
        destination_row = zonemap[myPlayer.location]['row']
        destination_col = zonemap[myPlayer.location]['col']

        # Calculate the new row and column based on the chosen direction
        if direction == 'up':
            destination_row -= 1
        elif direction == 'down':
            destination_row += 1
        elif direction == 'left':
            destination_col -= 1
        elif direction == 'right':
            destination_col += 1

        # Construct the destination key based on the new row and column
        destination_key = chr(destination_col + ord('a') - 1) + str(destination_row)

        # Check if the destination key is valid
        if destination_key in zonemap:
            movement_handler(destination_key)
            print("\n" + f"You have moved {direction}.")
        else:
            print("\nInvalid direction. Please enter a valid direction (up, down, left, right).")
    else:
        print("\nInvalid direction. Please enter a valid direction (up, down, left, right).")

and added :

for key in zonemap:
    zonemap[key]['row'] = int(key[1])
    zonemap[key]['col'] = ord(key[0].lower()) - ord('a') + 1
New movement system explained.

Movement is now determined solely by the name of each square, (ex : ‘d4’) and the names of its neighboring squares.
You have a 4 directional movement system and a map of squares, you’ve also already named them each individually as a1 or a2 or b1 or b2.

Instead of manually defining movement each time like :

UP: "c4",
DOWN:  "d4",
LEFT:  "d3",
RIGHT: "d4"

we can think of the letters as vertical based movement and the numbers as horizontal based movement.
It uses a column and row system for vertical and horizontal movement.

New code & link
import os
import sys
import time

screen_width = 100

# Player Setup
class player:
    def __init__(self):
      self.name = ''
      self.job = ''
      self.hp = 0
      self.mp = 0
      self.status_effects = []
      self.location = 'b2'
      self.game_over = False
myPlayer = player()

# Title Screen
def title_screen_selections():
    option = input("> ")
    if option.lower() == ("play"):
      setup_game() #place holder
    elif option.lower() == ("help"):
      help_menu()
    elif option.lower() == ("quit"):
      sys.exit()
    while option.lower() not in ['play', 'help', 'quit']:
      print("Invalid Option, Enter Valid Command")
      option = input("> ")
      if option.lower() == ("play"):
        setup_game() #place holder
      elif option.lower() == ("help"):
        help_menu()
      elif option.lower() == ("quit"):
        sys.exit()

def title_screen():
  os.system('clear')
  print('########################')
  print('# Welcome to Text RPG! #')
  print('########################')
  print('         -Play-          ')
  print('         -Help-          ')
  print('         -Quit-          ')
  title_screen_selections()

def help_menu():
  os.system('clear')
  print('###########################')
  print('# Help Menu #')
  print('###########################')
  print('Use the UP,DOWN,LEFT,RIGHT keys to move')
  print('Type your commands to do things')
  print('Use "examine" to inspect something')
  print('Good Luck!')
  print('#' * 25)
  print("Select an option to continue...")
  print('#' * 25)
  print("Play")
  print("Quit")
  title_screen_selections()

# Map #
"""
a1  a2... # Player starts at b2
-------------
|  |  |  |  |  a4
-------------
|  |  |  |  |  b4 ...
-------------`
-------------
|  |  |  |  |
-------------
|  |  |  |  |
-------------
"""



ZONENAME = ''
DESCRIPTION = 'description'
EXAMINATION = 'examine'
SOLVED = False
UP = 'up', 'north'
DOWN = 'down', 'south'
LEFT = 'left' , 'west'
RIGHT = 'right' , 'east'

solved_places = {'a1': False, 'a2': False, 'a3': False, 'a4': False, 
                 'b1': False,'b2': False, 'b3': False, 'b4': False,
                 'c1': False,'c2': False, 'c3': False, 'c4': False, 
                 'd1': False,'d2': False, 'd3': False, 'd4': False,
                }

zonemap = {
    'a1': {
      ZONENAME: "",
      DESCRIPTION: 'description',
      EXAMINATION: 'examine',
      SOLVED: False,
    },
  'a2': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  
  'a3': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  
  'a4': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  
  'b1': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  
  'b2': {
    ZONENAME: 'Home',
    DESCRIPTION: 'Home is Paradise. It is Small, but it is comfortable.',
    EXAMINATION: 'Your home is the same. Nothing has changed.',
    SOLVED: False,
  },  
  'b3': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  
  'b4': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
    
  },  'c1': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  'c2': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  
  },  'c3': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  'c4': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  'd1': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  'd2': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  'd3': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },  'd4': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },
}
for key in zonemap:
  zonemap[key]['row'] = int(key[1])
  zonemap[key]['col'] = ord(key[0].lower()) - ord('a') + 1

#Game Interactivity
def print_location():
  print('\n' + ('#' * (4 + len(str(myPlayer.location)))))
  print('# ' + str(myPlayer.location).upper() + ' #')
  print('# ' + zonemap[myPlayer.location][DESCRIPTION].upper() + ' #')
  print('\n' + ('#' * (4 + len(str(myPlayer.location)))))
  print('#')

#Prompt
def prompt():
  print("\n" + "=========================")
  print("What would you like to do?")
  action = input("> ")
  acceptable_actions = ['move', 'quit', 'examine']
  while action.lower() not in acceptable_actions:
    print("Unknown Action, please enter an Acceptable Action.\n")
    action = input("> ")
  if action.lower() == 'quit':
    sys.exit()
  elif action.lower() in ['move']:
    player_move(action)
  elif action.lower() in ['examine']:
    player_examine(action)

#How the Player moves, and to where
def player_move(myAction):
  ask = "Where would you like to go?\n"
  dest = input(ask)

  # Check if the input direction is valid
  if dest.lower() in ['up', 'down', 'left', 'right']:
      direction = dest.lower()
      destination_row = zonemap[myPlayer.location]['row']
      destination_col = zonemap[myPlayer.location]['col']

      # Calculate the new row and column based on the chosen direction
      if direction == 'up':
          destination_col -= 1
      elif direction == 'down':
          destination_col += 1
      elif direction == 'left':
          destination_row -= 1
      elif direction == 'right':
          destination_row += 1

      # Construct the destination key based on the new row and column
      destination_key = chr(destination_col + ord('a') - 1) + str(destination_row)

      # Check if the destination key is valid
      if destination_key in zonemap:
          movement_handler(destination_key)
          print("\n" + f"You have moved {direction}.")
      else:
          print("\nInvalid direction. Please enter a valid direction (up, down, left, right).")
  else:
      print("\nInvalid direction. Please enter a valid direction (up, down, left, right).")
def movement_handler(destination):
  myPlayer.location = destination
  print_location()


def player_examine(action):
  if zonemap[myPlayer.location][SOLVED]:
    print("\n" + "You have already exhausted this area.")
  else:
    print("Puzzle?")

#Game Components


def main_game_loop():
  while myPlayer.game_over is False:
    prompt()

def setup_game():
  os.system('clear')

  #Name
  question1 = "Hello, what is your Username?\n"
  for character in question1:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.05)
  player_name = input("> ")
  myPlayer.name = player_name

  #Job
  question2 = "Hello, what role do you want to play?\n"
  question2added = "You may play as a wizard, warrior, or a rogue.\n"
  for character in question2:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.05)
  for character in question2added:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.05)
  valid_jobs = ['wizard', 'warrior', 'rogue']
  player_job = input("> ").lower()
  if player_job in valid_jobs:
    if myPlayer.job == 'warrior':
      self.hp = 120
      self.mp = 20
    elif myPlayer.job == 'wizard':
      self.hp = 40
      self.mp = 120
    elif myPlayer.job == 'rogue':
      self.hp = 60
      self.mp = 60
    print("You are now a " + player_job + ".")
  while player_job.lower() not in valid_jobs:
      player_job = input("> ")
      if player_job.lower() in valid_jobs:
        myPlayer.job = player_job
        print("You are now a" + myPlayer.job + ".")
  #Player Stats


  question3 = "Welcome," + player_name + " the " + player_job +  ".\n"
  for character in question3:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.05)

  speech1 = "Welcome to Pineberry!\n"
  speech2 = "I hope you do well!\n"
  speech3 = "Don't get lost...\n"
  speech4 = "Farewell...\n"
  for character in speech1:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.03)
  for character in speech2:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.03)
  for character in speech3:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.1)
  for character in speech4:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.2)

  os.system('clear')
  print("###########################")
  print("#   On with the story...  #")
  print("###########################")
  main_game_loop()

title_screen()

https://replit.com/@vvithershins/Fork-Text-Based-Game#NewVersion.py

Adding a new square to the grid (easier now)

This makes expanding the game map/grid easier.
i’ve added 1 square making it 17 squares in total by adding this to the zonemap dictionary

'e4': {
    ZONENAME: "",
    DESCRIPTION: 'description',
    EXAMINATION: 'examine',
    SOLVED: False,
  },

and adding it to solved_places

How I used Ai to help me



It had the columns and rows for if direction == " mixmatched so i just swapped them.

If anyone can see any flaws with my changes please let me know. And if you have any questions I’ll do my best to answer them.

I have to admit, you are quite an impressive coder and problem solver. I also used a online video solely as to write this. I had given up, and was going to scrap this project, but you saved it. I am curious. Where has your edu come from? Replit, somewhere else?

I will definitely be checking to see how far you go as a programmer

Well thank you!
Yes the majority of my Python / coding education comes from Replit itself. I am currently on day 64 of the 100 days of code which has been a major help.

Your project is a good deal beyond my level honestly. I just looked at the parts that I thought I could understand and just started tinkering with it. Any successful changes I made were most likely due to a process of trial and error.

more

Most of the changes made to the code itself were done by AI. I use a strategy of asking it as precise and specific questions I can regarding what is currently happening and what changes I want it to make. I’ll oftentimes copy and paste the entire code verbatim into chatgpt and then ask it why I’m getting the error I’m receiving or why it’s not behaving how I expect/want it to.

While I adjusted some of the layout and order, and errorchecked the changes the AI made, I act more as just the messenger for the AI and the program.
I take the program and ask AI to help fix it, It tries to fix it, I test if it works, if it doesn’t I tell it what happened and reiterate exactly what I want to happen.
I’ll apply the knowledge I’ve gained (mostly through the 100 days.) to whatever I can .

I’ve played a lot of video games which I believe which might have helped in this case. My familiarity gives me a sort of innate sense of how some of them should work from an outside in perspective, (though I definitely could know ALOT more)

I also will ask ai to generate challenge exercises based on the lessons from the 100 days, to try and expand my understanding of what they covered. (for instance I’ll say generate an exercise for testing my understanding of lists , or something of the like.)

But thank you I really appreciate the kind words and I hope your project turns out well!

If you want to know more about my background you can check my about me in my summary/ though you may have to click the expand button.

I’ve been trying to think of another way to expand the map grid by naming each square something like '0101" instead of “a1” but all my attempts so far have failed. I will let you know if I ever get it to work though!

To do this, tuple coordinate pairs work nicely. [(0,0), (-1,10)]. (A custom class is probably best though, for more operations.)

I am currently on day nine, lol. I have started over about 3 times but I always get to if else loops then loose focus or get busy. This is the first time I have actually stuck with it for a bit longer and think this time I could get far. Check my replit profile. I am building a choose your own adventure based entirely off input variables and nested if loops. I am still in the early stages.

1 Like

Ah thank you.
I had tinkered around with

for key in zonemap:
  zonemap[key]['row'] = int(key[1])
  zonemap[key]['col'] = ord(key[0].lower()) - ord('a') + 1

and changed it to

for key in zonemap:
  zonemap[key]['row'] = int(key[2:3])
  zonemap[key]['col'] = int(key[0:1])

and changed the zonemap names from
A4
to 0101
It would give me an error related to not being able to use string slicing on ints, so I tried to convert them to strings and then back to int but kept running into various errors so I just reverted back to the way it was before

for key in zonemap:
  zonemap[key]['row'] = int(key[1])
  zonemap[key]['col'] = ord(key[0].lower()) - ord('a') + 1

and
A4

At this point it can be a 10 x 26 grid (0-9)(a-z)
I believe it could be expanded to a 26x26 grid just by changing the zone map names from A4 to AB and then modifying the zonemap[key][‘row’] to mirror the one for column.

I will look into testing this when I have the time.

I am confused by the code, I’m assuming key is the zonemap name (A4, 0101), but what is the 'row' and 'column' for?
The best ways to implement a zonemap:

  1. Use a list of lists:
zonemap = [
  ['val', 'valX', 'valY']
  ['...', '...', '...']
  ['...', '...', '...']
]

All squares are filled, access is like this: zonemap[1][0]

  1. Use a dict of tuple points:
zonemap = {(0,0): 'val1', (100,57): 'val2'}

Squares can be missing, and access is like zonemap[0,1] or zonemap[(0,1)]

For a nicer looking format than something like (50,56), y could be a 2 digit number and x could be 2 letters. (50,56) -> 'BB56', but honestly, a coordinate pair of ints is more readable.

1 Like

Yeah I’ve had to redo some previous days because I didn’t retain the knowledge or understand how to apply it in a new scenario. There’s been a few days that without the solution in the tutorial acting as guidance, I would still be stuck on.
I just try to make sure if I do look at the challenge’s solution that I can understand how it works.

When you first posted I viewed your profile and thought, “wait, they’re only in the first ten days and they’re already building something like this?”

I wasn’t sure if I’d be able to help or not but I just wanted to try anyway.

I’ve been in the same boat where I’ve reached the limit of my know how for a certain project I’m working on, but then they’ll introduce a new concept in one of the days which makes the way I was trying to do it previously much easier now.

I’ll sometimes go back to my previous days and change them with the new concepts I’ve learned. (while saving the old version as a copy.) so I can see and compare my progress.

I too was working on a text based / turn based adventure game but I’ve kind of put it on hold for now as the day’s lessons have started taking a bit more time.

I’ve got it to the point where all I have to do is make a new enemy’s stats and then I can use it as a new battle. It’s kinda rough as I’ve been working on it between other projects / lessons. But it might be able to give you an idea of some turn based / text based battle mechanics

https://replit.com/@vvithershins/The-Curse-Of-The-Evil-Eye

I definitely look forward to seeing how your games work out though, and if you need any more help you know where to find me!

1 Like

Taking a look at the project, a great way to improve your code is with custom python classes (object oriented programming).

1 Like

Where did you learn to code all this? Was this all solely from replit?

The names of the squares consist of vertical and horizontal positioners.
The letters act as the vertical columns, and the numbers act as the horizontal rows.
So when moving vertically we only need to look at the Letter part of it’s position
(A)4
and when moving horizontally we only need to look at the number part of it’s position
A(4)

for key in zonemap:            👇 #(the number/row)
  zonemap[key]['row'] = int(key[1])
  zonemap[key]['col'] = ord(key[0].lower()) - ord('a') + 1 
                                👆 #(the letter/column)

This would limit the row to 10 though and the columns to 26 right?
So I thought “what if we scrap the letter part of the names and use numbers for those too”

So squares would be named 11 or 21 or 12 instead of A1 or B1 or A2
but then this would limit it to a 10x10 map/grid.

So THEN I thought, well couldnt we expand it to 100x100 by using 4 characters instead of 2? (0101) instead of (11) or (A1)
This would give 0-99 for the rows(100)
by 0-99 for the colums (100)
100x100
and then we’ll use the first 2 numbers in the name as the row and the second 2 numbers in the name as the column and just use slicing to split it in half.

And that’s as far as I got.

Yes mostly through replit and then whenever I would get stuck I would ask replit AI to help me or copy and paste everything into chatGPT and ask it to help me.

I think everything used in it is covered by the time you get to dictionaries.(day 40)

I see.
Caching the actual integers for the string key is possible I guess, but this is why the dict or list zonemap with actual integer keys is much better.
When you tried keys with format 0101, the error is most likely from using raw integers 0101 instead of string numbers "0101", and the slicing also looks to be incorrect.

Also, classes are an upgrade to certain dictionaries.

1 Like

Yeah, I was thinking about your project, you should take some time to learn about those custom classes. It would make your code for your game much easier to read, and it will be better for more enemies. You can just put you different player classes at the top and enemy classes. You can filter all their stats into that. Should maybe help? Idk, I just learned a little about custom classes from my youtube vid.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.