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; } }
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(); }
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+)&a=" + Aid.ToString() + "&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+)&a=" + Aid.ToString() + "&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 }); }
/// <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); }
/// <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); }
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 + "&id=" + bid + "&c=[^\']*?)';\\sreturn"); n = Regex.Match(result, "(dorf(\\d)\\.php\\?a=" + bid + "&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 + "&id=" + bid + "&c=[^\']*?)'"); n = Regex.Match(result, "(dorf(\\d)\\.php\\?a=" + bid + "&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 }); }