//SmallSocket.cpp
/*
Copyright (C) 2004 Anders Hedstrom
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//#include <stdio.h>
#include <Parse.h>
#include "SmallHandler.h"
#include "World.h"
#include "cstring.h"
#include "ItemFactory.h"
#include "SmallSocket.h"
SmallSocket::SmallSocket(SocketHandler& h)
:TcpSocket(h)
,m_state(STATE_LOGIN)
,m_name("")
,m_x(0)
,m_y(0)
,m_player(NULL)
{
SetLineProtocol();
}
SmallSocket::~SmallSocket()
{
}
void SmallSocket::Send(const std::string& str)
{
cstring q;
q = str;
TcpSocket::Send( q.c_str() );
}
void SmallSocket::OnAccept()
{
Send("&WWelcome.&n\n");
SendPrompt();
}
void SmallSocket::OnLine(const std::string& line)
{
switch (m_state)
{
case STATE_LOGIN:
// check player
// exist - ask password STATE_PASSWORD
// don't exist - ask new player question STATE_NEW_PLAYER_QUESTION
m_player = GetPlayerF().FindPlayer(line, "");
if (m_player)
{
m_state = STATE_PASSWORD;
}
else
{
m_name = line;
m_state = STATE_NEW_PLAYER_QUESTION;
}
SendPrompt();
break;
case STATE_PROMPT:
if (line.size())
{
Parse pa(line);
std::string cmd = pa.getword();
if (line[0] == 34 || line[0] == '\'')
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " says '" + line.substr(1) + "'\n",this);
Send("You say '" + line.substr(1) + "&n'\n");
}
else
if (line[0] == '!')
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " shouts '" + line.substr(1) + "'\n",this,true);
Send("You shout '" + line.substr(1) + "&n'\n");
}
else
if (line == "n" || line == "s" || line == "e" || line == "w")
{
try_move(line);
static_cast<SmallHandler&>(Handler()).ShowCell(this);
}
else
if (line == "l")
{
static_cast<SmallHandler&>(Handler()).ShowCell(this);
}
else
if (line == "who")
{
static_cast<SmallHandler&>(Handler()).Who(this);
}
else
if (line == "quit")
{
m_state = STATE_QUIT;
}
else
if (cmd == "get")
{
TryGet(this, pa.getrest());
}
else
if (cmd == "drop")
{
TryDrop(this, pa.getrest());
}
else
if (line == "i")
{
m_player -> DisplayInventory(this);
}
else
if (line == "status")
{
static_cast<SmallHandler&>(Handler()).ShowStatus(this);
}
else
if (line == "help")
{
Send("n / s / e / w - move around\n");
Send("l - look around\n");
Send("get / drop <item>\n");
Send("i - display inventory\n");
Send("' / \" - talk ( as in >\"hi )\n");
Send("! - shout ( as in >!Hello anyone??? )\n");
Send("who - is online\n");
Send("status - show game status\n");
Send("help\nquit\n");
}
else
{
Send("Command not recognized - try '&Whelp&n'\n");
}
}
SendPrompt();
break;
case STATE_QUIT:
break;
case STATE_PASSWORD:
if (line == m_player -> m_passwd)
{
std::string str;
m_name = m_player -> m_name;
m_state = STATE_PROMPT;
GetWorld().GetRandomLocation(m_x,m_y,str);
Send("Welcome back, " + m_player -> m_name + ".\n");
Send("You wake up in a room: " + str + "\n");
}
else
{
m_state = STATE_LOGIN;
}
SendPrompt();
break;
case STATE_NEW_PLAYER_QUESTION:
if (!line.size() || line[0] == 'y' || line[0] == 'Y')
{
m_state = STATE_PASSWORD_1;
}
else
{
m_state = STATE_LOGIN;
}
SendPrompt();
break;
case STATE_PASSWORD_1:
if (line.size() > 3)
{
m_passwd = line;
m_state = STATE_PASSWORD_2;
}
else
{
Send("Enter at least 4 characters.\n");
}
SendPrompt();
break;
case STATE_PASSWORD_2:
if (line == m_passwd)
{
m_player = GetPlayerF().AddPlayer(m_name,m_passwd);
m_state = STATE_PASSWORD;
OnLine(line);
GetPlayerF().Save();
}
else
{
Send("Password mismatch - try again\n");
m_state = STATE_NEW_PLAYER_QUESTION;
SendPrompt();
}
break;
}
}
void SmallSocket::SendPrompt()
{
switch (m_state)
{
case STATE_LOGIN:
Send("Enter name: ");
break;
case STATE_PROMPT:
Send("> ");
break;
case STATE_QUIT:
Send("Goodbye!\n");
SetCloseAndDelete();
break;
case STATE_PASSWORD:
Send("Enter password: ");
break;
case STATE_NEW_PLAYER_QUESTION:
Send("Create a new player (Y,n)? ");
break;
case STATE_PASSWORD_1:
Send("Enter new player password: ");
break;
case STATE_PASSWORD_2:
Send("Repeat password: ");
break;
}
}
bool SmallSocket::IsAt(int x,int y)
{
if (m_x == x && m_y == y)
return true;
return false;
}
void SmallSocket::try_move(const std::string& dir)
{
std::string name;
bool n,s,e,w;
GetWorld().GetAt(m_x,m_y,name,n,s,e,w);
if (dir == "n")
{
if (n && GetWorld().FindAt(m_x,m_y - 1,name))
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " leaves north\n",this);
m_y--;
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " enters from the south\n",this);
return;
}
}
else
if (dir == "s")
{
if (s && GetWorld().FindAt(m_x,m_y + 1,name))
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " leaves south\n",this);
m_y++;
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " enters from the north\n",this);
return;
}
}
else
if (dir == "e")
{
if (e && GetWorld().FindAt(m_x + 1,m_y,name))
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " leaves east\n",this);
m_x++;
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " enters from the west\n",this);
return;
}
}
else
if (dir == "w")
{
if (w && GetWorld().FindAt(m_x - 1,m_y,name))
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " leaves west\n",this);
m_x--;
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " enters from the east\n",this);
return;
}
}
Send("&ROuch!&n\n");
}
void SmallSocket::TryGet(SmallSocket *sendto,const std::string& item)
{
item_v& ref = static_cast<SmallHandler&>(Handler()).GetItems(m_x,m_y);
item_v& ref_to = m_player -> GetInventory();
for (item_v::iterator it = ref.begin(); it != ref.end(); it++)
{
ITEM *i = *it;
bool ok;
if (i -> m_amount > 1)
{
ok = !strcmp(i -> m_plural.uc_str(), item.c_str());
}
else
{
ok = !strcmp(i -> m_name.uc_str(), item.c_str());
}
if (ok)
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " picks up " + i -> GetDescription() + "\n",this);
Send("You pick up " + i -> GetDescription() + "\n");
static_cast<SmallHandler&>(Handler()).MergeItem(ref_to,i);
ref.erase(it);
break;
}
}
}
void SmallSocket::TryDrop(SmallSocket *sendto,const std::string& item)
{
item_v& ref = m_player -> GetInventory();
item_v& ref_to = static_cast<SmallHandler&>(Handler()).GetItems(m_x,m_y);
for (item_v::iterator it = ref.begin(); it != ref.end(); it++)
{
ITEM *i = *it;
bool ok;
if (i -> m_amount > 1)
{
ok = !strcmp(i -> m_plural.uc_str(), item.c_str());
}
else
{
ok = !strcmp(i -> m_name.uc_str(), item.c_str());
}
if (ok)
{
static_cast<SmallHandler&>(Handler()).Event(m_x,m_y,m_name + " drops " + i -> GetDescription() + "\n",this);
Send("You drop " + i -> GetDescription() + "\n");
static_cast<SmallHandler&>(Handler()).MergeItem(ref_to,i);
ref.erase(it);
break;
}
}
}