A curses-game I need help with.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Gasten

    A curses-game I need help with.

    Hello.
    The last weeks I've been coding a roguelike (you know, like nethack) in
    python using the nCurses library. Some week ago I ran into a problem:
    When I made the object for messagebar-output, I found a bug that I
    can't figure out (believe me; I've tried everything and asked for help
    several times on the IRC-channel).

    The updateMsg() and iMsg() takes a list of message-lines as argument
    (or process a string to a list), and it'll output each of them to the
    messagebar, output a sign that say: More, and wait for the user to hit
    space, and then output another line. The last line will just be
    outputed, without waiting for the user to hit space. Thou, that doesn't
    work. It doesn't output the last line. Not when there are more than one
    line, and not when there is just that one line.

    I've tried calling noutrefresh() and doupdate() instead of just
    refresh(), I've rebuilt the structure of the methods, and done all
    sorts of things. By writing debug-messages to a file, I've understood
    that the last addstr() DO output the line, but the refresh isn't
    working. Or something else isn't working.

    Can you help?

    I'll just append all my code here (for anyone to test), so you who
    doesn't want to read this humble beginners code can skip to another
    message. Thank you for your time.

    (So far I've understood, is that iMsg() and updateMsg() is wrong. Line
    71 and 92.)


    try:
    import curses
    except ImportError:
    print "Missing the Curses-library."
    print "Please install the curses-library correctly."
    SystemExit

    #---------------------------------------------------------------

    class Game:
    """The Game-object. Controls the windows, global settings and so
    on."""
    def __init__(self):
    self.mainwin = curses.initscr( )

    ## Some basic settings
    curses.noecho()
    curses.cbreak()
    self.mainwin.ke ypad(1)
    curses.curs_set (0)

    self.msg = Msg()
    self.msg.msg(["Welcome to The Game! Lets watch another fearless
    samurai", "get beaten bloody in the arena!"])

    self.mainwin.ad dstr(3,15, '+' + '-' * 62 + '+')
    self.mainwin.ad dstr(22,15, '+' + '-' * 62 + '+')
    self.mainwin.vl ine(4,15, '|', 18)
    self.mainwin.vl ine(4,78, '|', 18)


    movedir = {
    'up': {'x':0, 'y':-1},
    'down': {'x':0, 'y':+1},
    'right': {'x':+1, 'y':0},
    'left': {'x':-1, 'y':0},
    'downright': {'x':+1, 'y':+1},
    'upright': {'x':+1, 'y':-1},
    'downleft': {'x':-1, 'y':+1},
    'upleft': {'x':-1, 'y':-1}
    }

    walls = (
    ord('|'),
    ord('+'),
    ord('-')
    )

    #---------------------------------------------------------------

    class Msg:
    """The messagehandelin g and -bar system."""
    def __init__(self):
    self.msgs = []

    def printMore(self) :
    # Print the little #More#-sign
    game.mainwin.ad dch(1, 71, curses.ACS_BLOC K, curses.A_REVERS E)
    game.mainwin.ad dstr(1, 72, "More", curses.A_REVERS E)
    game.mainwin.ad dch(1, 76, curses.ACS_BLOC K, curses.A_REVERS E)

    def msg(self, msg):
    if isinstance(msg, str):
    self.msgs.appen d(msg)
    else:
    self.msgs = self.msgs + msg

    def ereasMsg(self):
    for count in range(0,2):
    game.mainwin.mo ve(count,0)
    game.mainwin.cl rtoeol()

    def updateMsg(self) :
    count = len(self.msgs)
    for msg in self.msgs: # Print one msg after
    another
    game.mainwin.ad dstr(0,0, msg) # Print the actual message
    if count 1: # If there are two or more
    laft, print a #More#-sign.
    count -= 1
    self.printMore( )
    game.mainwin.re fresh()
    while 1:
    next = game.mainwin.ge tch()
    if next == ord(' '):
    self.ereasMsg()
    break
    else:
    continue
    else:
    game.mainwin.re fresh()

    self.msgs = [] # When done, kill all messages
    return True

    def iMsg(self, msg):
    """Same as msg(), but the screen will refresh instantly.
    'i' is standing for Interface or Instant message."""
    if isinstance(msg, str):
    msg = [msg] # List'it!
    count = len(msg)
    for item in msg:
    if count 1:
    count -= 1
    self.printMore( )
    game.mainwin.ad dstr(0,0, item)
    game.mainwin.re fresh()
    while 1:
    next = game.mainwin.ge tch()
    if next == ord(' '):
    self.ereasMsg()
    break
    else:
    continue
    else:
    game.mainwin.ad dstr(0,0, item)

    return


    #---------------------------------------------------------------

    class Samurai:
    """This is the object of the mighty Samurai. Phe4r him. He can
    move.
    He can spawn. He will be able to kick som robo butt too,
    but not now."""
    def __init__(self):
    ## Configuring game values.
    self.loc = {
    "x": 20,
    "y": 8
    }
    self.samuraicha r = ord("X")

    # spawn
    game.mainwin.ad dch(self.loc['y'], self.loc['x'],
    self.samuraicha r)

    def move(self, dir, speed=1):
    # Move in dir speed number of times.
    for count in range(1, speed + 1):
    newX = self.loc['x'] + game.movedir[dir]['x']
    newY = self.loc['y'] + game.movedir[dir]['y']

    # Checks that all is clear.
    if game.mainwin.in ch(newY, newX) not in game.walls:

    # Delete old
    game.mainwin.ad dch(self.loc['y'], self.loc['x'], ' ')

    self.loc['x'] = newX
    self.loc['y'] = newY
    # Create a new character.
    game.mainwin.ad dch(self.loc['y'], self.loc['x'],
    self.samuraicha r)

    else:
    game.msg.iMsg(" You can't go there.")
    return

    #---------------------------------------------------------------

    def main():
    global game, player
    game = Game()
    player = Samurai()

    running = True


    while running:
    key_command = game.mainwin.ge tch()

    if key_command == ord('8'): ## Movement-commands
    player.move('up ')

    elif key_command == ord('2'):
    player.move('do wn')

    elif key_command == ord('4'):
    player.move('le ft')

    elif key_command == ord('6'):
    player.move('ri ght')

    elif key_command == ord('7'):
    player.move('up left')

    elif key_command == ord('9'):
    player.move('up right')

    elif key_command == ord('1'):
    player.move('do wnleft')

    elif key_command == ord('3'):
    player.move('do wnright')

    elif key_command == ord('Q'): ## Exit
    break

    elif key_command == ord('5'): ## Wait
    pass

    elif key_command == ord('x'): ## print location
    game.msg.iMsg(" X: " + str(player.loc['x']) + ", Y: " +
    str(player.loc['y']))

    elif key_command == ord('z'):
    strlist = ""
    for i in game.walls:
    strlist = strlist + str(i) + " "
    game.msg.iMsg(s trlist)

    elif key_command == ord('c'):
    for count in range(0,2):
    game.mainwin.mo ve(count,0)
    game.mainwin.cl rtoeol()

    else:
    game.msg.iMsg(" That is not a valid command.")

    if len(game.msg.ms gs) == 0: # If there are any msgs.
    game.mainwin.re fresh()
    else:
    game.msg.update Msg()

    game.msg.ereasM sg()


    if __name__ == "__main__":
    try:
    import psyco
    psyco.full()
    except ImportError:
    # Don't use something that doesn't exists.
    pass

    main()

    curses.nocbreak (); game.mainwin.ke ypad(0); curses.echo()
    curses.endwin()


    (The code is GPL'ed, Martin Ahnelöv 06)

  • Gasten

    #2
    Re: A curses-game I need help with.

    Hi. I would like to know why no one have answered my post

    ..
    It were my first post here (and on the Usenet overall), so I would like
    to know what I did wrong. Too´many spellingmisstak es? Shitty code? No
    one understands? No one got the answer? Should I wait a little longer?
    Thank you.

    Comment

    • Rob Wolfe

      #3
      Re: A curses-game I need help with.

      "Gasten" <operagasten@gm ail.comwrites:
      Can you help?
      I'm not a guru on curses by any means, but I've moved one line
      of your code and IMHO it works fine now.
      Look below for the code I've changed.
      I'll just append all my code here (for anyone to test), so you who
      doesn't want to read this humble beginners code can skip to another
      message. Thank you for your time.
      >
      (So far I've understood, is that iMsg() and updateMsg() is wrong. Line
      71 and 92.)
      >
      >
      try:
      import curses
      except ImportError:
      print "Missing the Curses-library."
      print "Please install the curses-library correctly."
      SystemExit
      >
      #---------------------------------------------------------------
      >
      class Game:
      """The Game-object. Controls the windows, global settings and so
      on."""
      def __init__(self):
      self.mainwin = curses.initscr( )
      >
      ## Some basic settings
      curses.noecho()
      curses.cbreak()
      self.mainwin.ke ypad(1)
      curses.curs_set (0)
      >
      self.msg = Msg()
      self.msg.msg(["Welcome to The Game! Lets watch another fearless
      samurai", "get beaten bloody in the arena!"])
      >
      self.mainwin.ad dstr(3,15, '+' + '-' * 62 + '+')
      self.mainwin.ad dstr(22,15, '+' + '-' * 62 + '+')
      self.mainwin.vl ine(4,15, '|', 18)
      self.mainwin.vl ine(4,78, '|', 18)
      >
      >
      movedir = {
      'up': {'x':0, 'y':-1},
      'down': {'x':0, 'y':+1},
      'right': {'x':+1, 'y':0},
      'left': {'x':-1, 'y':0},
      'downright': {'x':+1, 'y':+1},
      'upright': {'x':+1, 'y':-1},
      'downleft': {'x':-1, 'y':+1},
      'upleft': {'x':-1, 'y':-1}
      }
      >
      walls = (
      ord('|'),
      ord('+'),
      ord('-')
      )
      >
      #---------------------------------------------------------------
      >
      class Msg:
      """The messagehandelin g and -bar system."""
      def __init__(self):
      self.msgs = []
      >
      def printMore(self) :
      # Print the little #More#-sign
      game.mainwin.ad dch(1, 71, curses.ACS_BLOC K, curses.A_REVERS E)
      game.mainwin.ad dstr(1, 72, "More", curses.A_REVERS E)
      game.mainwin.ad dch(1, 76, curses.ACS_BLOC K, curses.A_REVERS E)
      >
      def msg(self, msg):
      if isinstance(msg, str):
      self.msgs.appen d(msg)
      else:
      self.msgs = self.msgs + msg
      >
      def ereasMsg(self):
      for count in range(0,2):
      game.mainwin.mo ve(count,0)
      game.mainwin.cl rtoeol()
      >
      def updateMsg(self) :
      count = len(self.msgs)
      for msg in self.msgs: # Print one msg after
      another
      game.mainwin.ad dstr(0,0, msg) # Print the actual message
      if count 1: # If there are two or more
      laft, print a #More#-sign.
      count -= 1
      self.printMore( )
      game.mainwin.re fresh()
      while 1:
      next = game.mainwin.ge tch()
      if next == ord(' '):
      self.ereasMsg()
      break
      else:
      continue
      else:
      game.mainwin.re fresh()
      >
      self.msgs = [] # When done, kill all messages
      return True
      >
      def iMsg(self, msg):
      """Same as msg(), but the screen will refresh instantly.
      'i' is standing for Interface or Instant message."""
      if isinstance(msg, str):
      msg = [msg] # List'it!
      count = len(msg)
      for item in msg:
      if count 1:
      count -= 1
      self.printMore( )
      game.mainwin.ad dstr(0,0, item)
      game.mainwin.re fresh()
      while 1:
      next = game.mainwin.ge tch()
      if next == ord(' '):
      self.ereasMsg()
      break
      else:
      continue
      else:
      game.mainwin.ad dstr(0,0, item)
      >
      return
      >
      >
      #---------------------------------------------------------------
      >
      class Samurai:
      """This is the object of the mighty Samurai. Phe4r him. He can
      move.
      He can spawn. He will be able to kick som robo butt too,
      but not now."""
      def __init__(self):
      ## Configuring game values.
      self.loc = {
      "x": 20,
      "y": 8
      }
      self.samuraicha r = ord("X")
      >
      # spawn
      game.mainwin.ad dch(self.loc['y'], self.loc['x'],
      self.samuraicha r)
      >
      def move(self, dir, speed=1):
      # Move in dir speed number of times.
      for count in range(1, speed + 1):
      newX = self.loc['x'] + game.movedir[dir]['x']
      newY = self.loc['y'] + game.movedir[dir]['y']
      >
      # Checks that all is clear.
      if game.mainwin.in ch(newY, newX) not in game.walls:
      >
      # Delete old
      game.mainwin.ad dch(self.loc['y'], self.loc['x'], ' ')
      >
      self.loc['x'] = newX
      self.loc['y'] = newY
      # Create a new character.
      game.mainwin.ad dch(self.loc['y'], self.loc['x'],
      self.samuraicha r)
      >
      else:
      game.msg.iMsg(" You can't go there.")
      return
      >
      #---------------------------------------------------------------
      >
      def main():
      global game, player
      game = Game()
      player = Samurai()
      >
      running = True
      >
      >
      while running:
      key_command = game.mainwin.ge tch()
      # I've moved erasing messages here
      game.msg.ereasM sg()
      >
      if key_command == ord('8'): ## Movement-commands
      player.move('up ')
      >
      elif key_command == ord('2'):
      player.move('do wn')
      >
      elif key_command == ord('4'):
      player.move('le ft')
      >
      elif key_command == ord('6'):
      player.move('ri ght')
      >
      elif key_command == ord('7'):
      player.move('up left')
      >
      elif key_command == ord('9'):
      player.move('up right')
      >
      elif key_command == ord('1'):
      player.move('do wnleft')
      >
      elif key_command == ord('3'):
      player.move('do wnright')
      >
      elif key_command == ord('Q'): ## Exit
      break
      >
      elif key_command == ord('5'): ## Wait
      pass
      >
      elif key_command == ord('x'): ## print location
      game.msg.iMsg(" X: " + str(player.loc['x']) + ", Y: " +
      str(player.loc['y']))
      >
      elif key_command == ord('z'):
      strlist = ""
      for i in game.walls:
      strlist = strlist + str(i) + " "
      game.msg.iMsg(s trlist)
      >
      elif key_command == ord('c'):
      for count in range(0,2):
      game.mainwin.mo ve(count,0)
      game.mainwin.cl rtoeol()
      >
      else:
      game.msg.iMsg(" That is not a valid command.")
      >
      if len(game.msg.ms gs) == 0: # If there are any msgs.
      game.mainwin.re fresh()
      else:
      game.msg.update Msg()
      >
      game.msg.ereasM sg()
      # I've moved this line
      # game.msg.eraseM sg
      >
      >
      if __name__ == "__main__":
      try:
      import psyco
      psyco.full()
      except ImportError:
      # Don't use something that doesn't exists.
      pass
      >
      main()
      >
      curses.nocbreak (); game.mainwin.ke ypad(0); curses.echo()
      curses.endwin()
      >
      >
      (The code is GPL'ed, Martin Ahnelöv 06)
      >
      --
      HTH,
      Rob

      Comment

      • Ben Finney

        #4
        Re: A curses-game I need help with.

        "Gasten" <operagasten@gm ail.comwrites:
        I would like to know what I did wrong. Too´many spellingmisstak es?
        Shitty code? No one understands? No one got the answer? Should I
        wait a little longer? Thank you.
        For my part, I skipped over your post because the code was far too long.

        If you have a problem you'd like a lot of people to look at, the most
        effective way is to make a short, complete example that demonstrates
        exactly the problem you're trying to understand.

        This approach has the bonus benefit that, in isolating the problem for
        this purpose, you often gain a better understanding of it yourself
        before posting it :-)

        --
        \ "Earth gets its price for what Earth gives us." -- James |
        `\ Russell Lowell |
        _o__) |
        Ben Finney

        Comment

        • Gasten

          #5
          Re: A curses-game I need help with.

          Ben Finney wrote:
          If you have a problem you'd like a lot of people to look at, the most
          effective way is to make a short, complete example that demonstrates
          exactly the problem you're trying to understand.
          I should make a demo, you say? I'm gonna do that next time. Thanks.

          Comment

          • Gasten

            #6
            Re: A curses-game I need help with.

            Rob Wolfe wrote:
            while running:
            key_command = game.mainwin.ge tch()
            >
            # I've moved erasing messages here
            game.msg.ereasM sg()
            Man... I didn't even think of that. It's embarassing. Thanks. It works
            perfect now. Again, thanks.

            Gasten

            Comment

            • Jia Lu

              #7
              Re: A curses-game I need help with.

              try:
              import curses
              except ImportError:
              print "Missing the Curses-library."
              print "Please install the curses-library correctly."
              SystemExit
              ~~~~~~~~~
              Does this work ? Maybe *raise SystemExit* ??

              Comment

              • Rainy

                #8
                Re: A curses-game I need help with.


                Gasten wrote:
                Rob Wolfe wrote:
                while running:
                key_command = game.mainwin.ge tch()
                # I've moved erasing messages here
                game.msg.ereasM sg()
                >
                Man... I didn't even think of that. It's embarassing. Thanks. It works
                perfect now. Again, thanks.
                >
                Gasten
                By the way, I also started doing a small rogue-like with a twist that
                you control monsters. I used curses, too. It's very small and
                incomplete, and I think there was a bug with monsters going through
                walls, but it may help you..

                You can find it at silmarill.org -programs -I, monster.

                I'd be interested in looking at your game, as it gets imporved, too, do
                you have a webpage for it yet? Please post..

                Comment

                Working...