Click here to Skip to main content
15,896,201 members
Articles / Desktop Programming / MFC

Auto-Task Tool for Web Game Travian

Rate me:
Please Sign up or sign in to vote.
4.84/5 (26 votes)
29 Oct 20075 min read 783.9K   7.1K   45  
Developing Auto-Task Tool for Web Game Travian
/*****************************************************************************
Module :     Travian.H
Notices:     2007.3.1 Written by Ling, Xiao-li.  Mailto: ling.xiaoli.s@gmail.com
Description: This file encapsulates html parsing relating to most tasks of travian web game,
			 such as upgrade task, build task, etc.
			 HTML getting or posting uses CHttpClient class.
			 HTML parsing uses CRegex which is a Wrapper for ATL regular string class CAtlRegExp<>.
			 
*****************************************************************************/
#pragma once
#include "stdafx.h"
#include "EventLog.h"
#include "HttpClient.h"
#include "Regex.h"
//extern System::EventLog::CEventLog g_TravianEvtLog;
//#define LOGERR(sErr) g_TravianEvtLog.AddEvt(EVENT_ERR, sErr)
//#define LOGWARNN(sWar) g_TravianEvtLog.AddEvt(EVENT_WARN, sWar)
//#define LOGINFO(sInf) g_TravianEvtLog.AddEvt(EVENT_INFOR, sInf)

using namespace std;
using namespace System::EventLog;
using namespace System::Internet;
using namespace System::String;

namespace Travian
{

// NOTE: character & maybe encoded as: &amp;
#define TRAVIAN_URL_TASK_CHECK					_T("build.php?id=%d")
#define TRAVIAN_URL_TASK_UPGRADE_RESOURCE		_T("dorf1.php?a=%d&c=")
#define TRAVIAN_URL_TASK_UPGRADE_BUILDING		_T("dorf2.php?a=%d&c=")
#define TRAVIAN_URL_TASK_BUILD					_T("dorf2.php?a=%d&id=%d&c=")	
#define TRAVIAN_URL_TASK_CHECK_VILLAGE			_T("dorf1.php")
#define TRAVIAN_URL_TASK_SWITCH_VILLAGE			_T("dorf1.php?newdid=%d")
#define TRAVIAN_URL_TASK_VILLAGEURL_MARK		_T("?newdid=")	//!!!
#define TRAVIAN_URL_TASK_DEVELOP				_T("build.php?id=%d&a=%d")
#define TRAVIAN_URL_TASK_CHECK_DISPATCH_TROOP	_T("a2b.php")

#define TRAVIAN_URL_LOGINPAGE					_T("login.php")
#define TRAVIAN_LOGIN_CONFIRMSTART				_T("dorf1.php?ok")

#define TRAVIAN_CAT_RESOURCE					1
#define TRAVIAN_CAT_BUILDING					2
#define TRAVIAN_CAT_MILITARY					3

// Wall/Rally location are fixed
#define TRAVIAN_LOC_MB							26
#define	TRAVIAN_LOC_RALLY						39
#define TRAVIAN_LOC_WALL						40
#define TRAVIAN_LOC_LOWLIMIT					1
#define TRAVIAN_LOC_UPLIMIT						40

#define TRAVIAN_LOC_RES_UPLIMIT					18	// resource location id up limit:
#define TRAVIAN_LOC_BLD_LOWLIMIT				19	// building location id starts from:

#define TRAVIAN_GROUP_LOWLIMIT					1
#define TRAVIAN_GROUP_UPLIMIT					37


#define TRAVIAN_TROOPTYPEID_LOWLIMIT			1
#define TRAVIAN_TROOPTYPEID_UPLIMIT				11
#define TRAVIAN_TRAP_ID							99	//!!!

#define DATETIME_PART_COUNT						6	// Date time format has 6 parts: Y-M-D H:M:S
#define TRAVIAN_COMMAND_LEN						3	// Travian backend program automatically generates extra parameter (here called command) 
													// in uprade or build task's links. And the command length is 3 chars at present.
struct RESOURCE
{
	vector<long> vecRes;
	RESOURCE() {
		vecRes.resize(4);
		vecRes.at(0) = 0;	// Wood
		vecRes.at(1) = 0;	// Clay
		vecRes.at(2) = 0;	// Iron
		vecRes.at(3) = 0;	// Grain
	};
	RESOURCE(const RESOURCE& rhs)
	{
		vecRes = rhs.vecRes;
	};
	RESOURCE& operator = (const RESOURCE& rhs) {
		vecRes = rhs.vecRes;
		return *this;
	}

};

struct TROOP
{
	int		nTypeID;							// Troop Type ID
	int		nQty;								// Quantity
	TROOP() {
		nTypeID = -1;
		nQty = 0;
	};
	TROOP(const TROOP& rhs) {
		nTypeID = rhs.nTypeID;
		nQty = rhs.nQty;
	};
	TROOP& operator = (const TROOP& rhs) {
		nTypeID = rhs.nTypeID;
		nQty = rhs.nQty;
		return *this;
	}
};


// Village coordinate
struct VILLAGE
{
	// Just fill nX,nY, or just fill sName.
	int		nX;
	int		nY;
	CString sName;
	VILLAGE() {
		nX = 0; nY = 0;
	};
	VILLAGE(const VILLAGE& rhs) {
		nX = rhs.nX; nY = rhs.nY;
		sName = rhs.sName;
	};
	VILLAGE& operator = (const VILLAGE& rhs) {
		nX = rhs.nX; nY = rhs.nY;
		sName = rhs.sName;
		return *this;
	}
};

enum eTaskExecState
{
	  E_EXEC_STATE_INITIAL	= -1
	, E_EXEC_STATE_FINISHED	= 0
	, E_EXEC_STATE_DELAYED	= 1	// this task will delay to execute because of current condition not satisfied, but condition will change in future.
	, E_EXEC_STATE_STOPPED	= 2	// this task cancelled because of beyond condition, such as trainning troop that has not been developed, and resource tranfer failed.
};

enum eTroopDispatchType
{
	  E_TROOPDISPATCH_NONE			= -1
	, E_TROOPDISPATCH_REINFORCE		= 2
	, E_TROOPDISPATCH_ATTACK_NORMAL	= 3
	, E_TROOPDISPATCH_ATTACK_RAID	= 4
};

class CTravianTask;
typedef vector< pair<int, CTravianTask*> > Tasks;
class CTravianTask: public CEventWrapper
{
public:
	eTaskExecState		m_eExecState;		// task execution state
	int					m_nVillageIndex;	// The order number indexed by village creation date for one player, starting from 1. 
	int					m_nLoc;				// Represent target location. In build task, used as "id" parameter, but in upgrade task, used as "a" parameter.
	COleDateTime		m_dtFire;
	bool				m_bCanParallelExec;	// whether this task can executed parallel with other tasks.
protected:
	long				m_nVillageID;		// Village ID. -1 indicates the current player has only one village, so don't need to store village id.
	bool				m_bFormPost;		// This task needs to post form data
	bool				m_bFormConfirmPost; // This task needs to post form data, and also needs post confirm form data.
	CString				m_sTaskDescStr;		// task description string
protected:
	static map<CString, vector<long> >	m_mapVillageIDs;	// map key is the combination of server name and user name, while value is the village IDs vector for that combination. Here don't need to adopt synchronization mechanism, but user should only user one thread to execute one server/user tasks.

public:
	CTravianTask(CEventLog* pEvtLog) 
		: m_eExecState(E_EXEC_STATE_INITIAL)
		, m_bFormPost(false)
		, m_bFormConfirmPost(false)
		, m_bCanParallelExec (false) {
		m_pEvtLog = pEvtLog;
		m_nVillageIndex = 1;
		m_nVillageID = 0;
		m_nLoc = -1;
	};
	CTravianTask(const CTravianTask& rhs) {
		m_eExecState = rhs.m_eExecState;
		m_bFormPost = rhs.m_bFormPost;
		m_bFormConfirmPost = rhs.m_bFormConfirmPost;
		m_bCanParallelExec = rhs.m_bCanParallelExec;
		m_pEvtLog = rhs.m_pEvtLog;
		m_nVillageIndex = rhs.m_nVillageIndex;
		m_nVillageID = rhs.m_nVillageID;
		m_nLoc = rhs.m_nLoc;
		m_dtFire = rhs.m_dtFire;
	};
	virtual ~CTravianTask() {};

public:
	static bool GetFormAction(CString& sHTML, CString& sFormActionURL, CEventLog& EvtLog);	// Get form action URL (the fist one form). 
	// NOTE: Form elements tags: 
	//	<input ... 
	//	<select ... 
	//	<textarea ...
	// Get the given input field name/value pairs vector.
	static bool GetFormInputFields(CString& sHTML, vector< pair<CString, CString> > & vecNameVal, map<CString, CString>& mapNameVal, CEventLog& EvtLog);
	static bool GetFormInputFieldByIdx(vector< pair<CString, CString> > & vecNameVal, int nIndex, CString& sName, CString& sVal, CEventLog& EvtLog);
	static bool GetFormInputFieldByIdx(CString& sHTML, int nIndex, CString& sName, CString& sVal, CEventLog& EvtLog);
	static bool GetFormInputFieldByName(map<CString, CString>& mapNameVal, LPCTSTR lpszName, CString& sVal, CEventLog& EvtLog);
	static bool GetFormInputFieldByName(CString& sHTML, LPCTSTR lpszName, CString& sVal, CEventLog& EvtLog);

	static CString			GetURLLoginPage()			{ return CString(TRAVIAN_URL_LOGINPAGE);};
	static CString			GetURLLoginConfirmStart()	{ return CString(TRAVIAN_LOGIN_CONFIRMSTART);};
	static bool				IsNeedLogin(CString& sHTML);
	static bool				GetLoginPostData(LPCTSTR lpszUName, LPCTSTR lpszUPwd, CString& sHTML, CStringA& sPostData, CString& sPostURL, CEventLog& EvtLog);
	static bool				GetTasks(LPCTSTR lpszTaskFile, Tasks& ts, CEventLog& EvtLog);
	static void				ClearTasks(Tasks& ts) { for(int i=0; i<ts.size(); i++) delete ts.at(i).second; ts.clear();};
	static Tasks			CloneTasks(const Tasks& ts) { Tasks ts_new; for(int i=0; i<ts.size(); i++) ts_new.push_back( make_pair(i, ts.at(i).second->Clone()) ); return ts_new;};

public:
	bool					GetVillageIDs(CHttpClient& http, LPCTSTR lpszSvr, LPCTSTR lpszUser, LPCTSTR lpszPwd);
	inline bool				GetVillageSwitchURL(CHttpClient& http, LPCTSTR lpszSvr, LPCTSTR lpszUser, LPCTSTR lpszPwd, CString& sRetURL); // if not needed to switch village, then return true and sRetURL empty. If encounter error, return false;
	inline bool				Login(CString& sRefererHTML, CHttpClient& http, LPCTSTR lpszSvr, LPCTSTR lpszUser, LPCTSTR lpszPwd);
	eTaskExecState			ExecTask(CHttpClient& http, LPCTSTR lpszSvr, LPCTSTR lpszUser, LPCTSTR lpszPwd, bool bRecursive=false);

public:
	virtual CTravianTask*	Clone() { return new CTravianTask(*this); };
	virtual CString			GetTaskRefererURL();	
	virtual bool			GetTaskURL(CString& sHTML, CString& sRetPatURL, bool& bStopTask);	// Return true: found the task upgrade url; false: not found task upgrade url.
	virtual bool			GetFormPostData(CString& sHTML, CStringA& sRetPostData, bool& bStopTask, bool bConfirmForm=false) {  bStopTask = false; return true;};
	virtual const CString&	GetTaskStr();
};

// Build new building
class CTravianTaskBuild: public CTravianTask
{
public:
	int				m_nGroup;			// Represent target group. Only needed in building task.
										// To resource, the group parameter not needed, and only location can identify itself.
public:
	CTravianTaskBuild(CEventLog* pEvtLog): CTravianTask(pEvtLog) {
		m_nGroup = -1;
	};
	CTravianTaskBuild(CTravianTaskBuild& rhs):CTravianTask(rhs)  {
		m_nGroup = rhs.m_nGroup;
	};
public:	
	virtual CTravianTaskBuild*	Clone() { return new CTravianTaskBuild(*this); };
	virtual bool				GetTaskURL(CString& sHTML, CString& sRetPatURL, bool& bStopTask);	// Return true: found the task building url; false: not found task build url.
	virtual const CString&		GetTaskStr();
};

// Development applies to: Academy, Armoury, Blacksmith
class CTravianTaskDevelop: public CTravianTask
{
public:
	int						m_nTroopType;
public:
	CTravianTaskDevelop(CEventLog* pEvtLog): CTravianTask(pEvtLog) {
		m_nTroopType = -1;
		m_bCanParallelExec = true;
	};
	CTravianTaskDevelop(CTravianTaskDevelop& rhs):CTravianTask(rhs)  {
		m_nTroopType = rhs.m_nTroopType;
	};
public:
	virtual CTravianTaskDevelop*	Clone() { return new CTravianTaskDevelop(*this); };
	virtual bool					GetTaskURL(CString& sHTML, CString& sRetPatURL, bool& bStopTask);
	virtual const CString&			GetTaskStr();
};

// Training applies to: Barracks, Stable, Workshop. Need to post form data.
class CTravianTaskTrain: public CTravianTask
{
public:
	vector<TROOP>			m_vecTroops;	// Includes all troops event that some troops have quantity 0.
public:
	CTravianTaskTrain(CEventLog* pEvtLog): CTravianTask(pEvtLog) {
		m_bFormPost = true;
		m_bCanParallelExec = true;
	};
	CTravianTaskTrain(CTravianTaskTrain& rhs):CTravianTask(rhs) {
		m_vecTroops = rhs.m_vecTroops;
	};
public:
	virtual CTravianTaskTrain*	Clone() { return new CTravianTaskTrain(*this); };
	virtual bool				GetFormPostData(CString& sHTML, CStringA& sRetPostData, bool& bStopTask, bool bConfirmForm=false);
	virtual const CString&		GetTaskStr();
};

// Transporting resource applies to Marketplace. Need to post form data.
class CTravianTaskResourceTransport: public CTravianTask
{
public:
	RESOURCE				m_res;
	VILLAGE					m_DestVillage;
public:
	CTravianTaskResourceTransport(CEventLog* pEvtLog): CTravianTask(pEvtLog) {
		m_bFormPost = true;
		m_bFormConfirmPost = true;
		m_DestVillage.nX = 0;
		m_DestVillage.nY = 0;
		m_bCanParallelExec = true;
	};
	CTravianTaskResourceTransport(CTravianTaskResourceTransport& rhs):CTravianTask(rhs) {
		m_res = rhs.m_res;
		m_DestVillage = rhs.m_DestVillage;
	};
public:
	virtual CTravianTaskResourceTransport*	Clone() { return new CTravianTaskResourceTransport(*this); };
	virtual bool							GetFormPostData(CString& sHTML, CStringA& sRetPostData, bool& bStopTask, bool bConfirmForm=false);
	virtual const CString&					GetTaskStr();
};

// Dispatch troop applies to rally. Need to post form data.
class CTravianTaskDispatchTroop: public CTravianTask
{
public:
	vector<TROOP>			m_vecTroops;
	VILLAGE					m_DestVillage;
	eTroopDispatchType		m_eDispatchType;
public:
	CTravianTaskDispatchTroop(CEventLog* pEvtLog): CTravianTask(pEvtLog) {
		m_bFormPost = true;
		m_bFormConfirmPost = true;
		m_DestVillage.nX = 0;
		m_DestVillage.nY = 0;
		m_eDispatchType = E_TROOPDISPATCH_NONE;
		m_bCanParallelExec = true;

		for(int i=0, nTroopTyeId = TRAVIAN_TROOPTYPEID_LOWLIMIT; nTroopTyeId<= TRAVIAN_TROOPTYPEID_UPLIMIT; i++, nTroopTyeId++)
		{
			TROOP troop;
			troop.nTypeID = nTroopTyeId;
			m_vecTroops.push_back(troop); 
		}
	};
	CTravianTaskDispatchTroop(CTravianTaskDispatchTroop& rhs):CTravianTask(rhs) {
		m_vecTroops = rhs.m_vecTroops;
		m_DestVillage = rhs.m_DestVillage;
		m_eDispatchType = rhs.m_eDispatchType;
	};
public:
	virtual CTravianTaskDispatchTroop*	Clone() { return new CTravianTaskDispatchTroop(*this); };
	virtual CString						GetTaskRefererURL();
	virtual bool						GetFormPostData(CString& sHTML, CStringA& sRetPostData, bool& bStopTask, bool bConfirmForm=false);
	virtual const CString&				GetTaskStr();
};

};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions