LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-01-2013, 10:07 PM   #1
EnigmaticFellow
LQ Newbie
 
Registered: Jul 2012
Distribution: Arch Linux
Posts: 26

Rep: Reputation: Disabled
Problems with using the cl-charms library in Common Lisp


I've been having some difficulty with cl-charms when trying to convert a basic roguelike program from C into a Common Lisp version of it

Here is the Common Lisp version of it that I wrote.
Code:
(load "~/quicklisp/setup.lisp")
(ql:quickload "cl-charms")

(defconstant +map+ #2A(
  ("#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#")
  ("#" " " " " " " " " " " " " "#" " " " " " " " " " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " " " " " " " "#")
  ("#" " " " " " " " " " " " " "#" "#" "#" " " "#" "#" "#" "#")
  ("#" "#" "#" "#" " " "#" "#" "#" " " " " " " "#" " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " "#" " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " "#" " " " " "#")
  ("#" " " " " " " " " " " " " "#" " " " " " " " " " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " "#" " " " " "#")
  ("#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#")))

(defun move ()
  (cl-charms:keypad (cl-charms:initscr) 1)
  (cl-charms:curs-set 0)

  (setf y 1 x 1)

  (let ((c (cl-charms:getch)))
    (loop while (not (eq c 113)) do
      ;; printing map
      (loop for yy from 0 to 9 do
        (loop for xx from 0 to 14 do
          (cl-charms:mvaddstr y x (aref +map+ yy xx))))
      (if (and (eq c 107) (equal (aref +map+ (1- y) x) " "))
        (incf y -1))
      (if (and (eq c 106) (equal (aref +map+ (1+ y) x) " "))
        (incf y))
      (if (and (eq c 104) (equal (aref +map+ y (1- x)) " "))
        (incf x -1))
      (if (and (eq c 108) (equal (aref +map+ y (1+ x)) " "))
        (incf x))
      (if (and (eq c 98) (equal (aref +map+ (1+ y) (1- x)) " "))
        (progn (incf y) (incf x -1)))
      (if (and (eq c 121) (equal (aref +map+ (1- y) (1- x)) " "))
        (progn (incf y -1) (incf x -1)))
      (if (and (eq c 117) (equal (aref +map+ (1- y) (1+ x)) " "))
        (progn (incf y -1) (incf x)))
      (if (and (eq c 110) (equal (aref +map+ (1+ y) (1+ x)) " "))
        (progn (incf y) (incf x)))

      (cl-charms:mvaddstr y x "@"))))

  (cl-charms:endwin))
And here's the C source code I translated it from.
Code:
#include <curses.h>

char *map[] = 
{
    "###############",
    "#      #      #",
    "#             #",
    "#      ### ####",
    "#### ###   #  #",
    "#          #  #",
    "#          #  #",
    "#             #",
    "#          #  #",
    "###############"
};

int main()
{
    //initialize curses
    keypad(initscr(), 1);
    curs_set(0);

    //player's starting coordinates
    int y = 1;
    int x = 1;

    //placeholder for capturing keyboard input
    char c;

    do
    {
        //draw map
        for(int yy = 0; yy < 10; yy++)
        {
            for(int xx = 0; xx < 15; xx++)
                 mvaddch(yy, xx, map[yy][xx]);
        }

        //move player if there is no wall in the way
        if('k' == c && ' ' == map[y - 1][x])
        {
            y--;
        }
        if('j' == c && ' ' == map[y + 1][x])
        {
            y++;
        }
        if('h' == c && ' ' == map[y][x - 1])
        {
            x--;
        }
        if('l' == c && ' ' == map[y][x + 1])
        {
            x++;
        }
        if('b' == c && ' ' == map[y + 1][x - 1])
        {
            y++;
            x--;
        }
        if('y' == c && ' ' == map[y - 1][x - 1])
        {
            y--;
            x--;
        }
        if('u' == c && ' ' == map[y - 1][x + 1])
        {
            y--;
            x++;
        }
        if('n' == c && ' ' == map[y + 1][x + 1])
        {
            y++;
            x++;
        }

        //draw character
        mvaddch(y, x, '@');

    } while(('q' != (c = getch())));
    
    //clean up after we've finished using curses
    return endwin();
}
When I try to run the program I wrote with "clisp -i basic-movement.lisp", I get this error message.
Code:
READ from #<INPUT BUFFERED FILE-STREAM CHARACTER #P"basic-movement.lisp" @48>: an object cannot start with #\)
I don't really understand the error message I got from clisp, and any help to get this program into working order would be greatly appreciated.
 
Old 07-01-2013, 11:05 PM   #2
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
I don't really understand the error message I got from clisp
The error is complaining about an extra close paren. You should use an editor with that can indent based on parens for you. I re-indented your code to make it easier to see the improper nesting. There are some other problems which I commented on in blue below:


Code:
(defun move ()
  (cl-charms:keypad (cl-charms:initscr) 1)
  (cl-charms:curs-set 0)

  ; setting unbound variables has implementation defined behaviour,
  ; I would consider it bad style, use let for locals, defvar for globals
  (setf y 1 x 1)

  ; the getch call is outside the loop so the program only reads 1 char,
  ; and then just tests it again and again...
  (let ((c (cl-charms:getch)))
    (loop while (not (eq c 113)) do
          ;; printing map
          (loop for yy from 0 to 9 do
                (loop for xx from 0 to 14 do
                      (cl-charms:mvaddstr y x (aref +map+ yy xx)))) ; have x & y instead of xx & yy
          (if (and (eq c 107) (equal (aref +map+ (1- y) x) " "))
              (incf y -1))
          (if (and (eq c 106) (equal (aref +map+ (1+ y) x) " "))
              (incf y))
          (if (and (eq c 104) (equal (aref +map+ y (1- x)) " "))
              (incf x -1))
          (if (and (eq c 108) (equal (aref +map+ y (1+ x)) " "))
              (incf x))
          ; since you have no else branch, use when instead of if to avoid the progn
          ; although probably the whole series of ifs should replaced with a cond or case
          ; (similarly, the C version should use switch)
          (if (and (eq c 98) (equal (aref +map+ (1+ y) (1- x)) " "))
              (progn (incf y) (incf x -1)))
          (if (and (eq c 121) (equal (aref +map+ (1- y) (1- x)) " "))
              (progn (incf y -1) (incf x -1)))
          (if (and (eq c 117) (equal (aref +map+ (1- y) (1+ x)) " "))
              (progn (incf y -1) (incf x)))
          (if (and (eq c 110) (equal (aref +map+ (1+ y) (1+ x)) " "))
              (progn (incf y) (incf x)))

          (cl-charms:mvaddstr y x "@")))) ; closed too much here, assuming the endwin should be inside the function

(cl-charms:endwin))
 
Old 07-02-2013, 07:22 AM   #3
EnigmaticFellow
LQ Newbie
 
Registered: Jul 2012
Distribution: Arch Linux
Posts: 26

Original Poster
Rep: Reputation: Disabled
Thanks for the help ntubski. After reading your post and fixing a few errors I overlooked, I was able to get the program working. All I need to do now is refactor some parts of it.

For those of you curious, here's the working version.
Code:
(load "~/quicklisp/setup.lisp")
(ql:quickload "cl-charms")

(defconstant +map+ #2A(
  ("#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#")
  ("#" " " " " " " " " " " " " "#" " " " " " " " " " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " " " " " " " "#")
  ("#" " " " " " " " " " " " " "#" "#" "#" " " "#" "#" "#" "#")
  ("#" "#" "#" "#" " " "#" "#" "#" " " " " " " "#" " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " "#" " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " "#" " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " " " " " " " "#")
  ("#" " " " " " " " " " " " " " " " " " " " " "#" " " " " "#")
  ("#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#")))

(defun move ()
  (cl-charms:keypad (cl-charms:initscr) 1)
  (cl-charms:curs-set 0)

  (let ((y 1) (x 1) c)
    (loop while (not (eq c 113)) do
      ;; printing map                                                       
      (loop for yy from 0 to 9 do
        (loop for xx from 0 to 14 do
          (cl-charms:mvaddstr yy xx (aref +map+ yy xx))))
      (if (and (eq c 107) (equal (aref +map+ (1- y) x) " "))
        (incf y -1))
      (if (and (eq c 106) (equal (aref +map+ (1+ y) x) " "))
        (incf y))
      (if (and (eq c 104) (equal (aref +map+ y (1- x)) " "))
        (incf x -1))
      (if (and (eq c 108) (equal (aref +map+ y (1+ x)) " "))
        (incf x))
      (if (and (eq c 98) (equal (aref +map+ (1+ y) (1- x)) " "))
        (progn (incf y) (incf x -1)))
      (if (and (eq c 121) (equal (aref +map+ (1- y) (1- x)) " "))
        (progn (incf y -1) (incf x -1)))
      (if (and (eq c 117) (equal (aref +map+ (1- y) (1+ x)) " "))
        (progn (incf y -1) (incf x)))
      (if (and (eq c 110) (equal (aref +map+ (1+ y) (1+ x)) " "))
        (progn (incf y) (incf x)))

    (cl-charms:mvaddstr y x "@")
    (setf c (cl-charms:getch))))

  (cl-charms:endwin))

(defun main ()
  (move)
  (exit))

Last edited by EnigmaticFellow; 07-02-2013 at 07:25 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Common Lisp: CLOS and with-slots hydraMax Programming 1 06-10-2013 08:59 PM
[SOLVED] struggling with a function in Common Lisp sycamorex Programming 2 10-10-2011 04:04 AM
Common Lisp tuning for Gedit entz Linux - Software 12 08-30-2010 08:46 AM
Common Lisp functions. zaxonus Programming 2 07-09-2010 04:30 PM
Programming Ideas in Common Lisp Trizon Programming 1 03-03-2008 02:07 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:06 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration