Index: client/Client/Client.vcxproj
===================================================================
--- client/Client/Client.vcxproj	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ client/Client/Client.vcxproj	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -47,5 +47,5 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>c:\allegro\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>allegro-5.0.7-monolith-md-debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>allegro-5.0.8-monolith-md-debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
@@ -65,4 +65,5 @@
   <ItemGroup>
     <ClCompile Include="..\..\common\Common.cpp" />
+    <ClCompile Include="..\..\common\WorldMap.cpp" />
     <ClCompile Include="..\..\common\Message.cpp" />
     <ClCompile Include="..\..\common\Player.cpp" />
@@ -77,4 +78,5 @@
     <ClInclude Include="..\..\common\Common.h" />
     <ClInclude Include="..\..\common\Compiler.h" />
+    <ClInclude Include="..\..\common\WorldMap.h" />
     <ClInclude Include="..\..\common\Message.h" />
     <ClInclude Include="..\..\common\Player.h" />
Index: client/Client/Client.vcxproj.filters
===================================================================
--- client/Client/Client.vcxproj.filters	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ client/Client/Client.vcxproj.filters	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -55,4 +55,7 @@
       <Filter>Source Files\common</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\common\WorldMap.cpp">
+      <Filter>Source Files\common</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
@@ -84,4 +87,7 @@
       <Filter>Header Files\common</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\common\WorldMap.h">
+      <Filter>Header Files\common</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
Index: client/Client/main.cpp
===================================================================
--- client/Client/main.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ client/Client/main.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -14,8 +14,11 @@
 
 #include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
 #include <string>
 #include <iostream>
+#include <sstream>
+
+#include <map>
 
 #include <map>
@@ -24,7 +27,9 @@
 #include <allegro5/allegro_font.h>
 #include <allegro5/allegro_ttf.h>
+#include <allegro5/allegro_primitives.h>
 
 #include "../../common/Message.h"
 #include "../../common/Common.h"
+#include "../../common/WorldMap.h"
 #include "../../common/Player.h"
 
@@ -42,5 +47,9 @@
 void initWinSock();
 void shutdownWinSock();
-void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole);
+void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player>& mapPlayers, unsigned int& curPlayerId);
+void drawMap(WorldMap* gameMap);
+void drawPlayers(map<unsigned int, Player>& mapPlayers, unsigned int curPlayerId);
+POSITION screenToMap(POSITION pos);
+POSITION mapToScreen(POSITION pos);
 
 // callbacks
@@ -99,4 +108,6 @@
    bool redraw = true;
    doexit = false;
+   map<unsigned int, Player> mapPlayers;
+   unsigned int curPlayerId = -1;
 
    float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
@@ -110,10 +121,18 @@
    }
 
-   al_init_primitives_addon();
+   if (al_init_primitives_addon())
+      cout << "Primitives initialized" << endl;
+   else
+      cout << "Primitives not initialized" << endl;
+
    al_init_font_addon();
    al_init_ttf_addon();
 
-   ALLEGRO_FONT *font = al_load_ttf_font("../pirulen.ttf", 12, 0);
- 
+   #if defined WINDOWS
+      ALLEGRO_FONT *font = al_load_ttf_font("../pirulen.ttf", 12, 0);
+   #elif defined LINUX
+      ALLEGRO_FONT *font = al_load_ttf_font("pirulen.ttf", 12, 0);
+   #endif
+
    if (!font) {
       fprintf(stderr, "Could not load 'pirulen.ttf'.\n");
@@ -144,4 +163,8 @@
       return -1;
    }
+
+   WorldMap* gameMap = WorldMap::loadMapFromFile("../../data/map.txt");
+   //delete gameMap;
+   //gameMap = WorldMap::createDefaultMap();
 
    wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
@@ -291,8 +314,29 @@
          }
       }
+      else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
+         if(wndCurrent == wndMain) {
+            msgTo.type = MSG_TYPE_PLAYER_MOVE;
+
+            POSITION pos;
+            pos.x = ev.mouse.x;
+            pos.y = ev.mouse.y;
+            pos = screenToMap(pos);
+
+            if (pos.x != -1)
+            {
+               memcpy(msgTo.buffer, &curPlayerId, 4);
+               memcpy(msgTo.buffer+4, &pos.x, 4);
+               memcpy(msgTo.buffer+8, &pos.y, 4);
+
+               sendMessage(&msgTo, sock, &server);
+            }
+            else
+               cout << "Invalid point: User did not click on the map" << endl;
+         }
+      }
 
       if (receiveMessage(&msgFrom, sock, &from) >= 0)
       {
-         processMessage(msgFrom, state, chatConsole);
+         processMessage(msgFrom, state, chatConsole, mapPlayers, curPlayerId);
          cout << "state: " << state << endl;
       }
@@ -301,8 +345,6 @@
       {
          redraw = false;
- 
+
          wndCurrent->draw(display);
- 
-         al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
 
          chatConsole.draw(font, al_map_rgb(255,255,255));
@@ -314,4 +356,7 @@
          else if(wndCurrent == wndMain) {
             al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Message:");
+
+            drawMap(gameMap);
+            drawPlayers(mapPlayers, curPlayerId);
          }
 
@@ -330,4 +375,6 @@
    delete wndLogin;
    delete wndMain;
+
+   delete gameMap;
 
    al_destroy_event_queue(event_queue);
@@ -372,5 +419,36 @@
 }
 
-void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole)
+POSITION screenToMap(POSITION pos)
+{
+   pos.x = pos.x-300;
+   pos.y = pos.y-100;
+
+   if (pos.x < 0 || pos.y < 0)
+   {
+      pos.x = -1;
+      pos.y = -1;
+   }
+
+   return pos;
+}
+
+POSITION mapToScreen(POSITION pos)
+{
+   pos.x = pos.x+300;
+   pos.y = pos.y+100;
+
+   return pos;
+}
+
+POSITION mapToScreen(FLOAT_POSITION pos)
+{
+   POSITION p;
+   p.x = pos.x+300;
+   p.y = pos.y+100;
+
+   return p;
+}
+
+void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player>& mapPlayers, unsigned int& curPlayerId)
 {
    string response = string(msg.buffer);
@@ -383,6 +461,4 @@
       {
          cout << "In STATE_START" << endl;
-
-         chatConsole.addLine(response);
 
          switch(msg.type)
@@ -408,6 +484,14 @@
                   state = STATE_LOGIN;
                   wndCurrent = wndMain;
-                  cout << "User login successful" << endl;
+                  
+                  Player p("", "");
+                  p.deserialize(msg.buffer);
+                  mapPlayers[p.id] = p;
+                  curPlayerId = p.id;
+
+                  cout << "Got a valid login response with the player" << endl;
+                  cout << "Player id: " << curPlayerId << endl; 
                }
+
                break;
             }
@@ -418,7 +502,5 @@
       case STATE_LOGIN:
       {
-         chatConsole.addLine(response);
-
-          switch(msg.type)
+         switch(msg.type)
          {
             case MSG_TYPE_REGISTER:
@@ -428,4 +510,6 @@
             case MSG_TYPE_LOGIN:
             {
+               chatConsole.addLine(response);
+
                if (response.compare("You have successfully logged out.") == 0)
                {
@@ -448,12 +532,15 @@
 
                cout << "p.id: " << p.id << endl;
-               cout << "p.name: " << p.name << endl;
-               cout << "p.pos.x: " << p.pos.x << endl;
-               cout << "p.pos.y: " << p.pos.y << endl;
 
                break;
             }
-         }
-                     
+            case MSG_TYPE_CHAT:
+            {
+               chatConsole.addLine(response);
+
+               break;
+            }
+         }
+
          break;
       }
@@ -467,4 +554,45 @@
 }
 
+void drawMap(WorldMap* gameMap)
+{
+   POSITION mapPos;
+   mapPos.x = 0;
+   mapPos.y = 0;
+   mapPos = mapToScreen(mapPos);
+   for (int x=0; x<12; x++)
+   {
+      for (int y=0; y<12; y++)
+      {
+         WorldMap::TerrainType el = gameMap->getElement(x, y);
+
+         if (el == WorldMap::TERRAIN_GRASS)
+            al_draw_filled_rectangle(x*25+mapPos.x, y*25+mapPos.y, x*25+25+mapPos.x, y*25+25+mapPos.y, al_map_rgb(0, 255, 0));
+         else if (el == WorldMap::TERRAIN_OCEAN)
+            al_draw_filled_rectangle(x*25+mapPos.x, y*25+mapPos.y, x*25+25+mapPos.x, y*25+25+mapPos.y, al_map_rgb(0, 0, 255));
+         else if (el == WorldMap::TERRAIN_ROCK)
+            al_draw_filled_rectangle(x*25+mapPos.x, y*25+mapPos.y, x*25+25+mapPos.x, y*25+25+mapPos.y, al_map_rgb(100, 100, 0));
+      }
+   }
+}
+
+void drawPlayers(map<unsigned int, Player>& mapPlayers, unsigned int curPlayerId)
+{
+   map<unsigned int, Player>::iterator it;
+
+   Player* p;
+   POSITION pos;
+
+   for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
+   {
+      p = &it->second;
+      pos = mapToScreen(p->pos);
+
+      if (p->id == curPlayerId)
+         al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(255, 0, 0));
+      else
+         al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(191, 0, 0));
+   }
+}
+
 void registerAccount()
 {
Index: client/makefile
===================================================================
--- client/makefile	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ client/makefile	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -3,8 +3,11 @@
 FLAGS = $(LIB_FLAGS)
 COMMON_PATH = ../common
-DEPENDENCIES = Message.o Player.o chat.o GuiComponent.o Window.o Textbox.o Button.o
+DEPENDENCIES = Common.o Message.o Player.o chat.o GuiComponent.o Window.o Textbox.o Button.o
 
 gameClient : Client/main.cpp $(DEPENDENCIES)
 	$(CC) -o $@ $+ $(FLAGS)
+
+Common.o : $(COMMON_PATH)/Common.cpp
+	$(CC) -c -o $@ $? $(FLAGS)
 
 Message.o : $(COMMON_PATH)/Message.cpp
Index: common/Common.cpp
===================================================================
--- common/Common.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ common/Common.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -1,3 +1,12 @@
 #include "Common.h"
+
+#include <iostream>
+using namespace std;
+
+#if defined WINDOWS
+   #include <Windows.h>
+#elif defined LINUX
+   #include <time.h>
+#endif
 
 void set_nonblock(int sock)
@@ -13,2 +22,18 @@
    #endif
 }
+
+unsigned long long getCurrentMillis()
+{
+   unsigned long long numMilliseconds;
+
+   #if defined WINDOWS
+      numMilliseconds = GetTickCount();
+   #elif defined LINUX
+      timespec curTime;
+      clock_gettime(CLOCK_REALTIME, &curTime);
+
+      numMilliseconds = curTime.tv_sec*(unsigned long long)1000+curTime.tv_nsec/(unsigned long long)1000000;
+   #endif
+
+   return numMilliseconds;
+}
Index: common/Common.h
===================================================================
--- common/Common.h	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ common/Common.h	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -13,4 +13,5 @@
 
 void set_nonblock(int sock);
+unsigned long long getCurrentMillis();
 
 typedef struct
@@ -18,5 +19,11 @@
    int x;
    int y;
-} PLAYER_POS;
+} POSITION;
+
+typedef struct
+{
+   float x;
+   float y;
+} FLOAT_POSITION;
 
 #endif
Index: common/Message.cpp
===================================================================
--- common/Message.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ common/Message.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -11,7 +11,15 @@
 #endif
 
+#include <iostream>
+
+using namespace std;
+
 int sendMessage(NETWORK_MSG *msg, int sock, struct sockaddr_in *dest)
 {
-   return sendto(sock, (char*)msg, sizeof(NETWORK_MSG), 0, (struct sockaddr *)dest, sizeof(struct sockaddr_in));
+   int ret =  sendto(sock, (char*)msg, sizeof(NETWORK_MSG), 0, (struct sockaddr *)dest, sizeof(struct sockaddr_in));
+
+   cout << "Sent message of type " << msg->type << endl;
+
+   return ret;
 }
 
@@ -21,4 +29,9 @@
 
    // assume we don't care about the value of socklen
-   return recvfrom(sock, (char*)msg, sizeof(NETWORK_MSG), 0, (struct sockaddr *)dest, &socklen);
+   int ret =  recvfrom(sock, (char*)msg, sizeof(NETWORK_MSG), 0, (struct sockaddr *)dest, &socklen);
+
+   if (ret > -1)
+      cout << "Received message of type " << msg->type << endl;
+
+   return ret;
 }
Index: common/Message.h
===================================================================
--- common/Message.h	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ common/Message.h	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -6,5 +6,6 @@
 #define MSG_TYPE_LOGOUT       3
 #define MSG_TYPE_CHAT         4
-#define MSG_TYPE_PLAYER       5
+#define MSG_TYPE_PLAYER       5  // server sends this to update player positions
+#define MSG_TYPE_PLAYER_MOVE  6  // client sends this when a player wants to move
 
 typedef struct
Index: common/Player.cpp
===================================================================
--- common/Player.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ common/Player.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -4,4 +4,5 @@
 #include <sstream>
 #include <cstring>
+#include <cmath>
 
 using namespace std;
@@ -12,6 +13,7 @@
    this->name = "";
    this->password = "";
-   this->pos.x = 0;
-   this->pos.y = 0;
+   this->pos.x = this->target.x = 0;
+   this->pos.y = this->target.y = 0;
+   this->timeLastUpdated = 0;
 }
 
@@ -23,4 +25,6 @@
    this->pos.x = p.pos.x;
    this->pos.y = p.pos.y;
+   this->target.x = p.target.x;
+   this->target.y = p.target.y;
    this->addr = p.addr;
 }
@@ -31,6 +35,6 @@
    this->name = name;
    this->password = password;
-   this->pos.x = 200;
-   this->pos.y = 200;
+   this->pos.x = this->target.x = 200;
+   this->pos.y = this->target.y = 200;
 }
 
@@ -40,6 +44,6 @@
    this->name = name;
    this->password = "";
-   this->pos.x = 200;
-   this->pos.y = 200;
+   this->pos.x = this->target.x = 200;
+   this->pos.y = this->target.y = 200;
    this->addr = addr;
 }
@@ -51,24 +55,27 @@
 void Player::serialize(char* buffer)
 {
-   ostringstream oss;
-
-   oss.write((char*)&(this->id), sizeof(int));
-   oss << this->name;
-   oss.write("\0", 1);
-   oss.write((char*)&(this->pos.x), sizeof(int));
-   oss.write((char*)&(this->pos.y), sizeof(int));
-
-   memcpy(buffer, oss.str().c_str(), this->name.length()+1+2*sizeof(int));
+   memcpy(buffer, &this->id, 4);
+   memcpy(buffer+4, &this->pos.x, 4);
+   memcpy(buffer+8, &this->pos.y, 4);
+   memcpy(buffer+12, &this->target.x, 4);
+   memcpy(buffer+16, &this->target.y, 4);
+   strcpy(buffer+20, this->name.c_str());
 }
 
 void Player::deserialize(char* buffer)
 {
-   istringstream iss;
-   iss.str(buffer);
+   memcpy(&this->id, buffer, 4);
+   memcpy(&this->pos.x, buffer+4, 4);
+   memcpy(&this->pos.y, buffer+8, 4);
+   memcpy(&this->target.x, buffer+12, 4);
+   memcpy(&this->target.y, buffer+16, 4);
+   this->name.assign(buffer+20);
 
-   iss.read((char*)&(this->id), sizeof(int));
-   iss >> this->name;
-   iss.read((char*)&(this->pos.x), sizeof(int));
-   iss.read((char*)&(this->pos.y), sizeof(int));
+   cout << "id: " << this->id << endl;
+   cout << "pos x: " << this->pos.x << endl;
+   cout << "pos y: " << this->pos.y << endl;
+   cout << "target x: " << this->target.x << endl;
+   cout << "target y: " << this->target.y << endl;
+   cout << "name: " << this->name << endl;
 }
 
@@ -82,2 +89,28 @@
    this->addr = addr;
 }
+
+void Player::move(void) {
+   int speed = 100; // pixels per second
+   unsigned long long curTime = getCurrentMillis();
+
+   // if we're at our target, don't move
+   if (pos.x == target.x && pos.y == target.y)
+      cout << "We're already at our target" << endl;
+   else {
+      float pixels = speed * (curTime-timeLastUpdated) / 1000.0;
+      cout << "We need to move " << pixels << " pixels" << endl;
+
+      double angle = atan2(target.y-pos.y, target.x-pos.x);
+
+      float dist = sqrt(pow(target.x-pos.x, 2) + pow(target.y-pos.y, 2));
+      if (dist <= pixels) {
+         pos.x = target.x;
+         pos.y = target.y;
+      }else {
+         pos.x += cos(angle)*pixels;
+         pos.y += sin(angle)*pixels;
+      }
+   }
+
+   timeLastUpdated = curTime;
+}
Index: common/Player.h
===================================================================
--- common/Player.h	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ common/Player.h	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -32,9 +32,13 @@
    void setAddr(sockaddr_in addr);
 
+   void move();
+
    int id;
    string name;
    string password;
    sockaddr_in addr;
-   PLAYER_POS pos;
+   FLOAT_POSITION pos;
+   POSITION target;
+   unsigned long long timeLastUpdated;
 };
 
Index: common/WorldMap.cpp
===================================================================
--- common/WorldMap.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
+++ common/WorldMap.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -0,0 +1,140 @@
+#include "WorldMap.h"
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <cstdlib>
+
+using namespace std;
+
+WorldMap::WorldMap(int width, int height)
+{
+   this->width = width;
+   this->height = height;
+
+   vctMap = new vector<vector<TerrainType>*>(width);
+
+   for (int x=0; x<width; x++) {
+      vector<TerrainType>* newVector = new vector<TerrainType>(height);
+
+      for (int y=0; y<height; y++)
+         (*newVector)[y] = TERRAIN_NONE;
+
+      (*vctMap)[x] = newVector;
+   }
+}
+
+WorldMap::~WorldMap()
+{
+   for (int x=0; x<width; x++)
+      delete (*vctMap)[x];
+
+   delete vctMap;
+}
+
+WorldMap::TerrainType WorldMap::getElement(int x, int y)
+{
+   return (*(*vctMap)[x])[y];
+}
+
+void WorldMap::setElement(int x, int y, TerrainType t)
+{
+   (*(*vctMap)[x])[y] = t;
+}
+
+WorldMap* WorldMap::createDefaultMap()
+{
+   WorldMap* m = new WorldMap(12l, 12);
+
+   for(int x=0; x<12; x++)
+   {   
+      for(int y=0; y<12; y++)
+      {
+         if (x ==0 || y == 0 || x == 11 || y == 11)
+            m->setElement(x, y, TERRAIN_OCEAN);
+         else
+            m->setElement(x, y, TERRAIN_GRASS);
+      }
+   }
+
+   m->setElement(5, 5, TERRAIN_ROCK);
+
+   return m;
+}
+
+WorldMap* WorldMap::loadMapFromFile(string filename)
+{
+   WorldMap* m = new WorldMap(12l, 12);
+
+   ifstream file(filename.c_str());
+
+   if (file.is_open())
+   {
+      string line;
+      int width, height;
+
+      // read the map dimensions
+      getline(file, line);
+      if (line.size() > 0)
+      {
+         istringstream iss(line);
+         string token;
+         getline(iss, token, 'x');
+         width = atoi(token.c_str());
+         getline(iss, token, 'x');
+         height = atoi(token.c_str());
+      }
+
+      cout << "width: " << width << endl;
+      cout << "height: " << height << endl;
+
+      // read the map contents
+      int row = 0;
+      while ( file.good() )
+      {
+         getline(file, line);
+         if (line.size() > 0)
+         {
+            cout << "line: " << line << endl;
+
+            istringstream iss(line);
+            string token;
+            int type;
+            TerrainType terrain;
+
+            for(int x=0; x<width; x++)
+            {
+               getline(iss, token, ',');
+               cout << "token: " << token << endl;
+               type = atoi(token.c_str());
+               cout << "type: " << type << endl;
+
+               switch(type) {
+               case 1:
+                  terrain = TERRAIN_GRASS;
+                  break;
+               case 2:
+                  terrain = TERRAIN_OCEAN;
+                  break;
+               case 3:
+                  terrain = TERRAIN_ROCK;
+                  break;
+               }
+
+               cout << "About to set element" << endl;
+               cout << "x: " << x << endl;
+               cout << "row: " << row << endl;
+               m->setElement(x, row, terrain);
+            }
+         }
+
+         row++;
+      }
+      file.close();
+   }
+   else
+      cout << "Could not open the file" << endl;
+
+   return m;
+}
Index: common/WorldMap.h
===================================================================
--- common/WorldMap.h	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
+++ common/WorldMap.h	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -0,0 +1,33 @@
+#ifndef _WORLDMAP_H
+#define _WORLDMAP_H
+
+#include <string>
+
+#include <vector>
+
+using namespace std;
+
+class WorldMap {
+public:
+   enum TerrainType {
+      TERRAIN_NONE,
+      TERRAIN_GRASS,
+      TERRAIN_OCEAN,
+      TERRAIN_ROCK
+   };
+
+   int width, height;
+   vector<vector<TerrainType>*>* vctMap;
+
+   WorldMap(int width, int height);
+
+   ~WorldMap();
+
+   TerrainType getElement(int x, int y);
+   void setElement(int x, int y, TerrainType type);
+
+   static WorldMap* createDefaultMap();
+   static WorldMap* loadMapFromFile(string filename);
+};
+
+#endif
Index: data/map.txt
===================================================================
--- data/map.txt	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
+++ data/map.txt	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -0,0 +1,13 @@
+12x12
+2,2,2,2,2,2,2,2,2,2,2,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,2,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,1,1,1,1,1,1,1,1,1,1,2
+2,2,2,2,2,2,2,2,2,2,2,2
Index: readme.txt
===================================================================
--- readme.txt	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ readme.txt	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -1,2 +1,4 @@
+This info is outdated. The latest info is on the github wiki.
+
 BoostPro Installer options
 
Index: server/DataAccess.cpp
===================================================================
--- server/DataAccess.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ server/DataAccess.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -3,4 +3,5 @@
 #include <iostream>
 #include <sstream>
+#include <cstdlib>
 
 using namespace std;
@@ -27,7 +28,36 @@
    ostringstream oss;
 
-   oss << "'" << username << "', '" << password << "'";
+   string salt = "$1$";
+   int random;
+   char chr;
+   for(int i=0; i<8; i++)
+   {
+      random = rand() % 62;
+      if (random < 26)
+         chr = (char)('a'+random);
+      else if (random < 52)
+         chr = (char)('A'+random-26);
+      else
+         chr = (char)('0'+random-52);
+      salt += chr;
+   }
+   salt += '$';
+
+   string encrypted(crypt(password.c_str(), salt.c_str()));
+
+   oss << "'" << username << "', '" << encrypted << "'";
 
    return insert("users", "name, password", oss.str());
+}
+
+int DataAccess::updatePlayer(string username, string password)
+{
+   ostringstream values, where;
+
+   values << "password='" << password << "'";
+   
+   where << "name='" << username << "'";
+
+   return update("users", values.str(), where.str());
 }
 
@@ -51,7 +81,8 @@
    }
 
-   if ( ( row = mysql_fetch_row(result)) != NULL )
+   if ( ( row = mysql_fetch_row(result)) != NULL ) {
+      cout << "Creating a new player" << endl;
       p = new Player(string(row[1]), string(row[2]));
-   else {
+   }else {
       cout << "Returned no results for some reason" << endl;
       p = NULL;
@@ -63,5 +94,9 @@
 }
 
-int DataAccess::printPlayers()
+// need to make sure this list is freed
+// since we need to create a DataAccess class
+// when calling these functions,
+// we could free this list in the destructor
+list<Player*>* DataAccess::getPlayers()
 {
    MYSQL_RES *result;
@@ -73,22 +108,49 @@
    if (result == NULL) {
       cout << mysql_error(connection) << endl;
-      return 1;
+      return NULL;
    }
 
+   list<Player*>* lstPlayers = new list<Player*>();
    while ( ( row = mysql_fetch_row(result)) != NULL ) {
       cout << row[0] << ", " << row[1] << ", " << row[2] << endl;
+      lstPlayers->push_back(new Player(row[1], row[2]));
    }
 
    mysql_free_result(result);
 
-   return 0;
+   return lstPlayers;
 }
 
-int DataAccess::insert(string table, string rows, string values)
+bool DataAccess::verifyPassword(string password, string encrypted)
+{
+   string test(crypt(password.c_str(), encrypted.c_str()));
+
+   return encrypted.compare(test) == 0;
+}
+
+int DataAccess::insert(string table, string columns, string values)
 {
    int query_state;
    ostringstream oss;
 
-   oss << "INSERT into " << table << " (" << rows << ") VALUES (" << values << ")";
+   oss << "INSERT into " << table << " (" << columns << ") VALUES (" << values << ")";
+   cout << "query: " << oss.str() << endl;
+
+   query_state = mysql_query(connection, oss.str().c_str());
+
+   if (query_state != 0) {
+      cout << mysql_error(connection) << endl;
+      return 1;
+   }
+
+   return 0;
+}
+
+int DataAccess::update(string table, string values, string where)
+{
+   int query_state;
+   ostringstream oss;
+
+   oss << "UPDATE " << table << " SET " << values << " WHERE " << where;
    cout << "query: " << oss.str() << endl;
 
Index: server/DataAccess.h
===================================================================
--- server/DataAccess.h	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ server/DataAccess.h	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -3,4 +3,5 @@
 
 #include <string>
+#include <list>
 
 #include <mysql/mysql.h>
@@ -16,9 +17,12 @@
 
    int insertPlayer(string username, string password);
+   int updatePlayer(string username, string password);
 
-   Player *getPlayer(string username);
-   int printPlayers();
+   Player* getPlayer(string username);
+   list<Player*>* getPlayers();
+   bool verifyPassword(string encrypted, string password);
 
    int insert(string table, string rows, string values);
+   int update(string table, string values, string where);
    MYSQL_RES *select(string table, string filter);
 
Index: rver/crypt.cpp
===================================================================
--- server/crypt.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ 	(revision )
@@ -1,19 +1,0 @@
-#include "crypt.h"
-
-Crypt::Crypt()
-{
-}
-
-Crypt::~Crypt()
-{
-}
-
-string Crypt::encrypt(string s)
-{
-	return s + " encrypted";
-}
-
-string Crypt::decrypt(string s)
-{
-	return s.substr(0, s.length()-10);
-}
Index: rver/crypt.h
===================================================================
--- server/crypt.h	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ 	(revision )
@@ -1,13 +1,0 @@
-#include <string>
-
-using namespace std;
-
-class Crypt
-{
-public:
-	Crypt();
-	~Crypt();
-
-	string encrypt(string);
-	string decrypt(string);
-};
Index: rver/database.cpp
===================================================================
--- server/database.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ 	(revision )
@@ -1,44 +1,0 @@
-#include "database.h"
-
-#include <string>
-#include <mysql/mysql.h> 
-
-using namespace std;
-
-Database::Database(string host, string username, string password, string database)
-{
-	mysql_init(&(this->mysql));
-
-        this->conn = mysql_real_connect(&(this->mysql),
-		host.c_str(), username.c_str(), password.c_str(), database.c_str(),
-		0, 0, 0);
-
-        if (this->conn == NULL) {
-		// throw an error
-        }
-}
-
-Database::~Database()
-{
-        mysql_close(conn);
-}
-
-void Database::createUser(string username, string password)
-{
-        MYSQL_RES *result;
-        MYSQL_ROW row;
-        int query_state;
-
-        query_state = mysql_query(conn, (string()+"INSERT INTO users VALUES ("+username+","+password+")").c_str());
-
-        if (query_state !=0) {
-		// throw an error
-        }
-
-        mysql_free_result(result);
-}
-
-string Database::getPassword(string username)
-{
-	return "defaultPassword";
-}
Index: rver/database.h
===================================================================
--- server/database.h	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ 	(revision )
@@ -1,19 +1,0 @@
-#include <string>
-
-#include <mysql/mysql.h>
-
-using namespace std;
-
-class Database
-{
-private:
-	MYSQL mysql, *conn;
-
-public:
-        Database(string host, string username, string password, string database);
-        ~Database();
-
-        void createUser(string username, string password);
-
-        string getPassword(string username);
-};
Index: server/makefile
===================================================================
--- server/makefile	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ server/makefile	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -1,7 +1,7 @@
 CC = g++
-LIB_FLAGS = -lssl -lmysqlclient
+LIB_FLAGS = -lssl -lmysqlclient -lcrypt -lrt
 FLAGS = $(LIB_FLAGS)
 COMMON_PATH = ../common
-DEPENDENCIES = Common.o Message.o Player.o DataAccess.o
+DEPENDENCIES = Common.o Message.o Player.o WorldMap.o DataAccess.o
 
 server : server.cpp $(DEPENDENCIES)
@@ -17,4 +17,7 @@
 	$(CC) -c -o $@ $?
 
+WorldMap.o : $(COMMON_PATH)/WorldMap.cpp
+	$(CC) -c -o $@ $?
+
 %.o : %.cpp
 	$(CC) -c -o $@ $?
Index: server/server.cpp
===================================================================
--- server/server.cpp	(revision 3a79253784dcf52104a4d43b21218f28f83fc81a)
+++ server/server.cpp	(revision ca44f829f24c3cc1c8b68b7811a002879b661c5c)
@@ -6,4 +6,5 @@
 #include <sstream>
 #include <cstring>
+#include <cmath>
 
 #include <vector>
@@ -14,4 +15,6 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
+
+#include <crypt.h>
 
 /*
@@ -24,4 +27,5 @@
 #include "../common/Common.h"
 #include "../common/Message.h"
+#include "../common/WorldMap.h"
 #include "../common/Player.h"
 
@@ -30,7 +34,7 @@
 using namespace std;
 
-bool processMessage(const NETWORK_MSG &clientMsg, const struct sockaddr_in &from, map<unsigned int, Player>& mapPlayers, unsigned int& unusedId, NETWORK_MSG &serverMsg);
-
-void updateUnusedId(unsigned int& id);
+bool processMessage(const NETWORK_MSG &clientMsg, const struct sockaddr_in &from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedId, NETWORK_MSG &serverMsg);
+
+void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers);
 
 // this should probably go somewhere in the common folder
@@ -94,5 +98,5 @@
    NETWORK_MSG clientMsg, serverMsg;
    map<unsigned int, Player> mapPlayers;
-   unsigned int unusedId = 0;
+   unsigned int unusedId = 1;
 
    //SSL_load_error_strings();
@@ -104,4 +108,6 @@
       exit(1);
    }
+
+   WorldMap* gameMap = NULL; //WorldMap::createDefaultMap();
  
    sock = socket(AF_INET, SOCK_DGRAM, 0);
@@ -127,8 +133,10 @@
          cout << "Got a message" << endl;
 
-         broadcastResponse = processMessage(clientMsg, from, mapPlayers, unusedId, serverMsg);
-
+         broadcastResponse = processMessage(clientMsg, from, mapPlayers, gameMap, unusedId, serverMsg);
+
+         // probably replace this with a function that prints based on the
+         // message type
          cout << "msg: " << serverMsg.buffer << endl;
-
+         cout << "broadcastResponse: " << broadcastResponse << endl;
          if (broadcastResponse)
          {
@@ -136,5 +144,4 @@
 
             map<unsigned int, Player>::iterator it;
-
             for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
             {
@@ -151,4 +158,11 @@
          }
 
+         // update player positions
+         map<unsigned int, Player>::iterator it;
+         for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
+         {
+            it->second.move();
+         }
+
          broadcastPlayerPositions(mapPlayers, sock);
       }
@@ -158,5 +172,5 @@
 }
 
-bool processMessage(const NETWORK_MSG& clientMsg, const struct sockaddr_in& from, map<unsigned int, Player>& mapPlayers, unsigned int& unusedId, NETWORK_MSG& serverMsg)
+bool processMessage(const NETWORK_MSG& clientMsg, const struct sockaddr_in& from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedId, NETWORK_MSG& serverMsg)
 {
    DataAccess da;
@@ -195,11 +209,12 @@
       case MSG_TYPE_LOGIN:
       {
+         cout << "Got login message" << endl;
+
          string username(clientMsg.buffer);
          string password(strchr(clientMsg.buffer, '\0')+1);
-         cout << "Player logging in: " << username << endl;
 
          Player* p = da.getPlayer(username);
 
-         if (p == NULL || p->password != password)
+         if (p == NULL || !da.verifyPassword(password, p->password))
          {
             strcpy(serverMsg.buffer, "Incorrect username or password");
@@ -212,9 +227,10 @@
          {
             p->setAddr(from);
+            updateUnusedId(unusedId, mapPlayers);
             p->id = unusedId;
             mapPlayers[unusedId] = *p;
-            updateUnusedId(unusedId);
-
-            strcpy(serverMsg.buffer, "Login successful. Enjoy chatting with other players.");
+
+            // sendd back the new player info to the user
+            p->serialize(serverMsg.buffer);
          }
 
@@ -235,4 +251,5 @@
          {
             strcpy(serverMsg.buffer, "That player is not logged in. This is either a bug, or you're trying to hack the server.");
+            cout << "Player not logged in" << endl;
          }
          else if ( p->addr.sin_addr.s_addr != from.sin_addr.s_addr ||
@@ -240,4 +257,5 @@
          {
             strcpy(serverMsg.buffer, "That player is logged in using a differemt connection. This is either a bug, or you're trying to hack the server.");
+            cout << "Player logged in using a different connection" << endl;
          }
          else
@@ -247,5 +265,9 @@
             mapPlayers.erase(p->id);
             strcpy(serverMsg.buffer, "You have successfully logged out.");
-         }
+            cout << "Player logged out successfuly" << endl;
+         }
+
+         // should really be serverMsg.type = MSG_TYPE_LOGOUT;
+         serverMsg.type = MSG_TYPE_LOGIN;
 
          break;
@@ -265,8 +287,8 @@
             broadcastResponse = true;
 
-            stringstream ss;
-            ss << p->name << ": " << clientMsg.buffer;
-
-            strcpy(serverMsg.buffer, ss.str().c_str());
+            ostringstream oss;
+            oss << p->name << ": " << clientMsg.buffer;
+
+            strcpy(serverMsg.buffer, oss.str().c_str());
          }	
 
@@ -275,4 +297,67 @@
          break;
       }
+      case MSG_TYPE_PLAYER_MOVE:
+      {
+         cout << "Got a move message" << endl;
+
+         istringstream iss;
+         iss.str(clientMsg.buffer);
+
+         cout << "PLAYER_MOVE" << endl;
+
+         int id, x, y;
+
+         memcpy(&id, clientMsg.buffer, 4);
+         memcpy(&x, clientMsg.buffer+4, 4);
+         memcpy(&y, clientMsg.buffer+8, 4);
+         
+         cout << "x: " << x << endl;
+         cout << "y: " << y << endl;
+         cout << "id: " << id << endl;
+
+         if ( mapPlayers[id].addr.sin_addr.s_addr == from.sin_addr.s_addr &&
+              mapPlayers[id].addr.sin_port == from.sin_port )
+         {
+            // we need to make sure the player can move here
+            if (0 <= x && x < 300 && 0 <= y && y < 300 &&
+               gameMap->getElement(x/25, y/25) == WorldMap::TERRAIN_GRASS)
+            {
+               // first we get the correct vector 
+               mapPlayers[id].target.x = x;
+               mapPlayers[id].target.y = y;
+               int xDiff = mapPlayers[id].target.x - mapPlayers[id].pos.x;
+               int yDiff = mapPlayers[id].target.y - mapPlayers[id].pos.y;
+               cout << "xDiff: " << xDiff << endl;               
+               cout << "yDiff: " << yDiff << endl;               
+
+               // then we get the correct angle
+               double angle = atan2(yDiff, xDiff);
+               cout << "angle: " << angle << endl;               
+
+               // finally we use the angle to determine
+               // how much the player moves
+               // the player will move 50 pixels in the correct direction
+               mapPlayers[id].pos.x += cos(angle)*50;
+               mapPlayers[id].pos.y += sin(angle)*50;
+               cout << "new x: " << mapPlayers[id].pos.x << endl;               
+               cout << "new y: " << mapPlayers[id].pos.y << endl;               
+
+               serverMsg.type = MSG_TYPE_PLAYER_MOVE;
+               
+               memcpy(serverMsg.buffer, &id, 4);
+               memcpy(serverMsg.buffer+4, &mapPlayers[id].pos.x, 4);
+               memcpy(serverMsg.buffer+8, &mapPlayers[id].pos.y, 4);
+               //memcpy(serverMsg.buffer, clientMsg.buffer, 12);
+
+               broadcastResponse = true;
+            }
+            else
+               cout << "Bad terrain detected" << endl;
+         }
+         else  // nned to send back a message indicating failure
+            cout << "Player id (" << id << ") doesn't match sender" << endl;
+
+         break;
+      }
       default:
       {
@@ -285,9 +370,12 @@
    }
 
+   cout << "Got to the end of the switch" << endl;
+
    return broadcastResponse;
 }
 
-void updateUnusedId(unsigned int& id)
-{
-   id = 5;
-}
+void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers)
+{
+   while (mapPlayers.find(id) != mapPlayers.end())
+      id++;
+}
