   Help, open and closing a door, changing a tile on a map
  Hi, I was doing a tutorial on tile based ASCII character console games and I made a bunch of modifications for a simple beginning Rogue-like project.  All is working fine except changing the tile of the door from closed to open. using the arrow keys to move (set constants for those) and used char 'o' to open a door and 'c' to close a door. It will notify you when you press the o or c keys and ask for the direction to do the task. The problem is it looks like it may be just redrawing the original map after you do the function as the door never displays open or lets you pass (it wouldn't because the closed door is set to be impassable.)Can someone give me a hand figuring this out, I am stumped on this, and will need this to implement any other tile changes on the map. (there will be many)/*Simple Rogue Version 1.2@Date - 5-24-10**/#include "conio.h" // Console I/O - supplies the getch() function#include "ExtendedWin32Console.h" // Simple Win32 3rd party console display engine// Symbolic Constants //////////////////////////////////////////////////////////////////////Map Dimensions #define MAP_WIDTH   20 #define MAP_HEIGHT  15//Tile types - add new tiles here part1#define TILE_FLOOR 2#define TILE_WALL  1#define TILE_GRASS 0#define TILE_OPENDOOR 3#define TILE_TREE 4#define TILE_WATER 5#define TILE_CLOSEDDOOR 6//define arrow keys to char values compatible with the getch() functionconst char UP = 72;const char LT = 75;const char RT = 77;const char DN = 80;// Data Structures /////////////////////////////////////////////////////////////////////////version 1.2 difference - makes TILES into a Struct holds values for// character, color and passable booleanstruct TILE_TYPE{    char nCharacter; // ASCII character for this tile type    short nColorCode;   // Color code for this tile type    bool bPassable;  //set to true if you can walk on this tile};// Globals /////////////////////////////////////////////////////////////////////////////////level 1 static mapint nMapArray[MAP_HEIGHT][MAP_WIDTH] = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5 },{ 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 5, 5, 5 },{ 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 5, 5, 5 },{ 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 5, 5, 5 },{ 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 5, 0, 5 },{ 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 5, 0, 0 },{ 0, 0, 1, 1, 3, 1, 1, 0, 0, 0, 1, 1, 6, 1, 1, 0, 0, 5, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },{ 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0 },{ 0, 4 ,4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5 },{ 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5 }};//ver 1.2 - Global array used to define all tile types properties used in the game// add new tiles here part2TILE_TYPE sTileIndex[] = {    { '"', 2 , true},  // (0) TILE_GRASS    { '#', 8,  false},  // (1) TILE_WALL    { ' ', 3,  true },  // (2) TILE_ROCKFLOOR    { '/', 12, true}, // (3) TILE_OPENDOOR    { 't', 10, false}, // (4) TILE_TREE    { char(174), 11, false}, //(5) TILE_WATER    { '+', 12, false}, // (6) TILE_CLOSEDDOOR};//The players location on the current mapint nPlayerX;int nPlayerY;// Function Prototypes ///////////////////////////////////////////////////////////////////void DrawMap( void );bool IsPassable( int x, int y );void DrawTile( int x, int y );void CloseDoorCommand( void );void OpenDoorCommand( void );// DrawTile Function ///////////////////////////////////////////////////////////////////////VER 1.2 DrawTile Function// Draws a map tile for the map coordinates specifiedvoid DrawTile( int x, int y){    // Designate the position of the tile on screen    console.SetPosition( x, y);    // Record the tile type    int nType = nMapArray[y][x];    // Select the tile color    console.SetColor( sTileIndex[nType].nColorCode);    // Draw the tile to the screen    console << sTileIndex[nType].nCharacter;}// DrawMap Function //////////////////////////////////////////////////////////////////////void DrawMap(void){    for(int y= 0; y < MAP_HEIGHT; y++){   for(int x = 0; x < MAP_WIDTH; x++ ){  //draw the tiles  DrawTile(x, y);   }//end of for loop    }//end of for loop}// OpenDoorCommand Function //////////////////////////////////////////////////////////////////user command function which attempts to convert a closed door to an open one at a//tile specified by the user.//void OpenDoorCommand( void ){    //draw some notification to the user    console.SetPosition(2, 22);    console << "Which direction? (DN,LT,RT,UP)";    //let player decide where to look    char nKey = getch();    int nDeltaX = 0;int nDeltaY = 0;// Clear the screen to get rid of the notification textconsole.Clear();// Compute which tile the user specifiedswitch( nKey ){// SOUTHcase DN:nDeltaX = 0;nDeltaY = 1;break;// WESTcase LT:nDeltaX = -1;nDeltaY = 0;break;// EASTcase RT:nDeltaX = 1;nDeltaY = 0;break;// NORTHcase UP:nDeltaX = 0;nDeltaY = -1;break;// Not a valid directiondefault:// No direction specified, so abortconsole.Clear();return;}// Is there a closed door present in the direction specified?if( nMapArray[nPlayerY + nDeltaY][nPlayerX + nDeltaX] == TILE_CLOSEDDOOR ){// If there is a closed door, change it to an open onenMapArray[nPlayerY + nDeltaY][nPlayerX + nDeltaX] = TILE_OPENDOOR;}}// CloseDoorCommand Function /////////////////////////////////////////////////////////////////User command function which attempts to convert an open door to a closed one at a//tile specified by the user.//void CloseDoorCommand( void ){// Draw some notification to the userconsole.SetPosition( 2, 22 );console << "Which direction? (DN,LT,RT,UP)";// Let the user decide where to lookchar nKey = getch();int nDeltaX = 0;int nDeltaY = 0;// Clear the screen to get rid of the notification textconsole.Clear();// Compute which tile the user specifiedswitch( nKey ){// SOUTHcase DN:nDeltaX = 0;nDeltaY = 1;break;// WESTcase LT:nDeltaX = -1;nDeltaY = 0;break;// EASTcase RT:nDeltaX = 1;nDeltaY = 0;break;// NORTHcase UP:nDeltaX = 0;nDeltaY = -1;break;// Not a valid directiondefault:// No direction specified, so abortreturn;}// Is there a closed door present in the direction specified?if( nMapArray[nPlayerY + nDeltaY][nPlayerX + nDeltaX] == TILE_OPENDOOR ){// If there is a closed door, change it to an open onenMapArray[nPlayerY + nDeltaY][nPlayerX + nDeltaX] = TILE_CLOSEDDOOR;}}//IsPassable Function //////////////////////////////////////////////////////////////////// This function analyzes the coordinates of the map array specified and// returns true if the coord is passable (able for the player to occupy), false if not.bool IsPassable(int x, int y){    //before we do anything make damn sure the coords are valid    if(x <0 || x >= MAP_WIDTH ||y <0 || y>= MAP_HEIGHT)    return false;    //store the value of the tile specified    int nTileValue = nMapArray[y][x];    // Return true if it isn't passable    return sTileIndex[nTileValue].bPassable;}//player position function void playerPos(int nplayX, int nplayY){   //console.Clear();   console.SetPosition(nplayX, nplayY);   console << "@";  };//Main functionint main(void){    SetConsoleTitle(" Simple Rogue version 1.2 ");    //initialization phase//delcare the players positions   int nPlayerX=4;    int nPlayerY=4;    //Game Loop   //input phase goes herechar nKey = 0;while(true){   DrawMap();//draw the player to the screen//console.Clear();console.SetColor(14);console.SetPosition(nPlayerX, nPlayerY);console << "@";    //grab user input    nKey = getch();   //processing phase goes here   //variables for passable test   int nDeltaX =0;   int nDeltaY =0;   //swtich for keyboard input differential  switch( nKey ){// Move upcase UP:nDeltaX = 0;nDeltaY = -1;break;// Move leftcase LT:nDeltaX = -1;nDeltaY = 0;break;// Move rightcase RT:nDeltaX = 1;nDeltaY = 0;break;// Move downcase DN:nDeltaX = 0;nDeltaY = 1;break;    // Open Door    case 'o':   OpenDoorCommand();   break;    // Close Door    case 'c':   CloseDoorCommand();   break;// Escape keycase 27:// Quit the programreturn 0;}// check and see if we're allowed to move in the direction specifiedif(IsPassable(nPlayerX +nDeltaX, nPlayerY + nDeltaY) ){    //if allowed move in direction specified    nPlayerX += nDeltaX;    nPlayerY += nDeltaY;}}}Here is the header file I am using for console output (will do pdcurses later)I doubt this even matters for what the issue is as it's just a i/o function header, but figured i'd include it anyway.////////////////////////////////////////////////////////////////////////////////////////////////////////CExtendedWin32Console.h - Declaration for extended Win32-Console functionality.//////////////////////////////////////////////////////////////////////////////////////////////////////////////This header defines the data structures and functionality required to create a console I/O////library similar in feature to the ubiquitous cout and cin objects. It is by no means ////compatible with those objects however and serves only as fullfilling a requirement for////the tutorials.////////Coded by: Craig Stickel////(C) April 9, 2007/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BEGIN HEADER /////////////////////////////////////////////#pragma once// System #includes ///////////////////////////////////////////////////////////////////////////#define WIN32_LEAN_AND_MEAN#include <windows.h>// Win32 commands#include <stdlib.h>// Borrows some number converting routines// Symbolic Constants /////////////////////////////////////////////////////////////////////////// Dimensionsconst int SCREEN_WIDTH = 80;const int SCREEN_HEIGHT = 25;// System Configurationsconst DWORD CONSOLE_MODE = ENABLE_PROCESSED_OUTPUT;// CExtendedWin32Console Class Declaration ////////////////////////////////////////////////////class CExtendedWin32Console{public:// Constructors and Destructors ///////////////////////////////////////////////////////// Default constructorCExtendedWin32Console(){// Retrieve console handles for input and outputthis->hConsoleInput= (HWND)GetStdHandle( STD_INPUT_HANDLE );this->hConsoleOutput= (HWND)GetStdHandle( STD_OUTPUT_HANDLE );// Configure console modesSetConsoleMode( this->hConsoleInput, NULL );SetConsoleMode( this->hConsoleOutput, CONSOLE_MODE );// Set console screen sizeSMALL_RECT smRect;smRect.Left = 0;smRect.Top = 0;smRect.Right = SCREEN_WIDTH - 1;smRect.Bottom = SCREEN_HEIGHT - 1;SetConsoleWindowInfo( this->hConsoleOutput, TRUE, &smRect );// Hide the cursorCONSOLE_CURSOR_INFO info;info.bVisible= false;info.dwSize= 100;SetConsoleCursorInfo( this->hConsoleOutput, &info );}~CExtendedWin32Console(){}// Public Methods /////////////////////////////////////////////////////////////////////// Clears the screenvoid Clear( void ){// Change the screen mode to allow wrappingSetConsoleMode( this->hConsoleOutput, ENABLE_WRAP_AT_EOL_OUTPUT );// Read the current attributeCONSOLE_SCREEN_BUFFER_INFO info;GetConsoleScreenBufferInfo( this->hConsoleOutput, &info );// Clear the screenCOORD dwCoord= { 0, 0 };DWORD dwWritten;FillConsoleOutputCharacter( this->hConsoleOutput, ' ', SCREEN_WIDTH * SCREEN_HEIGHT,dwCoord, &dwWritten );FillConsoleOutputAttribute( this->hConsoleOutput, info.wAttributes,SCREEN_WIDTH * SCREEN_HEIGHT, dwCoord, &dwWritten );// Move cursor back to start of the screen (coordinates 0,0)SetConsoleCursorPosition( this->hConsoleOutput, dwCoord );// Change back to the normal console modeSetConsoleMode( this->hConsoleOutput, CONSOLE_MODE );}// Draws a character to the consoleCExtendedWin32Console &operator <<( char nCharacter ){DWORD dwWritten;WriteConsole( this->hConsoleOutput, &nCharacter, 1, &dwWritten, NULL );// Return this instance to expediate concurrent function callsreturn *this;}// Draws a string to the consoleCExtendedWin32Console &operator <<( const char * p_szString ){DWORD dwWritten;WriteConsole( this->hConsoleOutput, p_szString, strlen( p_szString ), &dwWritten, NULL );// Return this instance to expediate concurrent function callsreturn *this;}// Draws an integer to the consoleCExtendedWin32Console &operator <<( signed int nInt ){// Convert the integer into a stringchar szBuffer[ 12 ];itoa( nInt, szBuffer, 10 );DWORD dwWritten;WriteConsole( this->hConsoleOutput, szBuffer, strlen( szBuffer ), &dwWritten, NULL );return *this;}CExtendedWin32Console &operator <<( signed long nInt ){// Convert the integer into a stringchar szBuffer[ 12 ];itoa( nInt, szBuffer, 10 );DWORD dwWritten;WriteConsole( this->hConsoleOutput, szBuffer, strlen( szBuffer ), &dwWritten, NULL );}CExtendedWin32Console &operator <<( signed short nInt ){// Convert the integer into a stringchar szBuffer[ 12 ];itoa( nInt, szBuffer, 10 );DWORD dwWritten;WriteConsole( this->hConsoleOutput, szBuffer, strlen( szBuffer ), &dwWritten, NULL );}CExtendedWin32Console &operator <<( unsigned int nInt ){// Convert the integer into a stringchar szBuffer[ 12 ];itoa( nInt, szBuffer, 10 );DWORD dwWritten;WriteConsole( this->hConsoleOutput, szBuffer, strlen( szBuffer ), &dwWritten, NULL );}CExtendedWin32Console &operator <<( unsigned long nInt ){// Convert the integer into a stringchar szBuffer[ 12 ];itoa( nInt, szBuffer, 10 );DWORD dwWritten;WriteConsole( this->hConsoleOutput, szBuffer, strlen( szBuffer ), &dwWritten, NULL );}CExtendedWin32Console &operator <<( unsigned short nInt ){// Convert the integer into a stringchar szBuffer[ 12 ];itoa( nInt, szBuffer, 10 );DWORD dwWritten;WriteConsole( this->hConsoleOutput, szBuffer, strlen( szBuffer ), &dwWritten, NULL );}// Draws a double to the consoleCExtendedWin32Console &operator <<( double dDouble ){// Convert the double to a stringint nDec;int nSign;char *p_szBuffer = _fcvt( dDouble, 7, &nDec, &nSign );// Create a copy of the stringint nLen = strlen( p_szBuffer );char *p_szString = new char[ nLen + 3 ];// +1 for negative sign (if needed), +1 for// decimal point, +1 for null character// Add the negative if not presentif( nSign ){p_szString[0] = '-';nSign = 1;// Just in case for the next command (nSign is not guaranteed to// be 1 if a negative symbol is needed)}// Copy up until the decimal pointstrncpy( p_szString + nSign, p_szBuffer, nDec );// Insert decimal pointp_szString[ nDec + nSign ] = '.';// Copy remaining portionstrcpy( p_szString + nSign + nDec + 1, p_szBuffer + nDec );// Remove any trailing zerosint nDrawLen;for( nDrawLen = nLen; nDrawLen > 0; nDrawLen-- ){if( p_szString[nDrawLen] == '0' )nDrawLen--;elsebreak;}// Because of the way the method works, nDrawLen is actually one less than it should benDrawLen++;DWORD dwWritten;WriteConsole( this->hConsoleOutput, p_szString, nDrawLen, &dwWritten, NULL );// Deallocate memorydelete [] p_szString;// Return this instance to expediate concurrent function callsreturn *this;}// Changes the color attributes of the console outputvoid SetColor( int nColor ){SetConsoleTextAttribute( this->hConsoleOutput, nColor );}// Changes the current position of console outputvoid SetPosition( int nPosX, int nPosY ){COORD dwCoord = { nPosX, nPosY };SetConsoleCursorPosition( this->hConsoleOutput, dwCoord );}private:// Private Properties /////////////////////////////////////////////////////////////////// Input handle for the consoleHWND hConsoleInput;// Output handle for the consoleHWND hConsoleOutput;} console;//////////////////////////////////////// END OF HEADER ///////////////////////////////////////////
  Well this has something to do with the Arrow keys and ASCII codes.  It seems it works fine for the main method , but when It comes to the 2 functions when the getch() function is working it is pulling in "M" instead of right arrow (or 77), i don't get it.When i change to use numbers as the input 8,2,4, and 6  (num pad usage) it seems to work fine, so something is off with the functions picking up the arrow keys.   ;  I had this problem a while back when writing a similar game. Turns out that getch() actually consumes TWO characters when you press an arrow key: one byte with the value of 0xE0 and then the actual arrow key code.The easy solution is to do something likeint key = getch();...switch (key){case 0xE0:int arrow = getch();// process arrow key herebreak;}The other way out is to use actual Windows console events. Look into ReadConsoleInput and INPUT_RECORD on MSDN.EDIT: I just tried setting up a little kbhit/getch project on my computer and I actually get 0xE0 instead of a null byte. I have revised my post to reflect this.[Edited by - Kuraitou on May 25, 2010 12:05:11 AM]