unexist.dev

Changeset 307:5d2af4d79357

Merged heads
author unexist
date Fri, 20 Jan 2012 18:21:15 +0100
parents 899bf34a4e2d (current diff) 05459944b0e6 (diff)
children 02da21c960a0
files
diffstat 12 files changed, 399 insertions(+), 239 deletions(-) [+]
line wrap: on
line diff
--- a/mud/driver.c	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/driver.c	Fri Jan 20 18:21:15 2012 +0100
@@ -12,33 +12,78 @@
 
 #include "mud.h"
 
-/* DriverReadPath {{{ */
+static char *directions[] = { "n", "ne", "nw", "e", "w", "s", "se", "sw" };
+
+/* DriverSetPosition {{{ */
 static void
-DriverReadPath(MudDriver *md)
+DriverSetPosition(MudDriver *md)
 {
-  struct dirent **names;
-  int n;
+  char oldpath[255] = { 0 }, newpath[255] = { 0 };
 
   assert(md);
 
+  /* Set location symlink */
+  snprintf(oldpath, sizeof(oldpath), "%s/%s/player.lua",
+    MUD_PLAYER, md->player);
+
+  snprintf(newpath, sizeof(newpath), "%s/%s.player",
+    md->path, md->player);
+
+  if(0 != symlink(oldpath, newpath))
+    {
+      perror("symlink");
+      exit(1);
+    }
+} /* }}} */
+
+/* DriverUpdatePosition {{{ */
+static void
+DriverUpdatePosition(MudDriver *md)
+{
+  char path[255] = { 0 };
+  struct dirent **names;
+  int nnames, i, j;
+
+  assert(md);
+
+  /* Reset gates */
+  md->gates = 0;
+
   /* Sort files in dir */
-  if(0 > (n = scandir(md->path, &names, NULL, alphasort)))
+  if(0 > (nnames = scandir(md->path, &names, NULL, alphasort)))
     {
       perror("scandir");
       exit(1);
     }
 
-  /* Dump content */
-  while(n--)
+  /* Read exits */
+  for(i = 0; i < nnames; i++)
     {
-      printf("%s\n", names[n]->d_name);
-      free(names[n]);
+      /* Check directions */
+      for(j = 0; 8 > j; j++)
+        if(0 == strcmp(names[i]->d_name, directions[j]))
+          {
+            md->gates |= (1 << j);
+            break;
+          }
+
+      free(names[i]);
     }
 
+  /* Load place description */
+  snprintf(path, sizeof(path), "%s/place.lua", md->path);
+
+  mudLuaLoadFile(md->ml, path);
+
+  if(md->location)    free(md->location);
+  if(md->description) free(md->description);
+
+  md->location    = mudLuaGetString(md->ml, "name");
+  md->description = mudLuaGetString(md->ml, "description");
+
   free(names);
 } /* }}} */
 
-
 /* Public */
 
  /** mudDriverNew {{{
@@ -47,7 +92,7 @@
   **/
 
 MudDriver *
-mudDriverNew(void)
+mudDriverNew(char *player)
 {
   MudDriver *md = NULL;
 
@@ -58,23 +103,52 @@
       exit(1);
     }
 
-  md->path = strdup(MUD_ENTRY);
+  snprintf(md->path, sizeof(md->path), "%s", MUD_ENTRY);
+  md->player = strdup(player);
+
+  /* Create lua vm */
+  md->ml = mudLuaNew();
+
+  /* Handle position in fs */
+  DriverUpdatePosition(md);
+  DriverSetPosition(md);
 
   return md;
 } /* }}} */
 
-/* mudDriverUpdateLocation {{{ */
+ /** mudDriverMove {{{
+  * Move to position
+  * @param[in]  md   A #MudDriver
+  * @param[in]  dir  A #MudDirection
+  **/
+
 void
-mudDriverMarkPath(MudDriver *md)
+mudDriverMove(MudDriver *md,
+  MudDirection dir)
 {
+  char path[255] = { 0 };
+
   assert(md);
 
-  /* Set location symlink */
-  if(symlink(md->path, md->path))
+  /* Remove old location */
+  snprintf(path, sizeof(path), "%s/%s.player",
+    md->path, md->player);
+
+  if(unlink(path))
     {
-      perror("symlink");
+      perror("unlink");
       exit(1);
     }
+
+  /* Move to new location */
+  snprintf(path, sizeof(path), "%s/%s",
+    md->path, directions[dir]);
+
+  memcpy(md->path, path, sizeof(path));
+
+  /* Set location symlink */
+  DriverSetPosition(md);
+  DriverUpdatePosition(md);
 } /* }}} */
 
  /** mudDriverKill {{{
@@ -85,21 +159,23 @@
 void
 mudDriverKill(MudDriver *md)
 {
+  char path[255] = { 0 };
+
   assert(md);
 
-  if(md->path)
+  snprintf(path, sizeof(path), "%s/%s.player",
+    md->player, md->path);
+
+  /* Check for location symlink */
+  if(unlink(path))
     {
-      /* Check for location symlink */
-      if(unlink(md->path))
-        {
-          perror("unlink");
-          exit(1);
-        }
-
-      free(md->path);
+      perror("unlink");
+      exit(1);
     }
 
-  closedir(md->dir);
+  /* Tidy up */
+  if(md->player) free(md->player);
+  if(md->ml)     mudLuaKill(md->ml);
 
   free(md);
 } /* }}} */
--- a/mud/lex.c	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/lex.c	Fri Jan 20 18:21:15 2012 +0100
@@ -360,8 +360,8 @@
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
 
-#define YY_NUM_RULES 23
-#define YY_END_OF_BUFFER 24
+#define YY_NUM_RULES 21
+#define YY_END_OF_BUFFER 22
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -369,13 +369,13 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[49] =
+static yyconst flex_int16_t yy_accept[47] =
     {   0,
-        0,    0,   24,   23,   21,   22,   19,   20,   19,   10,
-        3,   19,   19,   19,    1,    5,   19,    9,    7,   21,
-       19,   20,   16,   19,   19,   19,   19,    2,    8,    4,
-        6,   19,   17,   19,   19,   19,   19,   11,   19,   19,
-       18,   13,   15,   12,   19,   19,   14,    0
+        0,    0,   22,   21,   19,   20,   17,   18,   17,    4,
+       17,   17,   17,    1,    6,   17,    5,   19,   17,   18,
+       14,   17,   17,   17,   17,    2,    3,    7,    8,   17,
+       15,   17,   17,   17,   17,    9,   17,   17,   16,   11,
+       13,   10,   17,   17,   12,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -386,13 +386,13 @@
         1,    2,    1,    1,    1,    1,    1,    1,    4,    1,
         1,    1,    1,    1,    1,    1,    1,    5,    5,    5,
         5,    5,    5,    5,    5,    5,    5,    1,    1,    1,
-        1,    1,    1,    1,    6,    4,    4,    7,    8,    9,
-       10,    4,   11,    4,   12,    4,   13,   14,   15,    4,
-        4,   16,   17,   18,   19,   20,   21,   22,    4,    4,
-        1,    1,    1,    1,    1,    1,   23,    4,    4,   24,
+        1,    1,    1,    1,    6,    4,    4,    4,    7,    8,
+        9,    4,   10,    4,   11,    4,   12,   13,   14,    4,
+        4,   15,   16,   17,    4,   18,   19,   20,    4,    4,
+        1,    1,    1,    1,    1,    1,   21,    4,    4,    4,
 
-       25,   26,   27,    4,   28,    4,   29,    4,   30,   31,
-       32,    4,    4,   33,   34,   35,   36,   37,   38,   39,
+       22,   23,   24,    4,   25,    4,   26,    4,   27,   28,
+       29,    4,    4,   30,   31,   32,    4,   33,   34,   35,
         4,    4,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -410,68 +410,66 @@
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[40] =
+static yyconst flex_int32_t yy_meta[36] =
     {   0,
         1,    1,    1,    2,    1,    2,    2,    2,    2,    2,
         2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
         2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-        2,    2,    2,    2,    2,    2,    2,    2,    2
+        2,    2,    2,    2,    2
     } ;
 
-static yyconst flex_int16_t yy_base[50] =
+static yyconst flex_int16_t yy_base[48] =
     {   0,
-        0,    0,   87,  101,   84,  101,    0,   80,   22,    0,
-       19,   26,   32,   30,   41,   42,   41,    0,    0,   82,
-        0,   41,    0,   42,   36,   32,   35,    0,    0,   46,
-        0,   43,    0,   61,   62,   68,   62,    0,   70,   70,
-        0,    0,    0,    0,   68,   75,    0,  101,   43
-    } ;
-
-static yyconst flex_int16_t yy_def[50] =
-    {   0,
-       48,    1,   48,   48,   48,   48,   49,   48,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   48,
-       49,   48,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,    0,   48
+        0,    0,   86,   94,   78,   94,    0,   74,   19,   17,
+       23,   29,   27,   37,   38,   44,    0,   41,    0,   37,
+        0,   40,   33,   30,   32,    0,    0,   59,    0,   56,
+        0,   56,   57,   63,   60,    0,   68,   66,    0,    0,
+        0,    0,   64,   71,    0,   94,   39
     } ;
 
-static yyconst flex_int16_t yy_nxt[141] =
+static yyconst flex_int16_t yy_def[48] =
+    {   0,
+       46,    1,   46,   46,   46,   46,   47,   46,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   46,   47,   46,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,    0,   46
+    } ;
+
+static yyconst flex_int16_t yy_nxt[130] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,    7,    7,   15,    7,    7,   16,   17,   18,    7,
-       19,    7,    9,   10,   11,   12,   13,   14,    7,    7,
-       15,    7,    7,   16,   17,   18,    7,   19,    7,   23,
-       24,   25,   26,   27,   21,   22,   32,   34,   28,   30,
-       35,   36,   37,   38,   39,   33,   23,   24,   25,   26,
-       27,   29,   31,   32,   34,   28,   30,   35,   36,   37,
-       38,   39,   33,   40,   41,   42,   43,   44,   29,   31,
-       45,   46,   47,   20,   22,   20,   48,   48,   48,   48,
-       40,   41,   42,   43,   44,   48,   48,   45,   46,   47,
+        7,    7,   14,    7,    7,   15,   16,    7,   17,    7,
+        9,   10,   11,   12,   13,    7,    7,   14,    7,    7,
+       15,   16,    7,   17,    7,   21,   22,   23,   24,   25,
+       19,   20,   18,   26,   28,   32,   33,   34,   35,   30,
+       21,   22,   23,   24,   25,   27,   29,   31,   26,   28,
+       32,   33,   34,   35,   30,   36,   37,   38,   39,   40,
+       27,   29,   31,   41,   42,   43,   44,   45,   20,   18,
+       36,   37,   38,   39,   40,   46,   46,   46,   41,   42,
+       43,   44,   45,    3,   46,   46,   46,   46,   46,   46,
 
-        3,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46
     } ;
 
-static yyconst flex_int16_t yy_chk[141] =
+static yyconst flex_int16_t yy_chk[130] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    9,
-       11,   12,   13,   14,   49,   22,   17,   24,   15,   16,
-       25,   26,   27,   30,   32,   17,    9,   11,   12,   13,
-       14,   15,   16,   17,   24,   15,   16,   25,   26,   27,
-       30,   32,   17,   34,   35,   36,   37,   39,   15,   16,
-       40,   45,   46,   20,    8,    5,    3,    0,    0,    0,
-       34,   35,   36,   37,   39,    0,    0,   40,   45,   46,
+        1,    1,    1,    1,    1,    9,   10,   11,   12,   13,
+       47,   20,   18,   14,   15,   22,   23,   24,   25,   16,
+        9,   10,   11,   12,   13,   14,   15,   16,   14,   15,
+       22,   23,   24,   25,   16,   28,   30,   32,   33,   34,
+       14,   15,   16,   35,   37,   38,   43,   44,    8,    5,
+       28,   30,   32,   33,   34,    3,    0,    0,   35,   37,
+       38,   43,   44,   46,   46,   46,   46,   46,   46,   46,
 
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -494,7 +492,7 @@
 
 #define YY_INPUT(buf,result,max_size) \
   result = (fgets(buf, max_size, stdin)) ? strlen(buf) : YY_NULL;
-#line 498 "lex.c"
+#line 496 "lex.c"
 
 #define INITIAL 0
 
@@ -678,7 +676,7 @@
     
 #line 8 "lex.l"
 
-#line 682 "lex.c"
+#line 680 "lex.c"
 
 	if ( !(yy_init) )
 		{
@@ -731,13 +729,13 @@
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 49 )
+				if ( yy_current_state >= 47 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_base[yy_current_state] != 101 );
+		while ( yy_base[yy_current_state] != 94 );
 
 yy_find_action:
 		yy_act = yy_accept[yy_current_state];
@@ -774,110 +772,100 @@
 case 3:
 YY_RULE_SETUP
 #line 11 "lex.l"
-yylval.number = MUD_EAST;       return DIRECTION;
+yylval.number = MUD_NORTHWEST;  return DIRECTION;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
 #line 12 "lex.l"
-yylval.number = MUD_SOUTHEAST;  return DIRECTION;
+yylval.number = MUD_EAST;       return DIRECTION;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
 #line 13 "lex.l"
-yylval.number = MUD_SOUTH;      return DIRECTION;
+yylval.number = MUD_WEST;       return DIRECTION;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
 #line 14 "lex.l"
-yylval.number = MUD_SOUTHWEST;  return DIRECTION;
+yylval.number = MUD_SOUTH;      return DIRECTION;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
 #line 15 "lex.l"
-yylval.number = MUD_WEST;       return DIRECTION;
+yylval.number = MUD_SOUTHEAST;  return DIRECTION;
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
 #line 16 "lex.l"
-yylval.number = MUD_NORTHWEST;  return DIRECTION;
+yylval.number = MUD_SOUTHWEST;  return DIRECTION;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 17 "lex.l"
-yylval.number = MUD_UP;         return DIRECTION;
+#line 18 "lex.l"
+return SEE;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 18 "lex.l"
-yylval.number = MUD_DOWN;       return DIRECTION;
+#line 19 "lex.l"
+return TAKE;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
 #line 20 "lex.l"
-return SEE;
+return GIVE;
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
 #line 21 "lex.l"
-return TAKE;
+return EXAMINE;
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
 #line 22 "lex.l"
-return GIVE;
+return INTO;
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
 #line 23 "lex.l"
-return EXAMINE;
+return AT;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
 #line 24 "lex.l"
-return INTO;
+return TO;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
 #line 25 "lex.l"
-return AT;
+return FROM;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 26 "lex.l"
-return TO;
+#line 27 "lex.l"
+yylval.string = strdup(yytext); return OBJECT;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 27 "lex.l"
-return FROM;
+#line 28 "lex.l"
+yylval.number = atoi(yytext);   return NUMBER;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
 #line 29 "lex.l"
-yylval.string = strdup(yytext); return OBJECT;
+/* Ignore whitespaces */
 	YY_BREAK
 case 20:
+/* rule 20 can match eol */
 YY_RULE_SETUP
 #line 30 "lex.l"
-yylval.number = atoi(yytext);   return NUMBER;
+/* Ignore end of line */
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
 #line 31 "lex.l"
-/* Ignore whitespaces */
-	YY_BREAK
-case 22:
-/* rule 22 can match eol */
-YY_RULE_SETUP
-#line 32 "lex.l"
-/* Ignore end of line */
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 33 "lex.l"
 ECHO;
 	YY_BREAK
-#line 881 "lex.c"
+#line 869 "lex.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -1169,7 +1157,7 @@
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 49 )
+			if ( yy_current_state >= 47 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1197,11 +1185,11 @@
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 49 )
+		if ( yy_current_state >= 47 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 48);
+	yy_is_jam = (yy_current_state == 46);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -1875,7 +1863,7 @@
 
 #define YYTABLES_NAME "yytables"
 
-#line 33 "lex.l"
+#line 31 "lex.l"
 
 
 
--- a/mud/lex.l	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/lex.l	Fri Jan 20 18:21:15 2012 +0100
@@ -8,14 +8,12 @@
 %%
 n   yylval.number = MUD_NORTH;      return DIRECTION;
 ne  yylval.number = MUD_NORTHEAST;  return DIRECTION;
+nw  yylval.number = MUD_NORTHWEST;  return DIRECTION;
 e   yylval.number = MUD_EAST;       return DIRECTION;
+w   yylval.number = MUD_WEST;       return DIRECTION;
+s   yylval.number = MUD_SOUTH;      return DIRECTION;
 se  yylval.number = MUD_SOUTHEAST;  return DIRECTION;
-s   yylval.number = MUD_SOUTH;      return DIRECTION;
 sw  yylval.number = MUD_SOUTHWEST;  return DIRECTION;
-w   yylval.number = MUD_WEST;       return DIRECTION;
-nw  yylval.number = MUD_NORTHWEST;  return DIRECTION;
-u   yylval.number = MUD_UP;         return DIRECTION;
-d   yylval.number = MUD_DOWN;       return DIRECTION;
 
 see     return SEE;
 take    return TAKE;
--- a/mud/lua.c	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/lua.c	Fri Jan 20 18:21:15 2012 +0100
@@ -14,12 +14,11 @@
 
  /** mudLuaNew {{{
   * Create a new Lua state
-  * @param[in]  path  A path to a file
   * @return Returns a #MudLua.
   **/
 
 MudLua *
-mudLuaNew(const char *path)
+mudLuaNew(void)
 {
   MudLua *ml = NULL;
 
@@ -35,6 +34,21 @@
 
   luaL_openlibs(ml->l);
 
+  return ml;
+} /* }}} */
+
+ /** mudLuaLoadFile {{{
+  * Load a file into the vm
+  * @param[in]  ml    A #MudLua
+  * @param[in]  path  Path to file
+  **/
+
+void
+mudLuaLoadFile(MudLua *ml,
+  const char *path)
+{
+  assert(ml);
+
   /* Load file from path */
   if(luaL_loadfile(ml->l, path))
     {
@@ -50,8 +64,6 @@
         (char *)lua_tostring(ml->l, -1));
       exit(1);
     }
-
-  return ml;
 } /* }}} */
 
  /** mudLuaGetString {{{
--- a/mud/main.c	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/main.c	Fri Jan 20 18:21:15 2012 +0100
@@ -105,7 +105,7 @@
 
           if(mudPlayerAuth(mp))
             {
-              mudPlayerSee(mp);
+              mudPlayerMap(mp);
               mudPlayerHandler(mp);
             }
 
--- a/mud/mud.h	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/mud.h	Fri Jan 20 18:21:15 2012 +0100
@@ -42,31 +42,31 @@
 /* Parameters */
 #define MUD_NAME        "Mud"
 #define MUD_VERSION      "0.0"
-#define MUD_PORT        1111
+#define MUD_PORT         1111
 #define MUD_CONNECTIONS  10
-#define MUD_WORLD        "world"
-#define MUD_OBJECTS      "objects"
-#define MUD_PLAYER       "player"
-#define MUD_ENTRY        "world"
+#define MUD_WORLD        "/home/unexist/projects/shreds/mud/world"
+#define MUD_OBJECTS      "/home/unexist/projects/shreds/mud/projects"
+#define MUD_PLAYER       "/home/unexist/projects/shreds/mud/player"
+#define MUD_ENTRY        "/home/unexist/projects/shreds/mud/world"
 
 /* Typedef {{{ */
 typedef enum muddirection_t {
-  MUD_NORTH,
+  MUD_NORTH, 
   MUD_NORTHEAST,
+  MUD_NORTHWEST,
   MUD_EAST,
-  MUD_SOUTHEAST,
+  MUD_WEST,
   MUD_SOUTH,
-  MUD_SOUTHWEST,
-  MUD_WEST,
-  MUD_NORTHWEST,
-  MUD_UP,
-  MUD_DOWN
+  MUD_SOUTHEAST,
+  MUD_SOUTHWEST
 } MudDirection;
 
 typedef struct muddriver_t
 {
-  DIR  *dir;
-  char *path;
+  char            path[255];
+  char            *player, *location, *description;
+  int             gates;
+  struct mudlua_t *ml;
 } MudDriver;
 
 typedef struct mudlua_t
@@ -78,8 +78,6 @@
 {
   int                fd;
   struct muddriver_t *md;
-  struct mudlua_t    *ml;
-  char               *name;
 } MudPlayer;
 /* }}} */
 
@@ -90,12 +88,14 @@
 /* }}} */
 
 /* driver.c {{{ */
-MudDriver *mudDriverNew(void);
-void mudDriverKill(MudDriver *driver);
+MudDriver *mudDriverNew(char *name);
+void mudDriverMove(MudDriver *md, MudDirection dir);
+void mudDriverKill(MudDriver *md);
 /* }}} */
 
 /* lua.c {{{ */
-MudLua *mudLuaNew(const char *path);
+MudLua *mudLuaNew(void);
+void mudLuaLoadFile(MudLua *ml, const char *path);
 char *mudLuaGetString(MudLua *ml, const char *name);
 void mudLuaSetString(MudLua *ml, const char *name, char *val);
 void mudLuaDumpStack(MudLua *ml);
@@ -107,7 +107,7 @@
 void mudPlayerHandler(MudPlayer *mp);
 int mudPlayerAuth(MudPlayer *mp);
 void mudPlayerMove(MudPlayer *mp, MudDirection dir);
-void mudPlayerSee(MudPlayer *mp);
+void mudPlayerMap(MudPlayer *mp);
 int mudPlayerSend(MudPlayer *mp, const char *format, ...);
 int mudPlayerRecv(MudPlayer *mp, char **recv);
 void mudPlayerKill(MudPlayer *mp);
--- a/mud/parser.c	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/parser.c	Fri Jan 20 18:21:15 2012 +0100
@@ -1391,7 +1391,7 @@
 /* Line 1806 of yacc.c  */
 #line 43 "parser.y"
     {
-      mudPlayerSee((MudPlayer *)parm);
+      mudPlayerMap((MudPlayer *)parm);
     }
     break;
 
@@ -1429,14 +1429,13 @@
     {
       printf("\tERROR\n");
       yyerrok;
-
     }
     break;
 
 
 
 /* Line 1806 of yacc.c  */
-#line 1440 "parser.c"
+#line 1439 "parser.c"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1667,7 +1666,7 @@
 
 
 /* Line 2067 of yacc.c  */
-#line 65 "parser.y"
+#line 64 "parser.y"
 
 
 extern void 
--- a/mud/parser.y	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/parser.y	Fri Jan 20 18:21:15 2012 +0100
@@ -41,7 +41,7 @@
     }
   | SEE
     {
-      mudPlayerSee((MudPlayer *)parm);
+      mudPlayerMap((MudPlayer *)parm);
     }
   | TAKE OBJECT
     {
@@ -59,7 +59,6 @@
     {
       printf("\tERROR\n");
       yyerrok;
-
     }
   ;
 %%
--- a/mud/player.c	Fri Jan 20 18:21:07 2012 +0100
+++ b/mud/player.c	Fri Jan 20 18:21:15 2012 +0100
@@ -15,6 +15,8 @@
 
 #include "mud.h"
 
+#define GATE(FLAG,SYM) (mp->md->gates & (1 << MUD_##FLAG) ? SYM : " ")
+
  /** mudPlayerNew {{{
   * Creates a new player
   * @param[in]  fd  Socket descriptor
@@ -79,9 +81,11 @@
       /* Check if player exists */
       if(0 == access(path, R_OK))
         {
+          mp->md = mudDriverNew(name);
+
           /* Load lua vm and player file */
-          mp->ml = mudLuaNew(path);
-          check  = mudLuaGetString(mp->ml, "password");
+          mudLuaLoadFile(mp->md->ml, path);
+          check = mudLuaGetString(mp->md->ml, "password");
 
           /* Convert digest to hex (echo -n "test" | openssl sha1) */
           SHA1((const unsigned char *)password, strlen(password), md);
@@ -92,9 +96,6 @@
           /* Compare passwords */
           if(0 == strcmp(check, digest)) 
             {
-              mp->name = strdup(name);
-              mp->md   = mudDriverNew();
-
               ret++;
 
               mudPlayerSend(mp, "Welcome back, %s!\n", name);
@@ -123,7 +124,7 @@
   assert(mp);
 
   /* Call the parser */
-  for(;;) yyparse((void *)mp);  
+  for(;;) yyparse((void *)mp);
 } /* }}} */
 
  /** mudPlayerMove {{{
@@ -138,28 +139,45 @@
 {
   assert(mp);
 
-  printf("DEBUG %s:%d\n", __FILE__, __LINE__);
+  /* Check if gate exists */
+  if(mp->md->gates & (1 << dir))
+    {
+      mudDriverMove(mp->md, dir);
+      mudPlayerMap(mp);
+    }
+  else mudPlayerSend(mp, "Looks like the door is hidden, I cannot find it.\n");
 } /* }}} */
 
- /** mudPlayerSee {{{
-  * Show what a player sees
+ /** mudPlayerMap {{{
+  * Shows navigation for the user
   * @param[in]  mp  A #MudPlayer
   **/
 
 void
-mudPlayerSee(MudPlayer *mp)
+mudPlayerMap(MudPlayer *mp)
 {
   assert(mp);
+  assert(mp->md);
 
   mudPlayerSend(mp, "\nYou are here:\n\n");
 
-  mudPlayerSend(mp, " I   I   I       Marketplace\n");
-  mudPlayerSend(mp, "  \\  |  /        Foobar............................\n");
-  mudPlayerSend(mp, "   \\ | /         ......................................\n");
-  mudPlayerSend(mp, "I -- @ -- I      .........................................\n");
-  mudPlayerSend(mp, "   / | \\         Exits: N E W S\n");
-  mudPlayerSend(mp, "  /  |  \\\n");
-  mudPlayerSend(mp, " I   I   I\n\n");
+  mudPlayerSend(mp, " %s   %s   %s       %s\n",
+    GATE(NORTHWEST, "NW"), GATE(NORTH, "N"),
+    GATE(NORTHEAST, "NE"), mp->md->location);
+  mudPlayerSend(mp, "  %s  |  %s        %s\n",
+    GATE(NORTHWEST, "\\"), GATE(NORTHEAST, "\\"),
+    mp->md->description);
+  mudPlayerSend(mp, "   %s | %s\n",
+    GATE(NORTHWEST, "\\"), GATE(NORTHEAST, "\\"));
+  mudPlayerSend(mp, "%s -- @ -- %s\n",
+    GATE(WEST, "W"), GATE(EAST, "E"));
+  mudPlayerSend(mp, "   %s | %s\n",
+    GATE(SOUTHWEST, "/"), GATE(SOUTHEAST, "\\"));
+  mudPlayerSend(mp, "  %s  |  %s\n",
+    GATE(SOUTHWEST, "/"), GATE(SOUTHEAST, "\\"));
+  mudPlayerSend(mp, " %s   %s   %s\n\n",
+    GATE(SOUTHWEST, "SW"), GATE(SOUTH, "S"),
+    GATE(SOUTHEAST, "SE"));
 } /* }}} */
 
  /** mudPlayerSend {{{
@@ -243,9 +261,7 @@
 
   /* Tidy up */
   close(mp->fd);
-  if(mp->md)   mudDriverKill(mp->md);
-  if(mp->ml)   mudLuaKill(mp->ml);
-  if(mp->name) free(mp->name);
+  if(mp->md) mudDriverKill(mp->md);
 
   free(mp);
 } /* }}} */
--- a/studies/cmp/k2.py	Fri Jan 20 18:21:07 2012 +0100
+++ b/studies/cmp/k2.py	Fri Jan 20 18:21:15 2012 +0100
@@ -41,6 +41,12 @@
     "OP": 79
   }
 
+  # Operator symbols
+  OPS = {
+    "ADD": "+", "SUB": "-",
+    "LESS": "<", "EQUAL": "=", "GREATER": ">",
+  }
+
   ## __getattr__ {{{
   # Get attribute
   # @param[in]  key  Name of the key
@@ -157,7 +163,7 @@
   def __init__(self, string, tag, indent = 0):
     Token.__init__(self, tag, indent)
 
-    self.lexeme = string
+    self.value = string
   # }}}
 
   ## __str__ {{{
@@ -166,7 +172,7 @@
   ##
 
   def __str__(self):
-    return self.lexeme
+    return self.value
   # }}}
 # }}}
 
@@ -278,7 +284,7 @@
   ##
 
   def __reserve(self, word):
-    self.words[word.lexeme] = word
+    self.words[word.value] = word
   # }}}
 
   # Public
@@ -462,9 +468,11 @@
     self.indent     = 0
     self.procedures = {}
     self.proc       = None
+    self.main       = None
     self.labels     = 0
     self.taddr      = []
     self.jumps      = {}
+    self.retstack   = []
   # }}} 
 
   ## __match {{{
@@ -578,7 +586,23 @@
       value = self.__get_id()
 
     else:
-      self.__error("Expcted TYPE or ID, but got " + Tag[self.look.tag])
+      self.__unexpected()
+
+    return value
+  # }}}
+
+  ## __get_type_value_or_id {{{
+  # Get value of type or id
+  # @return Found value
+  ##
+
+  def __get_type_value_or_id(self, var):
+    value = None
+
+    if isinstance(var, Variable):
+      value = var.name
+    else:
+      value = str(var.value)
 
     return value
   # }}}
@@ -618,7 +642,7 @@
         self.__print(str(identifier) + " " + Tag[vartype] + " " +
           ("" if None == paramtype else Tag[paramtype]))
       else:
-        self.__error("Expected variable and got " + Tag[self.look.tag])
+        self.__unexpected()
 
     return v
   # }}}
@@ -739,17 +763,17 @@
     self.__match(Tag.NL)
 
     # Create new procedure entry
-    name                  = str(identifier)
-    label                 = self.__gen_label()
-    self.proc             = Procedure(name)
-    self.procedures[name] = self.proc
-    self.jumps[name]      = len(self.taddr) #< Use label address
+    label                      = self.__gen_label()
+    self.main                  = str(identifier)
+    self.proc                  = Procedure(self.main)
+    self.procedures[self.main] = self.proc
+    self.jumps[self.main]      = len(self.taddr) #< Use label address
 
     # Output
-    self.__print("PROCEDURE " + name)
+    self.__print("PROCEDURE %s" % self.main)
 
     self.__emit_label(label)
-    self.__emit_comment("Begin proc %s" % name)
+    self.__emit_comment("Begin proc %s" % self.main)
     self.__emit_taddr(Tag.BEGIN)
 
     self.indent += 1 #< Adjust indentation level
@@ -838,10 +862,9 @@
 
   ## __block {{{
   # Parse blocks
-  # @param[in]  ret_label  Label to return to after block
   ##
 
-  def __block(self, ret_label = None):
+  def __block(self):
     indent = self.indent
 
     # Parse all supported statements
@@ -899,23 +922,17 @@
 
         identifier = self.__get_id()
         value      = self.__get_type_or_id()
+        value      = self.__get_type_value_or_id(value)
 
         self.__match(Tag.NL)
 
-        if Tag.ADD == op.tag:
-          opname = "ADD"
-          opsym  = "+"
-        else:
-          opname = "SUB"
-          opsym  = "-"
-
         # Output
         self.__print("%s %s %s" % (
-          opname, str(identifier), Tag[value.tag]
+          Tag[op.tag], str(identifier), value
         ))
 
         self.__emit_taddr(Tag.OP, "%s = %s %s %s" % (
-          str(identifier), str(identifier), opsym, str(value.value)
+          str(identifier), str(identifier), Tag.OPS[Tag[op.tag]], value
         ))
       # }}}
 
@@ -967,9 +984,12 @@
         start_label = self.__gen_label()
         end_label   = self.__gen_label()
 
+        # Push end label to retstack
+        self.retstack.append(end_label)
+
         self.__emit_comment("Start loop")
         self.__emit_label(start_label)
-        self.__block(end_label)
+        self.__block()
         self.__emit_goto(start_label)
         self.__emit_label(end_label)
         self.__emit_comment("End loop")
@@ -986,7 +1006,9 @@
         self.__print("EXITLOOP")
 
         # Check if there is a label to return to
-        if None != ret_label:
+        if len(self.retstack):
+          ret_label = self.retstack.pop()
+
           self.__emit_comment("Exitloop")
           self.__emit_goto(ret_label)
           break #< Just exit loop
@@ -997,8 +1019,11 @@
         # Case label
         end_label = self.__gen_label()
 
+        # Push end label to retstack
+        self.retstack.append(end_label)
+
         self.__emit_comment("Start case")
-        self.__case(end_label)
+        self.__case()
         self.__emit_label(end_label)
         self.__emit_comment("End case")
 
@@ -1039,20 +1064,19 @@
 
   ## __case {{{
   # Parse case
-  # @param[in]  ret_label  Label to return to after block
   ##
 
-  def __case(self, ret_label = None):
+  def __case(self):
     indent = self.indent
 
     self.__match(Tag.CASE, self.indent)
-
-    value = self.__get_type_or_id()
-
     self.__match(Tag.NL)
 
     # Output
-    self.__print("CASE " + Tag[value.tag])
+    self.__print("CASE")
+
+    # Get ret label
+    ret_label = self.retstack.pop()
 
     self.indent += 1 #< Adjust indentation level
 
@@ -1076,25 +1100,29 @@
           operand1 = self.__get_type_or_id()
           operand2 = self.__get_type_or_id()
 
+          operand1 = self.__get_type_value_or_id(operand1)
+          operand2 = self.__get_type_value_or_id(operand2)
+
           self.__match(Tag.NL)
 
           # Create end label after block
           end_label = self.__gen_label()
 
           # Output
-          self.__print("WHEN " + Tag[operator.tag] + " " +
-            Tag[operand1.tag] + " " + Tag[operand2.tag])
+          self.__print("WHEN %s %s %s" % (
+            Tag[operator.tag], operand1, operand2
+          ))
 
           self.__emit_comment("When")
           self.__emit_taddr(Tag.IFZ, "%s %s %s GOTO L%.3d" % (
-            str(operand1), str(operator), str(operand2), end_label
+            operand1, Tag.OPS[Tag[operator.tag]], operand2, end_label
           ))
 
           self.indent += 1 #< Adjust indentation level
 
           self.__block()
 
-          # Goto to ret ├Âlabel and emit end labe for next when 
+          # Goto to ret label and emit end label for next when
           self.__emit_goto(ret_label)
           self.__emit_label(end_label)
 
@@ -1111,7 +1139,7 @@
         # Output
         self.__print("OTHERWISE")
 
-        self.__emit_comment("When")
+        self.__emit_comment("Otherwise")
 
         self.indent += 1 #< Adjust indentation level
 
@@ -1232,27 +1260,28 @@
 
   ## run {{{
   # Run virtual machine
+  # @param[in]  step  Print every step
   ##
 
-  def run(self):
+  def run(self, step = False):
     # Find main label aka last defined proc
-    scopename = self.parser.procedures.keys()[-1]
-    scope     = self.parser.procedures[scopename]
-    pointer   = self.parser.jumps[scopename]
+    scope     = self.parser.procedures[self.parser.main]
+    pointer   = self.parser.jumps[self.parser.main]
 
     # Execute proc
     while pointer < len(self.parser.taddr):
       # Handle types
       cur = self.parser.taddr[pointer] #< Convenience
 
-      if Tag.SET == cur["tag"]:
+      if Tag.SET == cur["tag"]: # {{{
         varname, eq, value = cur["value"].split(" ")
 
         # Update variable
         self.__check_var(scope, varname)
         scope.vtable[varname].value = value
+      # }}}
 
-      elif Tag.OP == cur["tag"]:
+      elif Tag.OP == cur["tag"]: # {{{
         varname, eq, lvalue, op, rvalue = cur["value"].split(" ")
 
         # Update variable
@@ -1268,42 +1297,65 @@
 
         # Eval..
         scope.vtable[varname].value = eval("%s %s %s" % ( lvalue, op, rvalue ))
+      # }}}
 
-      elif Tag.PARAM == cur["tag"]:
+      elif Tag.PARAM == cur["tag"]: # {{{
         varname = cur["value"]
 
         # Push parameter onto stack
         self.__check_var(scope, varname)
         self.stack.append(scope.vtable[varname].value)
+      # }}}
 
-      elif Tag.GOTO == cur["tag"]:
+      elif Tag.GOTO == cur["tag"]: # {{{
         # Move pointer
         if self.parser.jumps.has_key(cur["value"]):
           pointer = self.parser.jumps[cur["value"]]
         else:
           self.__error("Cannot find jump label `" + cur["value"] + "`")
+      # }}}
 
-      elif Tag.CALL == cur["tag"]:
+      elif Tag.CALL == cur["tag"]: # {{{
         callname = cur["value"]
 
-        # Store return address
-        self.callstack.append(pointer + 1)
-
         # Check defined and builtin procs
         if self.parser.procedures.has_key(callname):
+          # Store return address
+          self.callstack.append(pointer + 1)
           pass
+
         elif "print" == callname:
           value = self.stack.pop()
 
           print(value)
+      # }}}
 
-      elif Tag.BEGIN == cur["tag"]:
+      elif Tag.IFZ == cur["tag"]: # {{{
+        lvalue, op, rvalue, goto, label = cur["value"].split(" ") 
+
+        # Check whether lvalue is in scope or literal
+        if scope.vtable.has_key(lvalue):
+          lvalue = scope.vtable[lvalue].value
+
+        # Check whether rvalue is in scope or literal
+        if scope.vtable.has_key(rvalue):
+          rvalue = scope.vtable[rvalue].value
+
+        # Eval..
+        ret = eval("%s %s %s" % ( lvalue, op, rvalue ))
+
+        if not ret:
+          pointer = self.parser.jumps[label]
+      # }}}
+
+      elif Tag.BEGIN == cur["tag"]: # {{{
         # Pop values from stack
         for varname, var in scope.vtable.items():
           if Tag.IN == var.paramtype or Tag.INOUT == var.paramtype:
             var.value = self.stack.pop()
+      # }}}
 
-      elif Tag.END == cur["tag"]:
+      elif Tag.END == cur["tag"]: # {{{
         # Push values to stack
         for varname, var in scope.vtable.items():
           if Tag.OUT == var.paramtype or Tag.INOUT == var.paramtype:
@@ -1312,6 +1364,11 @@
         # Check callstack and adjust pointer
         if len(self.callstack):
           pointer = self.callstack.pop()
+      # }}}
+
+      # Print step
+      if step:
+        print("%s %s" % ( Tag[cur["tag"]], cur["value"] ))
 
       pointer += 1
   # }}}
@@ -1334,6 +1391,8 @@
     help="Show label and jump table")
   ap.add_argument("-r", "--run", dest="run", action="store_true",
     help="Run program")
+  ap.add_argument("-s", "--step", dest="step", action="store_true",
+    help="Step through program")
 
   args = ap.parse_args()
 
@@ -1359,5 +1418,5 @@
   vm = VMachine(p, args.debug)
 
   # Finally run
-  if args.run:
-    vm.run()
+  if args.run or args.step:
+    vm.run(args.step)
--- a/studies/cmp/run.sh	Fri Jan 20 18:21:07 2012 +0100
+++ b/studies/cmp/run.sh	Fri Jan 20 18:21:15 2012 +0100
@@ -1,3 +1,3 @@
 #!/bin/bash
 
-python2.7 ./k2.py ./test.txt
+python2.7 ./k2.py ./test.txt $*
--- a/studies/cmp/test.txt	Fri Jan 20 18:21:07 2012 +0100
+++ b/studies/cmp/test.txt	Fri Jan 20 18:21:15 2012 +0100
@@ -1,15 +1,28 @@
 program
+  procedure P1
+    parameter
+    declaration
+      hw string
+
+    set hw "HELLO WORLD"
+
+    print hw
+
   procedure P2
     parameter
     declaration
       i integer
 
-    set i 5
+    set i 0
 
     # Dummy loop
     loop
-      add i 4
+      add i 1
+
+      print i
 
-      exitloop
+      case
+        when greater i 10
+          exitloop
 
     print i