/*
 *** TXTGAME4.CPP ***
 VERSION 4.0 OF TEXTGAME
 Written by lightatdawn
 Yet another complete rewrite. This version will enscapulate everything in
 classes to enable easier use and more organised code. As your programs start
 getting larger you will begin to see the incredible advantages that classes
 give you. It will be neccesary to break the single file format of the previous
 versions. This version requires two header files in addition to the main CPP
 file. Make sure you have downloaded them and placed them in the same directory
 as this file.
 NOTE:
 The CWorld class contains most of the comments regarding the use of
 classes and you may wish te begin you're reading there. Then on to
 CCharacter.h, CGame,h and finally this file. I know you started here
 first so get lost. Go. Get out of here!
 [Apu Voice]Thank you come again (if you survive).[/Apu Voice]
 ADDITIONS from version 3:
 -Header file implementation
 -Classes for World, Game, and Character
 -Idle Time Processing
 -Incredibly confusing and horribly long comments
 -Same program. Very much more code. Very much better program.
 ROOM FOR IMPROVEMENT:
 -Parsing of item data into separate words to allow input such as
	'get key' instead of forcing the full 'get iron key'.
 -Equal parsing for item use.
 -Further error checking in areas indicated by comments, and others.
 -Item data loading from script based file.
*/
//******************************************************************************
//* INCLUDE FILES                                                              *
//******************************************************************************
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
//***
//We need to include the header files for CGame CCharcter, and CWorld
//which contain the description of those classes which we're going to be
//which contain the
//***
#include "CWorld.h"
#include "CCharacter.h"
#include "CGame.h"
//******************************************************************************
//* MAIN PROCEDURE                                                             *
//******************************************************************************
int main(void)
{
	//***************************************************************************
	//* MISCLANIOUS VARIABLE DECLARATION                                        *
	//***************************************************************************
	FILE * fp; //our file pointer for loading files
	int
		command_accepted = 0,
		loop = 0,
		in_loop = 0;
	char
		user_input[30];
	//Here we are creating our instance of the classes we're going
	//to use. You can think of the CWorld, CGame, and CCharacter
	//classes as new variable types we have created with special
	//uses.
	CWorld		World;
	CGame		Game;
	CCharacter	Character;
	//MAP OF THE WORLD
	//The ---- and the | are the squares. The "#" are the walls (duh!)
    /*
    |------------------|-------------------|-------------------|
    |##################|###################|###################|
    |#                #|#                  |                  #|
    |#                #|#                  |    Another       #|
    |#  You cant ever #|#   Really Dark    |   Really Dark    #|
    |#   get to this  #|#       Room       |      Room        #|
    |#     square     #|#                  |                  #|
    |#                #|#                  |                  #|
    |##################|########   ########|###################|
    |------------------|-------------------|-------------------|
    |##################|########   ########|###################|
    |#                #|#                 #|#                 #|
    |#                 |                  #|#                 #|
    |#                 |     Open Room     |      Moldy       #|
    |#     Empty Room #|#                  |        Room      #|
    |#                #|#                 #|#                 #|
    |#                #|#                 #|#                 #|
    |#                #|#######     #######|#                 #|
    |------------------|-------------------|-------------------|
    |#                #|#######[---]#######|#                 #|
    |#                #|#        Locked   #|#                 #|
    |#                #|#          Iron   #|#                 #|
    |#  Empty Room    #|#            Door #|#                 #|
    |#                #|#                 #|#       Oaken     #|
    |#                #|#    You are      #|#         Throne  #|
    |#                #|#      Here       #|#      [****]     #|
    |##################|###################|###################|
    |------------------|-------------------|-------------------|
    */
	//****************************************************************************
	//IMPORTANT: Make sure you have downloaded 'TextData.Map' as well as this file
	//			 or this isn't going to work.
	//****************************************************************************
	//NOTE: Also you can download a small application on the same page you found
	//		this (lightatdawn.cprogramming.com). It demonstrates a simple way to
	//		create a MAP file in the format used here without much effort on your
	//		part. Its useful for creating a default MAP template of your world
	//		without having to do one hell of a lot of typing. Check it out.
	//****************************************************************************
	//We call the World classes member function LoadMap() now
	//which does all the loading that used to be here in 3.0.
	//We also check to se if we recieved an error from LoadMap
	//and we exit if we did. If LoadMap returns anything except
	//S_OK then we consider it a problem.
	if (World.LoadMap() != S_OK)
		return -1;
	//We call the Game classes member function LoadItems() now
	//which does all the loading that used to be here in 3.0.
	if (Game.LoadItems() != S_OK)
		return -1;
	//***************************************************************************
	//* MAIN LOOP                                                               *
	//***************************************************************************
	//So that the text is printed the first time around...
	command_accepted = 1;
	do
	{
		printf("\n\n");
		if (command_accepted == 1)
		{
			//Now we call the Worlds DescribeRoom function to display
			//all the text about this room. We have to pass in the
			//characters world position to the function so that it
			//knows what room to display.
			//We check DescribeRoom() and see it it returned E_INVALIDARG.
			//If it did, then we're out of legal bounds and we say so.
			if (World.DescribeRoom(Character.location_x, Character.location_y) == E_INVALIDARG)
			{
				printf("\nERROR: Out of World Bounds!\n");
			}
			//Now we do the same for the Items
			//We dont bother error checking since theres no real need to.
			//The possible error isnt very severe and we dont need to be
			//warned twice since DescribeRoom already handled the problem
			Game.ShowItems(Character.location_x, Character.location_y);
		}//end if
		//************************************************************************
		//* GET INPUT FROM USER                                                  *
		//************************************************************************
		gets(user_input);
		printf("\n\n");
		//************************************************************************
		//* EXECUTE THE INPUT (DO STUFF)                                         *
		//************************************************************************
		//Now we check if the user is trying to walk anywhere.
		if (stricmp(user_input, "north") == 0 ||
			stricmp(user_input, "n") == 0 ||
			stricmp(user_input, "go north") == 0 ||
			stricmp(user_input, "walk north") == 0)
		{
			Character.location_y = World.GoNorth(Character.location_x, Character.location_y);
			command_accepted = 1;
		}
		if (stricmp(user_input, "south") == 0 ||
			stricmp(user_input, "s") == 0 ||
			stricmp(user_input, "go south") == 0 ||
			stricmp(user_input, "walk south") == 0)
		{
			Character.location_y = World.GoSouth(Character.location_x, Character.location_y);
			command_accepted = 1;
		}
		if (stricmp(user_input, "east") == 0 ||
			stricmp(user_input, "e") == 0 ||
			stricmp(user_input, "go east") == 0 ||
			stricmp(user_input, "walk east") == 0)
		{
			Character.location_x = World.GoEast(Character.location_x, Character.location_y);
			command_accepted = 1;
		}
		if (stricmp(user_input, "west") == 0 ||
			stricmp(user_input, "w") == 0 ||
			stricmp(user_input, "go west") == 0 ||
			stricmp(user_input, "walk west") == 0)
		{
			Character.location_x = World.GoWest(Character.location_x, Character.location_y);
			command_accepted = 1;
		}
		//GET ITEMS
		if (strnicmp(user_input, "get", 3) == 0 ||
			strnicmp(user_input, "grab", 4) == 0 ||
			strnicmp(user_input, "take", 4) == 0)
		{
			//We call a CGame function to get items now.
			//Even though GetItems() returns an HRESULT, it currently
			//cant return anything except S_OK so we dont need to
			//do any checking here.
			Game.GetItems(user_input, &Character);
			command_accepted = 1;
		}
		//USE ITEMS
		if (strnicmp(user_input, "use", 3) == 0)
		{
			//We call a CGame function to use items now.
			Game.UseItem(user_input, &Character, &World);
			command_accepted = 1;
		}
		//DROP ITEMS
		if (strnicmp(user_input, "drop", 4) == 0)
		{
			//We call a CGame function to drop items now.
			Game.DropItem(user_input, Character.location_x, Character.location_y);
			command_accepted = 1;
		}
		//CAST SPELLS
		if (strnicmp(user_input, "cast", 4) == 0)
		{
			Character.CastSpell(user_input, &World);
			command_accepted = 1;
		}
		//SEARCH THE ROOM
		if (stricmp(user_input, "search") == 0 ||
			stricmp(user_input, "look") == 0)
		{
			Game.Search(Character.location_x, Character.location_y);
			command_accepted = 3;
		}
		//INVENTORY LIST
		if (stricmp(user_input, "inven") == 0 || stricmp(user_input, "inventory") == 0)
		{
			Game.Inventory(Character.gold);
			command_accepted = 3;
		}
		//SPELLS LIST
		if (stricmp(user_input, "spells") == 0 ||
			stricmp(user_input, "spell") == 0 ||
			stricmp(user_input, "spellbook") == 0)
		{
			Character.SpellList();
			command_accepted = 3;
		}
		//A FEW VARIOUS COMMANDS
		if (strnicmp(user_input, "yell", 4) == 0 || strnicmp(user_input, "scream", 6) == 0)
		{
			printf("\nThrowing a tantrum isn't going to get you anywhere.\n");
			command_accepted = 3;
		}
		if (strnicmp(user_input, "jump", 4) == 0 || strnicmp(user_input, "leap", 4) == 0 ||
			strnicmp(user_input, "hop", 3) == 0)
		{
			printf("\nYou're not a frog, you're a human. Do what humans do... Walk.\n");
			command_accepted = 3;
		}
		if (strnicmp(user_input, "smash", 5) == 0 || strnicmp(user_input, "break", 5) == 0 ||
			strnicmp(user_input, "wreck", 5) == 0 || strnicmp(user_input, "destroy", 7) == 0)
		{
			printf("\nWell aren't we feeling violent today! Your not going to do anything but hurt\n");
			printf("yourself if you keep that up.\n");
			command_accepted = 3;
		}
		if (strnicmp(user_input, "climb", 5) == 0)
		{
			printf("\nThere is nothing to climb here.\n");
			command_accepted = 3;
		}
		if (strnicmp(user_input, "eat", 3) == 0)
		{
			printf("\nYou are a little hungry but you'll have to wait until you get back to your\n");
			printf("village before you can do that. Theres nothing edible around here.\n");
			command_accepted = 3;
		}
		//************************************************************************
		//* SAVE THE GAME                                                        *
		//************************************************************************
		if (stricmp(user_input, "save") == 0)
		{
			//we want to open our file for write and in binary
			fp = fopen("SAVEGAME.BIN", "wb");
			
			if (fp != NULL)
			{
				fwrite(&Character, sizeof(Character), 1, fp);
				fwrite(&Game, sizeof(Game), 1, fp);
				fwrite(&World, sizeof(World), 1, fp);
				fclose(fp);
			}
			else
				printf("\nError writing to file!\nGame not saved!\n");
			command_accepted = 1;
		}
		//************************************************************************
		//* LOAD THE GAME                                                        *
		//************************************************************************
		if (stricmp(user_input, "load") == 0)
		{
			fp = fopen("SAVEGAME.BIN", "rb");
			if (fp != NULL)
			{
				fread(&Character, sizeof(Character), 1, fp);
				fread(&Game, sizeof(Game), 1, fp);
				fread(&World, sizeof(World), 1, fp);
				fclose(fp);
			}
			else
				printf("\nError loaded to file!\nGame not loaded!\n");
			command_accepted = 1;
		}
		//if the user entered a command that is not a valid command, then command_accepted
		//will still be zero (as it was declared above). So do this:
		if (command_accepted == 0 && stricmp(user_input, "quit") != 0)
			printf("\nPlease re-phrase your statement...\n");
	//END OF LOOP! IF THE INPUT ISNT "QUIT" THEN GO BACK UP TO THE TOP
	}while(stricmp(user_input, "quit") != 0);
	//Hello! The input must've equalled "QUIT" cus we're out here now... the end
	return 0;
}