示例#1
0
int32 String::Compare(const String& stringA, const String& stringB, bool caseSensitive)
{
	if (!caseSensitive)
	{
		return String::Compare(stringA.ToLower(), stringB.ToLower(), true);
	}

	return strcmp(stringA.Cstr(), stringB.Cstr());
}
示例#2
0
   bool
   StringParser::WildcardMatchNoCase(const String &sWildcard, const String &sString)
   {
      String sLowerWild = sWildcard;
      String sLowerStr = sString;

      sLowerWild.ToLower();
      sLowerStr.ToLower();

      return WildcardMatch(sLowerWild, sLowerStr);
   }
示例#3
0
void FilterUtility::CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **permissionFilter)
{
	if (permissionFilter)
		*permissionFilter = nullptr;

	if (permission.IsEmpty())
		return;

	bool foundPermission = false;
	String requiredPermission = permission.ToLower();

	Array::Ptr permissions = user->GetPermissions();
	if (permissions) {
		ObjectLock olock(permissions);
		for (const Value& item : permissions) {
			String permission;
			Function::Ptr filter;
			if (item.IsObjectType<Dictionary>()) {
				Dictionary::Ptr dict = item;
				permission = dict->Get("permission");
				filter = dict->Get("filter");
			} else
				permission = item;

			permission = permission.ToLower();

			if (!Utility::Match(permission, requiredPermission))
				continue;

			foundPermission = true;

			if (filter && permissionFilter) {
				std::vector<std::unique_ptr<Expression> > args;
				args.emplace_back(new GetScopeExpression(ScopeLocal));
				std::unique_ptr<Expression> indexer{new IndexerExpression(std::unique_ptr<Expression>(MakeLiteral(filter)), std::unique_ptr<Expression>(MakeLiteral("call")))};
				FunctionCallExpression *fexpr = new FunctionCallExpression(std::move(indexer), std::move(args));

				if (!*permissionFilter)
					*permissionFilter = fexpr;
				else
					*permissionFilter = new LogicalOrExpression(std::unique_ptr<Expression>(*permissionFilter), std::unique_ptr<Expression>(fexpr));
			}
		}
	}

	if (!foundPermission) {
		Log(LogWarning, "FilterUtility")
			<< "Missing permission: " << requiredPermission;

		BOOST_THROW_EXCEPTION(ScriptError("Missing permission: " + requiredPermission));
	}
}
示例#4
0
bool BuildCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
{
    String argument = arguments[startIndex].ToLower();
    String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

    if (argument != "build")
    {
        errorMsg = "Unable to parse build command";
        return false;
    }

    if (!value.Length())
    {
        errorMsg = "Unable to parse build platform";
        return false;
    }

    buildPlatform_ = value.ToLower();

    for (int i = startIndex + 2; i < arguments.Size(); ++i)
    {
        String option = arguments[i].ToLower();
        
        if (option == "-tag")
        {
            if (arguments.Size() == i + 1)
            {
                errorMsg = "Missing tag";
                return false;
            }
        }
        else if (option == "-autolog")
        {
            autoLog_ = true;
        }
        else
        {
            errorMsg = "Invalid option: " + option;
            return false;
        }
    }

    String tag = startIndex + 2 < arguments.Size() ? arguments[startIndex + 2] : String::EMPTY;

    assetsBuildTag_ = tag.ToLower();

    return true;
}
示例#5
0
void SplitPath(const String& fullPath, String& pathName, String& fileName, String& extension, bool lowercaseExtension)
{
    String fullPathCopy = GetInternalPath(fullPath);

    unsigned extPos = fullPathCopy.FindLast('.');
    unsigned pathPos = fullPathCopy.FindLast('/');

    if (extPos != String::NPOS && (pathPos == String::NPOS || extPos > pathPos))
    {
        extension = fullPathCopy.Substring(extPos);
        if (lowercaseExtension)
            extension = extension.ToLower();
        fullPathCopy = fullPathCopy.Substring(0, extPos);
    }
    else
        extension.Clear();

    pathPos = fullPathCopy.FindLast('/');
    if (pathPos != String::NPOS)
    {
        fileName = fullPathCopy.Substring(pathPos + 1);
        pathName = fullPathCopy.Substring(0, pathPos + 1);
    }
    else
    {
        fileName = fullPathCopy;
        pathName.Clear();
    }
}
示例#6
0
TextureUnit ParseTextureUnitName(String name)
{
    name = name.ToLower().Trimmed();

    TextureUnit unit = (TextureUnit)GetStringListIndex(name.CString(), textureUnitNames, MAX_TEXTURE_UNITS);
    if (unit == MAX_TEXTURE_UNITS)
    {
        // Check also for shorthand names
        if (name == "diff")
            unit = TU_DIFFUSE;
        else if (name == "albedo")
            unit = TU_DIFFUSE;
        else if (name == "norm")
            unit = TU_NORMAL;
        else if (name == "spec")
            unit = TU_SPECULAR;
        else if (name == "env")
            unit = TU_ENVIRONMENT;
        // Finally check for specifying the texture unit directly as a number
        else if (name.Length() < 3)
            unit = (TextureUnit)Clamp(ToInt(name), 0, MAX_TEXTURE_UNITS - 1);
    }

    if (unit == MAX_TEXTURE_UNITS)
        LOGERROR("Unknown texture unit name " + name);

    return unit;
}
示例#7
0
String SystemLinux::GetDataDirName(const String &sName) const
{
	// Return ".<name>"
	String sLower = sName;
	sLower.ToLower();
	return "." + sLower;
}
示例#8
0
unsigned Technique::GetPassIndex(const String& passName)
{
    // Initialize built-in pass indices on first call
    if (passIndices.Empty())
    {
        basePassIndex = passIndices["base"] = 0;
        alphaPassIndex = passIndices["alpha"] = 1;
        materialPassIndex = passIndices["material"] = 2;
        deferredPassIndex = passIndices["deferred"] = 3;
        lightPassIndex = passIndices["light"] = 4;
        litBasePassIndex = passIndices["litbase"] = 5;
        litAlphaPassIndex = passIndices["litalpha"] = 6;
        shadowPassIndex = passIndices["shadow"] = 7;
    }

    String nameLower = passName.ToLower();
    HashMap<String, unsigned>::Iterator i = passIndices.Find(nameLower);
    if (i != passIndices.End())
        return i->second_;
    else
    {
        unsigned newPassIndex = passIndices.Size();
        passIndices[nameLower] = newPassIndex;
        return newPassIndex;
    }
}
示例#9
0
/**
*  @brief
*    Returns a cell with the given name
*/
PLSceneCell *PLSceneContainer::GetCell(const String &sName, IGameNode &cIGameNode)
{
	// Check the given name
	if (!sName.GetLength())
		return nullptr; // Error!

	// First at all, IS there already a cell with this name?
	String sNameLower = sName;
	sNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values!
	std::map<String, PLSceneCell*>::iterator pIterator = m_mapCells.find(sNameLower);
	if (pIterator != m_mapCells.end())
		return pIterator->second;

	// Nope, let's create a cell with this name
	g_pLog->LogFLine(PLLog::Scene, "Cell '%s' is created by the 3ds Max node '%s'", sName.GetASCII(), cIGameNode.GetName());
	PLSceneCell *pCell = new PLSceneCell(*this, sName);
	if (pCell) {
		// Register the new cell
		m_lstSceneNodes.push_back(pCell);
		m_mapCells.insert(std::make_pair(sNameLower, pCell));
		m_mapNodes.insert(std::make_pair(sNameLower, pCell));

		// Update the statistics
		m_sStatistics.nNumOfCells++;
		GetScene().m_sSceneStatistics.nNumOfCells++;
	}

	// Return the created cell
	return pCell;
}
示例#10
0
bool PackageFile::Open(const String& fileName)
{
    SharedPtr<File> file(new File(context_, fileName));
    if (!file->IsOpen())
        return false;
    
    // Check ID, then read the directory
    if (file->ReadFileID() != "UPAK")
    {
        LOGERROR(fileName + " is not a valid package file");
        return false;
    }
    
    fileName_ = fileName;
    nameHash_ = fileName_;
    totalSize_ = file->GetSize();
    
    unsigned numFiles = file->ReadUInt();
    checksum_ = file->ReadUInt();
    
    for (unsigned i = 0; i < numFiles; ++i)
    {
        String entryName = file->ReadString();
        PackageEntry newEntry;
        newEntry.offset_ = file->ReadUInt();
        newEntry.size_ = file->ReadUInt();
        newEntry.checksum_ = file->ReadUInt();
        if (newEntry.offset_ + newEntry.size_ > totalSize_)
            LOGERROR("File entry " + entryName + " outside package file");
        else
            entries_[entryName.ToLower()] = newEntry;
    }
    
    return true;
}
 AnchorInfo::AnchorInfo(Syntax::Expression& expr, int offset, int width, String str, bool ignore)
   :_expr(&expr)
   ,_pos(Position::Any)
   ,_offset(offset)
   ,_str(ignore ? new String(str.ToLower()) : new String(str))
   ,_width(width)
   ,_ignore(ignore) 
   {
   }
String getNormalizedPath(const String& path)
{
    // Full path is the fully qualified path from the root of the filesystem.  In order
    // to take advantage of the resource caching system, let's trim it down to just the
    // path inside the resources directory including the Resources directory so that the casing
    // is correct.
    const String& RESOURCES_MARKER = "resources/";
    return path.SubstringUTF8(path.ToLower().Find(RESOURCES_MARKER));
}
示例#13
0
void FilterUtility::CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **permissionFilter)
{
	if (permissionFilter)
		*permissionFilter = NULL;

	if (permission.IsEmpty())
		return;

	bool foundPermission = false;
	String requiredPermission = permission.ToLower();

	Array::Ptr permissions = user->GetPermissions();
	if (permissions) {
		ObjectLock olock(permissions);
		BOOST_FOREACH(const Value& item, permissions) {
			String permission;
			Function::Ptr filter;
			if (item.IsObjectType<Dictionary>()) {
				Dictionary::Ptr dict = item;
				permission = dict->Get("permission");
				filter = dict->Get("filter");
			} else
				permission = item;

			permission = permission.ToLower();

			if (!Utility::Match(permission, requiredPermission))
				continue;

			foundPermission = true;

			if (filter && permissionFilter) {
				std::vector<Expression *> args;
				args.push_back(new GetScopeExpression(ScopeLocal));
				FunctionCallExpression *fexpr = new FunctionCallExpression(new IndexerExpression(MakeLiteral(filter), MakeLiteral("call")), args);

				if (!*permissionFilter)
					*permissionFilter = fexpr;
				else
					*permissionFilter = new LogicalOrExpression(*permissionFilter, fexpr);
			}
		}
	}
示例#14
0
const wchar_t* Menus::MenuInfoItemTextHandler(MenuItem* sender)
{
	static String string;

	switch(sender->GetId())
	{
	case 1: // Current vis
		string = GetKernel()->GetGraphics()->GetVisualizationName(GetKernel()->GetGraphics()->GetVisualizationIndex());
		string.ToLower();
		return string;

	case 2: // Curent color preset
		string = GetKernel()->GetGraphics()->GetColorPresetName(GetKernel()->GetGraphics()->GetColorPresetIndex());
		string.ToLower();
		return string;
	}

	return false;
}
// Registers a shorthand property definition.
bool PropertySpecification::RegisterShorthand(const String& shorthand_name, const String& property_names, ShorthandType type)
{
	StringList properties;
	StringUtilities::ExpandString(properties, property_names.ToLower());

	if (properties.empty())
		return false;

	String lower_case_name = shorthand_name.ToLower();

	// Construct the new shorthand definition and resolve its properties.
	PropertyShorthandDefinition* property_shorthand = new PropertyShorthandDefinition();
	for (size_t i = 0; i < properties.size(); i++)
	{
		const PropertyDefinition* property = GetProperty(properties[i]);
		if (property == NULL)
		{
			Log::Message(Log::LT_ERROR, "Shorthand property '%s' was registered with invalid property '%s'.", shorthand_name.CString(), properties[i].CString());
			delete property_shorthand;

			return false;
		}

		property_shorthand->properties.push_back(PropertyShorthandDefinition::PropertyDefinitionList::value_type(properties[i], property));
	}

	if (type == AUTO)
	{
		if (properties.size() == 4 &&
			properties[0].Find("-top") != String::npos &&
			properties[1].Find("-right") != String::npos &&
			properties[2].Find("-bottom") != String::npos &&
			properties[3].Find("-left") != String::npos)
			property_shorthand->type = BOX;
		else
			property_shorthand->type = FALL_THROUGH;
	}
	else
		property_shorthand->type = type;

	shorthands[lower_case_name] = property_shorthand;
	return true;
}
示例#16
0
void Technique::RemovePass(const String& name)
{
    HashMap<String, unsigned>::ConstIterator i = passIndices.Find(name.ToLower());
    if (i == passIndices.End())
        return;
    else if (i->second_ < passes_.Size() && passes_[i->second_].Get())
    {
        passes_[i->second_].Reset();
        SetMemoryUse((unsigned)(sizeof(Technique) + GetNumPasses() * sizeof(Pass)));
    }
}
示例#17
0
   bool 
   TLD::IsTLD(const String &sName)
   {
      String sTmp = sName;

      sTmp.ToLower();

      if (tld_.find(sName) != tld_.end())
         return true;
      else
         return false;
   }
示例#18
0
void Image::FileType(const String& value)
{
	String s = value.ToLower().Trim();
	if (s == ImageFileTypes::bmp)
		fileType = s;
	else if (s == ImageFileTypes::gif)
		fileType = s;
	else if (s == ImageFileTypes::jpg)
		fileType = s;
	else if (s == ImageFileTypes::tga)
		fileType = s;
	else
		fileType = ImageFileTypes::png;
}
示例#19
0
文件: SquareRoom.cpp 项目: Nayrn/New
int SquareRoom::ProcessInput()
{
	Welcome();


	std::cout << "You have found a" << " " << Object.Cstr() << std::endl;
	std::cout << "Type in a keyword to open the " << " " << Object.Cstr() << std::endl;
	String uInput;
	uInput.ReadFromConsole();
	uInput.ToLower();
	while (true)
	{

		if (uInput.Equalto("open"))
		{
			std::cout << "You win" << std::endl;
			system("pause");
			break;
		}
		else
		{
			std::cout << "Wrong keyword, try again" << std::endl;
			system("pause");

			uInput.ReadFromConsole();
			uInput.ToLower();


		}
		

	}

	return 0;

}
示例#20
0
/**
*  @brief
*    Get shortcut of menu item (e.g. if text is "&Test" -> 'T' is the shortcut)
*/
char MenuItem::GetShortcut() const
{
	// Find '&' that marks a shortcut
	int nAmp = m_sText.IndexOf("&");
	if (nAmp >= 0) {
		// Get character after '&'
		String sChar = m_sText.GetSubstring(nAmp+1, 1);
		sChar.ToLower();

		// Return shortcut
		char nChar = sChar.GetASCII()[0];
		return nChar;
	}

	// No shortcut
	return '\0';
}
示例#21
0
int CheckChangedFiles(const char* filename,StrList& dst)
{
  String file=filename;
  file.ToLower();
  for(int i=0;i<files.Count();i++)
  {
    if(files[i]->filename==file && files[i]->indexFile.Length())
    {
      struct stat stf,sti;
      if(stat(file,&stf)==-1)return 0;
      if(stat(files[i]->indexFile,&sti)==-1)return 0;
      if(stf.st_mtime!=sti.st_mtime)return 0;
      CheckFiles(files[i],dst);
      return 1;
    }
  }
  return 0;
}
示例#22
0
Pass::Pass(const String& name) :
    blendMode_(BLEND_REPLACE),
    cullMode_(MAX_CULLMODES),
    depthTestMode_(CMP_LESSEQUAL),
    lightingMode_(LIGHTING_UNLIT),
    shadersLoadedFrameNumber_(0),
    depthWrite_(true),
    isDesktop_(false)
{
    name_ = name.ToLower();
    index_ = Technique::GetPassIndex(name_);

    // Guess default lighting mode from pass name
    if (index_ == Technique::basePassIndex || index_ == Technique::alphaPassIndex || index_ == Technique::materialPassIndex ||
        index_ == Technique::deferredPassIndex)
        lightingMode_ = LIGHTING_PERVERTEX;
    else if (index_ == Technique::lightPassIndex || index_ == Technique::litBasePassIndex || index_ == Technique::litAlphaPassIndex)
        lightingMode_ = LIGHTING_PERPIXEL;
}
bool GenericXMLParser::ParseAttribute(String &name, String &value)
{
	StartTrace(GenericXMLParser.ParseAttribute);
	name = ParseName();
	name.ToLower(); // XHTML conformance all attribute names are lower case
	Trace("attribute name:" << name);
	value = "";
	SkipWhitespace();
	int c = Peek();
	if (c != '=') {
		return false;
	}
	c = Get();
	(void)c;
	SkipWhitespace();
	value = ParseValue();
	return true;
	// otherwise it is a syntax error, we just ignore silently for now.
}
示例#24
0
void ApiClient::GetObjects(const String& pluralType, const ObjectsCompletionCallback& callback,
    const std::vector<String>& names, const std::vector<String>& attrs, const std::vector<String>& joins, bool all_joins) const
{
	Url::Ptr url = new Url();
	url->SetScheme("https");
	url->SetHost(m_Connection->GetHost());
	url->SetPort(m_Connection->GetPort());

	std::vector<String> path;
	path.push_back("v1");
	path.push_back("objects");
	path.push_back(pluralType);
	url->SetPath(path);

	std::map<String, std::vector<String> > params;

	for (const String& name : names) {
		params[pluralType.ToLower()].push_back(name);
	}

	for (const String& attr : attrs) {
		params["attrs"].push_back(attr);
	}

	for (const String& join : joins) {
		params["joins"].push_back(join);
	}

	params["all_joins"].push_back(all_joins ? "1" : "0");

	url->SetQuery(params);

	try {
		boost::shared_ptr<HttpRequest> req = m_Connection->NewRequest();
		req->RequestMethod = "GET";
		req->RequestUrl = url;
		req->AddHeader("Authorization", "Basic " + Base64::Encode(m_User + ":" + m_Password));
		req->AddHeader("Accept", "application/json");
		m_Connection->SubmitRequest(req, boost::bind(ObjectsHttpCompletionCallback, _1, _2, callback));
	} catch (const std::exception& ex) {
		callback(boost::current_exception(), std::vector<ApiObject::Ptr>());
	}
}
   bool 
   SQLScriptParser::PreprocessLine_(String &sLine)
   {
      // Do some basic preprocessing...
      while (sLine.Left(2).Compare(_T("\r\n")) == 0)
         sLine = sLine.Mid(2);
      
      while (sLine.Left(1).Compare(_T(" ")) == 0)
         sLine = sLine.Mid(1);
     
      while (sLine.Left(1).Compare(_T("\t")) == 0)
         sLine = sLine.Mid(1);


      String sTempLine = sLine;

      if (settings_->GetType() == HM::DatabaseSettings::TypeMSSQLCompactEdition)
      {
         if (sTempLine.ToLower().Left(3).Compare(_T("if ")) == 0)
         {
            return false;
         }
         else if (sLine.FindNoCase(_T(" CLUSTERED ")) >= 0)
         {
            sLine.ReplaceNoCase(_T(" CLUSTERED "), _T(" "));
         }
         else if (sLine.FindNoCase(_T("CREATE PROC")) >= 0)
         {
            // Procedures not supported by SQL CE
            return false;
         }

         sLine.Replace(_T("\t"), _T(" "));
         sLine.Replace(_T(" varchar"), _T(" nvarchar"));

      }

      if (sLine.IsEmpty())
         return false;


      return true;
   }
bool PlatformAddCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
{
    String argument = arguments[startIndex].ToLower();
    String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

    if (argument != "platform-add")
    {
        errorMsg = "Unable to parse build command";
        return false;
    }

    if (!value.Length())
    {
        errorMsg = "Unable to parse platform";
        return false;
    }

    platformToAdd_ = value.ToLower();

    return true;
}
示例#27
0
文件: RoundRoom.cpp 项目: Nayrn/New
int RoundRoom::ProcessInput()
{
	Welcome();
	findKey();
	String uInput;
	uInput.ReadFromConsole();
	uInput.ToLower();

	if (uInput.Equalto("back"))
	{
		std::cout << "Valid " << std::endl;
		return 0;
	}
	else
	{

		std::cout << "Dead end, try again" << std::endl;
		system("pause");
		return roomID;
	}
	return roomID;
}
示例#28
0
   bool 
   TLD::GetDomainNameFromHost(String &sHost, bool &bIsIPAddress)
   {
      bIsIPAddress = false;

      // Start at the end.
      std::vector<String> vecParts = StringParser::SplitString(sHost, ".");

      int iParts = vecParts.size();

      if (iParts < 2)
         return false;

      // Check if it's an IP address
      if (iParts == 4 && StringParser::IsValidIPAddress(sHost))
      {
         sHost = vecParts[3] + "." + vecParts[2] + "." + vecParts[1] + "." + vecParts[0];
         bIsIPAddress = true;
         return true;
      }

      // It's not an IP address.
      String sTwoLast = vecParts[iParts-2] + "." + vecParts[iParts-1];
      sTwoLast.ToLower();

      if (!IsTLD(sTwoLast))
         sHost = sTwoLast;
      else
      {
         if (iParts == 2)
            return false;

         sHost = vecParts[iParts-3] + "." + vecParts[iParts-2] + "." + vecParts[iParts-1];
      }

      return true;      
   }
示例#29
0
文件: File.cpp 项目: donbex/spkutils
int GetFileTypeFromString ( String type )
{
	String ltype = type.ToLower();
	if ( ltype == "script" )
		return FILETYPE_SCRIPT;
	else if ( ltype == "text" )
		return FILETYPE_TEXT;
	else if ( ltype == "readme" )
		return FILETYPE_README;
	else if ( ltype == "map" )
		return FILETYPE_MAP;
	else if ( ltype == "mod" )
		return FILETYPE_MOD;
	else if ( ltype == "uninstall" )
		return FILETYPE_UNINSTALL;
	else if ( ltype == "sound" )
		return FILETYPE_SOUND;
	else if ( ltype == "extra" )
		return FILETYPE_EXTRA;
	else if ( ltype == "screen" )
		return FILETYPE_SCREEN;
	else if ( ltype == "mission" )
		return FILETYPE_MISSION;
	else if ( ltype == "backup" )
		return FILETYPE_BACKUP;
	else if ( ltype == "shipother" )
		return FILETYPE_SHIPOTHER;
	else if ( ltype == "shipmodel" )
		return FILETYPE_SHIPMODEL;
	else if ( ltype == "shipscene" )
		return FILETYPE_SHIPSCENE;
	else if ( ltype == "cockpitscene" )
		return FILETYPE_COCKPITSCENE;

	return -1;
}
示例#30
0
void ConsoleInput::HandleInput(const String& input)
{
    String inputLower = input.ToLower().Trimmed();
    if (inputLower.Empty())
    {
        Print("Empty input given!");
        return;
    }

    if (inputLower == "quit" || inputLower == "exit")
        engine_->Exit();
    else if (gameOn_)
    {
        // Game is on
        if (inputLower == "help")
            Print("The following commands are available: 'eat', 'hide', 'wait', 'score', 'quit'.");
        else if (inputLower == "score")
            Print("You have survived " + String(numTurns_) + " turns.");
        else if (inputLower == "eat")
        {
            if (foodAvailable_)
            {
                Print("You eat several pieces of fish food.");
                foodAvailable_ = false;
                eatenLastTurn_ = true;
                hunger_ -= (hunger_ > 3) ? 2 : 1;
                if (hunger_ < 0)
                {
                    EndGame("You have killed yourself by over-eating!");
                    return;
                }
                else
                    Print("You are now " + hungerLevels[hunger_] + ".");
            }
            else
                Print("There is no food available.");

            Advance();
        }
        else if (inputLower == "wait")
        {
            Print("Time passes...");
            Advance();
        }
        else if (inputLower == "hide")
        {
            if (urhoThreat_ > 0)
            {
                bool evadeSuccess = hunger_ > 2 || Random() < 0.5f;
                if (evadeSuccess)
                {
                    Print("You hide behind the thick bottom vegetation, until Urho grows bored.");
                    urhoThreat_ = -2;
                }
                else
                    Print("Your movements are too slow; you are unable to hide from Urho.");
            }
            else
                Print("There is nothing to hide from.");

            Advance();
        }
        else
            Print("Cannot understand the input '" + input + "'.");
    }
    else
    {
        // Game is over, wait for (y)es or (n)o reply
        if (inputLower[0] == 'y')
            StartGame();
        else if (inputLower[0] == 'n')
            engine_->Exit();
        else
            Print("Please answer 'y' or 'n'.");
    }
}