예제 #1
0
		public void Action()
		{
			var CV = UpCall.TD.Villages[VillageID];
			UpCall.PageQuery(VillageID, "build.php?gid=24&a=" + ((int)PartyType).ToString());
			LastExec = DateTime.Now;
			if(CV.InBuilding[5] == null || CV.InBuilding[5].FinishTime < DateTime.Now)
			{
				// error occurred!
				retrycount++;
				if(retrycount > 10)
				{
					UpCall.DebugLog("Error on party for several times! Delete the queue!", DebugLevel.W);
					MarkDeleted = true;
				}
				else
				{
					UpCall.DebugLog("Error on party! Will retry...", DebugLevel.I);
					NextExec = DateTime.Now.AddSeconds(rand.Next(500 + retrycount * 20, 800 + retrycount * 30));
				}
				UpCall.Dirty = true;
			}
			else
			{
				UpCall.BuildCount();
				retrycount = 0;
			}
		}
예제 #2
0
        public void Action()
        {
            var CV = UpCall.TD.Villages[VillageID];

            if (NextExec >= DateTime.Now)
            {
                return;
            }
            NextExec = DateTime.Now.AddSeconds(rand.Next(150, 300));
            Dictionary <string, string> Postdata = new Dictionary <string, string>()
            {
                { "gid", "15" },
                { "a", VillageID.ToString() },
                { "abriss", Bid.ToString() },
                { "ok", "%E6%8B%86%E6%AF%81" }
            };

            UpCall.PageQuery(VillageID, "build.php", Postdata);

            int lvl = CV.InBuilding[2] != null && CV.InBuilding[2].FinishTime > DateTime.Now ? CV.InBuilding[2].Level : -1;

            if (lvl < 0)
            {
                UpCall.DebugLog("Unknown state: Destroy to -1", DebugLevel.W);
            }
            if (lvl <= 0)
            {
                MarkDeleted  = true;
                UpCall.Dirty = true;
                UpCall.CallStatusUpdate(this, new Travian.StatusChanged()
                {
                    ChangedData = Travian.ChangedType.Queue,
                    VillageID   = VillageID
                });
            }
            UpCall.BuildCount();
        }
예제 #3
0
        public void Action()
        {
            var    CV = UpCall.TD.Villages[VillageID];
            int    GID;
            var    Q = this;
            string mat_str, id, c;
            Match  m;
            string result;

            switch (ResearchType)
            {
            case TResearchType.Research:
                if (!CV.Upgrades[Aid].CanResearch)
                {
                    MarkDeleted  = true;
                    UpCall.Dirty = true;
                    UpCall.CallStatusUpdate(this, new Travian.StatusChanged()
                    {
                        ChangedData = Travian.ChangedType.Queue, VillageID = VillageID
                    });
                    return;
                }
                GID    = 22;
                result = UpCall.PageQuery(VillageID, "build.php?gid=" + GID.ToString());
                if (result == null)
                {
                    return;
                }
                mat_str = "'build.php\\?id=(\\d+)&amp;a=" + Aid.ToString() + "&amp;c=([^']*?)'";
                m       = Regex.Match(result, mat_str);
                if (!m.Success)
                {
                    return;
                }
                id     = m.Groups[1].Value;
                c      = m.Groups[2].Value;
                result = UpCall.PageQuery(VillageID, "build.php?id=" + id + "&a=" + Aid.ToString() + "&c=" + c);
                break;

            case TResearchType.UpTroopLevel:
                if (TargetLevel != 0 && CV.Upgrades[Aid].troop_lvl >= TargetLevel || CV.Upgrades[Aid].troop_lvl >= CV.SmithyLevel)
                {
                    MarkDeleted  = true;
                    UpCall.Dirty = true;
                    UpCall.CallStatusUpdate(this, new Travian.StatusChanged()
                    {
                        ChangedData = Travian.ChangedType.Queue, VillageID = VillageID
                    });
                    return;
                }
                GID    = 13;
                result = UpCall.PageQuery(VillageID, "build.php?gid=" + GID.ToString());
                if (result == null)
                {
                    return;
                }
                mat_str = "'build.php\\?id=(\\d+)&amp;a=" + Aid.ToString() + "&amp;c=([^']*?)'";
                m       = Regex.Match(result, mat_str, RegexOptions.Singleline);
                if (!m.Success)
                {
                    return;
                }
                id     = m.Groups[1].Value;
                c      = m.Groups[2].Value;
                result = UpCall.PageQuery(VillageID, "build.php?id=" + id + "&a=" + Aid.ToString() + "&c=" + c);
                break;

            default:
                return;
            }
            UpCall.BuildCount();

            if (TargetLevel == 0 || ResearchType == TResearchType.Research)
            {
                MarkDeleted  = true;
                UpCall.Dirty = true;
                UpCall.CallStatusUpdate(this, new Travian.StatusChanged()
                {
                    ChangedData = Travian.ChangedType.Queue, VillageID = VillageID
                });
            }
            else if (ResearchType == TResearchType.UpTroopLevel)
            {
                if (CV.Upgrades[Aid].troop_lvl >= TargetLevel || CV.Upgrades[Aid].troop_lvl >= CV.SmithyLevel)
                {
                    MarkDeleted  = true;
                    UpCall.Dirty = true;
                    UpCall.CallStatusUpdate(this, new Travian.StatusChanged()
                    {
                        ChangedData = Travian.ChangedType.Queue, VillageID = VillageID
                    });
                }
            }

            UpCall.CallStatusUpdate(this, new Travian.StatusChanged()
            {
                ChangedData = Travian.ChangedType.Research, VillageID = VillageID
            });
        }
예제 #4
0
        /// <summary>
        /// Trade resource with NPC with 1:1 rate (after paying 3 gold)
        /// </summary>
        public NpcTradeResult doNpcTrade()
        {
            // Get NPC trade form
            string result = UpCall.PageQuery(VillageID, "build.php?gid=17&t=3");

            if (result == null)
            {
                return(NpcTradeResult.Failure);
            }

            // Parse capacity and sum
            Match match = Regex.Match(result, "var summe=(?<summe>\\d+);var max123=(?<max123>\\d+);var max4=(?<max4>\\d+);");

            if (!match.Success)
            {
                return(NpcTradeResult.Failure);
            }

            int sum = Int32.Parse(match.Groups["summe"].Value);

            // Parse id
            match = Regex.Match(result, "<input type=\"hidden\" name=\"id\" value=\"(?<id>\\d+)\"");
            if (!match.Success)
            {
                return(NpcTradeResult.Failure);
            }

            string id = match.Groups["id"].Value;

            // Parse c
            match = Regex.Match(result, "<input type=\"hidden\" name=\"c\" value=\"(?<c>[^>]*?)\"");
            if (!match.Success)
            {
                return(NpcTradeResult.Failure);
            }

            string c = match.Groups["c"].Value;

            // Parse m1[] and m2[]
            MatchCollection matches = Regex.Matches(result, "<input type=\"hidden\" name=\"m1\\[\\]\" value=\"(?<m1>\\d+)\"");

            if (matches.Count != 4)
            {
                return(NpcTradeResult.Failure);
            }

            TResAmount m1 = new TResAmount(new int[matches.Count]);

            for (int i = 0; i < matches.Count; i++)
            {
                m1.Resources[i] = Int32.Parse(matches[i].Groups["m1"].Value);
            }

            // Does m1 exceeds threshold?
            for (int i = 0; i < m1.Resources.Length; i++)
            {
                if (m1.Resources[i] < Threshold.Resources[i])
                {
                    return(NpcTradeResult.Delay);
                }
            }

            // Compute m2
            TResAmount m2 = RedistributeResources(UpCall.TD, VillageID, sum);

            if (m2 == null)
            {
                return(NpcTradeResult.Delay);
            }

            // Prepare data
            Dictionary <string, string> postData = new Dictionary <string, string>();

            postData["id"] = id;
            postData["t"]  = "3";
            postData["a"]  = "6";
            postData["c"]  = c;

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < m2.Resources.Length; i++)
            {
                if (i > 0)
                {
                    sb.Append("&");
                }

                sb.AppendFormat("m2[]={0}&m1[]={1}", m2.Resources[i], m1.Resources[i]);
            }

            postData["!!!RawData!!!"] = sb.ToString();

            // Post form
            result = UpCall.PageQuery(VillageID, "build.php", postData);
            if (result == null)
            {
                return(NpcTradeResult.Failure);
            }

            match = Regex.Match(result, "<b>3</b>[^<]*?</p><script language=\"JavaScript\">var summe=");
            if (!match.Success)
            {
                return(NpcTradeResult.Failure);
            }

            UpCall.DebugLog(string.Format("NPC trade {0} -> {1} ({2}) ", m1, m2, VillageID), DebugLevel.I);
            UpCall.BuildCount();
            return(NpcTradeResult.Success);
        }
예제 #5
0
        /// <summary>
        /// Dispatch a transportation of a given amount of resource from one village to a given destiantion
        /// </summary>
        /// <param name="VillageID">Unique ID of the departure village</param>
        /// <param name="Amount">Amounts of resources to transport</param>
        /// <param name="TargetPos">Position of the arrival village</param>
        /// <returns>Error return minus number. Succeed return single way transfer time cost.</returns>
        public int doTransfer(TResAmount Amount, TPoint TargetPos)
        {
            string result = UpCall.PageQuery(VillageID, "build.php?gid=17&t=5");

            if (result == null)
            {
                return(-1);
            }
            var CV = UpCall.TD.Villages[VillageID];
            Dictionary <string, string> PostData = new Dictionary <string, string>();
            var m = Regex.Match(result, "name=\"id\" id=\"id\" value=\"(\\d+)\"", RegexOptions.Singleline);

            if (!m.Success)
            {
                return(-1);
            }
            PostData["cmd"] = "prepareMarketplace";
            PostData["id"]  = m.Groups[1].Value;

            if (result.Contains("Popup(2,5)") && Amount.TotalAmount > CV.Market.SingleCarry * CV.Market.ActiveMerchant)
            {
                resumeTime = DateTime.Now.AddSeconds(rand.Next(200 + retrycount * 20, 300 + retrycount * 30));
                UpCall.DebugLog("0:00:0?, Will retry...", DebugLevel.I);
                return(-2);
            }
            if (Amount.TotalAmount > CV.Market.SingleCarry * CV.Market.ActiveMerchant)
            {
                retrycount++;
                if (retrycount > 5)
                {
                    UpCall.DebugLog(string.Format("Transfer cannot go on: MCarry({0}) * MCount({1}) < Amount({2})", CV.Market.SingleCarry, CV.Market.ActiveMerchant, Amount.TotalAmount), DebugLevel.W);
                    return(-2);                    // Beyond transfer ability
                }
                else
                {
                    UpCall.DebugLog("Error on 'ActiveMerchant'! Will retry...", DebugLevel.I);
                    resumeTime = DateTime.Now.AddSeconds(rand.Next(500 + retrycount * 20, 800 + retrycount * 30));
                    CV.Market.ActiveMerchant = Math.Min(Amount.TotalAmount / CV.Market.SingleCarry + 1, CV.Market.MaxMerchant);
                    return(-2);
                }
            }
            retrycount = 0;
            for (int i = 0; i < 4; i++)
            {
                PostData["r" + (i + 1).ToString()] = Amount.Resources[i].ToString();
            }

            //cmd=prepareMarketplace&r1=3000&r2=3000&r3=3000&r4=&dname=&x=50&y=105&id=27&t=5&x2=1
            PostData["dname"] = "";
            PostData["x"]     = TargetPos.X.ToString();
            PostData["y"]     = TargetPos.Y.ToString();
            PostData["t"]     = "5";
            PostData["x2"]    = "1";

            result = UpCall.PageQuery(VillageID, "ajax.php?cmd=prepareMarketplace", PostData);

            //cmd=prepareMarketplace&t=5&id=27&a=64846&sz=2788&kid=236746&c=aaa02a&x2=1&r1=3000&r2=3000&r3=3000&r4=
            if (result == null)
            {
                return(-1);
            }
            PostData.Clear();
            result          = result.Replace("\\\"", "\"");
            result          = result.Replace("\\/", "/");
            PostData["cmd"] = "prepareMarketplace";
            MatchCollection matches = Regex.Matches(result, "name=\"(\\w+)\" id=\"\\w+\" value=\"(\\w+)\"");

            for (int i = 0; i < matches.Count; i++)
            {
                PostData[matches[i].Groups[1].Value] = matches[i].Groups[2].Value;
            }
            for (int i = 0; i < 4; i++)
            {
                PostData["r" + (i + 1).ToString()] = Amount.Resources[i].ToString();
            }
            m = Regex.Match(result, "<td>([0-9:]{6,})</td>");
            if (!m.Success)
            {
                return(-1);                // Parse error!
            }
            int TimeCost = Convert.ToInt32(UpCall.TimeSpanParse(m.Groups[1].Value).TotalSeconds);

            if (UpCall.TD.MarketSpeed != 0)
            {
                // calc market speed
                var distance = CV.Coord * TargetPos;
                UpCall.TD.Dirty       = true;
                UpCall.TD.MarketSpeed = Convert.ToInt32(Math.Round(distance * 3600 / TimeCost));
            }

            UpCall.PageQuery(VillageID, "ajax.php?cmd=prepareMarketplace", PostData);
            UpCall.BuildCount();

            // write data into target village if it's my village.
            foreach (var x in UpCall.TD.Villages)
            {
                if (x.Value == CV)
                {
                    continue;
                }
                if (x.Value.Coord == TargetPos)
                {
                    if (x.Value.isBuildingInitialized == 2)
                    {
                        x.Value.Market.MarketInfo.Add(new TMInfo()
                        {
                            CarryAmount = Amount.Clone(),
                            Coord       = CV.Coord,
                            FinishTime  = DateTime.Now.AddSeconds(TimeCost),
                            MType       = TMType.OtherCome,
                            VillageName = CV.Name
                        });
                    }
                    break;
                }
            }
            UpCall.DebugLog(string.Format("Transfer {0}({1}) => {2} {3}", CV.Coord.ToString(), VillageID, TargetPos.ToString(),
                                          Amount.ToString()), DebugLevel.I);
            return(TimeCost);
        }
예제 #6
0
		public void Action()
		{
			BuildingQueue Q = this;
			var CV = UpCall.TD.Villages[VillageID];

			if(Q.NextExec >= DateTime.Now)
				return;
			Q.NextExec = DateTime.Now.AddSeconds(60);
			
			int Bid = UpCall.testPossibleNow(VillageID, Q);
			//	-1表示目前无法建造
			if(Bid == -1)
			{
				Q.MarkDeleted = true;
				UpCall.DebugLog("Delete Queue [" + Q.Title + "] because it's impossible to build it.", DebugLevel.W);
				return;
			}
			//	0表示建造该建筑先要造某种别的建筑
			if(Bid != 0)
			{
				UpCall.DebugLog("Queue [" + Q.Title + "] needs Bid=" + Bid.ToString() + " to be extended.", DebugLevel.I);
				Q = new BuildingQueue() { UpCall = UpCall, Bid = Bid, Gid = CV.Buildings[Bid].Gid };
				UpCall.DebugLog("Create Queue [" + Q.Title + "] because it needs to be extended.", DebugLevel.I);
			}

			int bid = Q.Bid;
			int gid = Q.Gid;
			string result;
			result = UpCall.PageQuery(VillageID, "dorf1.php");
			if(result == null)
				return;
			List<int> nMilitaries = new List<int> {13, 14, 19, 20, 21, 22, 29, 30, 31, 32, 33, 36, 37};
			List<int> nResources = new List<int> {5, 6, 7, 8, 9};
			string url = "build.php?id=" + bid.ToString();
			if (nMilitaries.Contains(gid))
			{
				url += "&category=2";
			}
			else if (nResources.Contains(gid))
			{
				url += "&category=3";
			}
			else if (gid == 17)
			{
				url += "&t=0";
			}
			result = UpCall.PageQuery(VillageID, url);
			if(result == null)
				return;
			
			//	m用来解析新建建筑,n用来解析建筑升级
			Match m, n;
			m = Regex.Match(result, "(dorf(\\d)\\.php\\?a=" + gid + "&amp;id=" + bid + "&amp;c=[^\']*?)';\\sreturn");
			n = Regex.Match(result, "(dorf(\\d)\\.php\\?a=" + bid + "&amp;c=[^\']*?)';\\sreturn");
			if(!m.Success && !n.Success)
			{
				// check reason
				/*
				 * <span class="c">已经有建筑在建造中</span>
				 * <div class="c">资源不足</div>
				 * <p class="c">伐木场建造完成</p>
				 * <span class="c">建造所需资源超过仓库容量上限,请先升级你的仓库</span>
				 * <span class="c">粮食产量不足: 需要先建造一个农场</span>
				 * 
				 */
				int RomaNeedCrop = -1;
				//	仓库容量不足的话,先造仓库
				if(gid != 10 && UpCall.GidLang.ContainsKey(10) && Regex.Match(result, "<span class=\"(c|none)\">[^<]*?" + UpCall.GetGidLang(10) + "[^<]*?</span>", RegexOptions.IgnoreCase).Success)
				{
					gid = 10;
					bid = findBuilding(VillageID, gid);
				}
				//	粮食产量不足的话,先造农场
                else if (gid != 11 && UpCall.GidLang.ContainsKey(11) && Regex.Match(result, "<span class=\"(c|none)\">[^<]*?" + UpCall.GetGidLang(11) + "[^<]*?</span>", RegexOptions.IgnoreCase).Success)
				{
					gid = 11;
					bid = findBuilding(VillageID, gid);
				}
                else if (gid != 4 && UpCall.GidLang.ContainsKey(4) && Regex.Match(result, "<span class=\"(c|none)\">[^<]*?" + UpCall.GetGidLang(4) + "[^<]*?</span>", RegexOptions.IgnoreCase).Success)
				{
                	if (UpCall.TD.isRomans && CV.InBuilding[0] != null && Q.Bid > 18)
                	{
                		if (CV.InBuilding[0].Gid != 4)
                			RomaNeedCrop = 1;
                		else if (CV.InBuilding[0].Gid == 4)
                		{
                			RomaNeedCrop = 0;
                			return;
                		}
                		UpCall.DebugLog("Roma NEED Crop rule", DebugLevel.W);
                		Q.NextExec = CV.InBuilding[0].FinishTime.AddSeconds(30);
                	}
                	gid = 4;
                	bid = findBuilding(VillageID, gid);
				}
                else if (result.Contains("<p class=\"(c|none)\">"))
				{
					UpCall.DebugLog("Unexpected status! Report it on the forum! " + Q.Title, DebugLevel.W);
					Q.MarkDeleted = true;
					UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID });
					return;
				}
                else if (UpCall.GidLang.ContainsKey(gid) && Regex.Match(result, "<span class=\"(c|none)\">[^<]*?" + UpCall.GetGidLang(gid) + "[^<]*?</span>", RegexOptions.IgnoreCase).Success)
					return;
                else if (result.Contains("<span class=\"(c|none)\">"))
				{
					//Q.Delay = rand.Next(500, 1000);
					// Delay shouldn't happen.
					Q.NextExec = DateTime.Now.AddSeconds(rand.Next(150, 300));
					UpCall.DebugLog("Data not refreshed? Add delay for " + Q.Title, DebugLevel.I);
					return;
				}
				else
				{
					UpCall.PageQuery(VillageID, "dorf1.php");
					UpCall.PageQuery(VillageID, "dorf2.php");
					UpCall.DebugLog("Unknown status! And cause a queue been deleted! " + Q.Title, DebugLevel.W);
					//Q.MarkDeleted = true;
					//UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID });
					Q.NextExec = DateTime.Now.AddSeconds(rand.Next(150, 300));
					return;
				}
				
				// 检查资源是否足够
				int timecost;
				if(CV.Buildings.ContainsKey(bid))
					timecost = CV.TimeCost(Buildings.Cost(gid, CV.Buildings[bid].Level + 1));
				else
					timecost = CV.TimeCost(Buildings.Cost(gid, 1));
				if(CV.InBuilding[UpCall.TD.isRomans && bid > 18 ? 1 : 0] != null)
					timecost = Math.Max(timecost, Convert.ToInt32(DateTime.Now.Subtract(CV.InBuilding[UpCall.TD.isRomans && bid > 18 ? 1 : 0].FinishTime).TotalSeconds));
				if(timecost > 0 || RomaNeedCrop == 1)
				{
					UpCall.DebugLog("Need to build but resource not enough so add into queue: " + Q.Title, DebugLevel.I);
					CV.Queue.Insert(0, new BuildingQueue()
					{
						UpCall = UpCall,
						VillageID = VillageID,
						Bid = bid,
						Gid = gid
					});
					UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID });

					return;
				}
				result = UpCall.PageQuery(VillageID, "build.php?id=" + bid.ToString());
				if(result == null)
					return;
				m = Regex.Match(result, "(dorf(\\d)\\.php\\?a=" + gid + "&amp;id=" + bid + "&c=[^\']*?)'");
				n = Regex.Match(result, "(dorf(\\d)\\.php\\?a=" + bid + "&amp;c=[^\']*?)'");
				if(!m.Success && !n.Success)
				{
					UpCall.DebugLog("Unknown error on building " + Q.Title, DebugLevel.E);
					Q.MarkDeleted = true;
					UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID });
					return;
				}
			}

			// New building
			int qtype = bid < 19 && bid > 0 ? 0 : 1;

			if(CV.Buildings.ContainsKey(bid))
				CV.RB[UpCall.TD.isRomans ? qtype : 0] = new TInBuilding() { ABid = bid, Gid = gid, Level = CV.Buildings[bid].Level };
			else
				CV.RB[UpCall.TD.isRomans ? qtype : 0] = new TInBuilding() { ABid = bid, Gid = gid, Level = 1 };
			
			//	执行建造操作
			string uri;
			if(m.Success)
			{
				uri = m.Groups[1].Value.Replace("amp;", "");
				UpCall.PageQuery(VillageID, uri);
			}
			else
			{
				uri = n.Groups[1].Value.Replace("amp;", "");
				UpCall.PageQuery(VillageID, uri);
			}
			UpCall.BuildCount();

			if(Q.Bid == bid)
				UpCall.DebugLog("Build " + Q.Title, DebugLevel.I);
			else
				UpCall.DebugLog("Build (other) " + Q.Title, DebugLevel.I);
			
			if(Q.Bid == bid)
			{
				if(Q.TargetLevel == 0 || Q.TargetLevel <= CV.Buildings[bid].Level)
				{
					Q.MarkDeleted = true;
					UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID });
				}
			}
			UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Buildings, VillageID = VillageID });
		}