/// <summary> /// Remove a item from the village task queue /// </summary> /// <param name="villageID">Which village the task queue belongs to</param> /// <param name="task">The item to delete from the task queue</param> private void RemoveQueuedTask() { MarkDeleted = true; UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID }); }
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() { // 当前时刻还未到唤醒时刻 if (MinimumDelay > 0) { return; } if (evade_status == EvadeStatus.NoAtkDetected || evade_status == EvadeStatus.AtkDetected || evade_status == EvadeStatus.TroopsBack) { CheckAttack(); } else if (evade_status == EvadeStatus.ReadyForEvade) { DoEvade(); } else if (evade_status == EvadeStatus.Evaded || evade_status == EvadeStatus.ReadyForBack) { evade_status = EvadeStatus.ReadyForBack; DoTroopsBack(); } else { evade_status = EvadeStatus.NoAtkDetected; MinimumDelay = nMinInterval; } UpCall.TD.Dirty = true; UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID }); }
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 }); }
private bool FetchAvailGidAndBidWithlvl(TVillage CV, out int gid, out int bid) { bid = -1; gid = 0; // 按资源田等级 int i; int minlevel = 10; int[] buildpriority = new int[5]; bool bIsCroopsAbove5 = false; // 以粮食的最低等级划分判定区域,避免初期粮食过少 for (i = 1; i <= 18; i++) { if (!CV.Buildings.ContainsKey(i) || CV.Buildings[i].Gid != 4) { continue; } var tlevel = CV.Buildings[i].Level; if (tlevel < minlevel) { minlevel = tlevel; } } if (minlevel >= 5) { bIsCroopsAbove5 = true; } minlevel = 10; // 找到所有资源田的最低等级 for (i = 1; i <= 18; i++) { if (!CV.Buildings.ContainsKey(i)) { continue; } var tlevel = 0; if (bIsCroopsAbove5) { tlevel = CV.Buildings[i].Gid != 4 ? CV.Buildings[i].Level : CV.Buildings[i].Level + 1; } else { tlevel = CV.Buildings[i].Level; } if (tlevel < minlevel) { minlevel = tlevel; } } // 找到等级最低资源田的种类和坑号 int min = 1; for (i = 1; i <= 18; i++) { if (!CV.Buildings.ContainsKey(i)) { continue; } var tlevel = 0; if (bIsCroopsAbove5) { tlevel = CV.Buildings[i].Gid != 4 ? CV.Buildings[i].Level : CV.Buildings[i].Level + 1; } else { tlevel = CV.Buildings[i].Level; } if (tlevel == minlevel && buildpriority[CV.Buildings[i].Gid] == 0) { min = CV.Buildings[i].Gid - 1; buildpriority[CV.Buildings[i].Gid] = i; } } // 如果有多种资源田同级,则按资源的评估比率确定升级的资源田 for (i = 0; i < 4; i++) { if (CV.Resource[min].CurrAmount / Travian.resrate[min] > CV.Resource[i].CurrAmount / Travian.resrate[i] && buildpriority[i + 1] != 0) { min = i; } } gid = min + 1; bid = buildpriority[gid]; // 如果最低等级为10级,则查找等级低于10级的粮食 if (minlevel == 10) { bool croop = false; for (i = 1; i <= 18; i++) { if (!CV.Buildings.ContainsKey(i)) { continue; } var tlevel = CV.Buildings[i].Level; if (tlevel < 10) { gid = CV.Buildings[i].Gid; bid = i; croop = true; break; } } int finish_cnt = 0; for (i = 19; i <= 40; i++) { if (!CV.Buildings.ContainsKey(i)) { continue; } for (int j = 0; j < Goal.Length; j++) { if (CV.Buildings[i].Gid == Goal[j].gid && CV.Buildings[i].Level == Goal[j].limit_lvl) { finish_cnt++; break; } } } // 如果所有资源田都满级了,那么删除掉该任务 if (croop == false && finish_cnt == Goal.Length && CV.Queue.Contains(this)) { MarkDeleted = true; UpCall.TD.Dirty = true; UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID }); return(false); } } return(true); }
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 }); }
public void Action() { if (MinimumDelay > 0) { return; } string data = UpCall.CheckBuildingExistAndQuery(VillageID, 16); if (data == null) { MinimumDelay = 60; return; } hero_status = CheckIfHeroHome(); if (hero_status == -1) { UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID }); UpCall.DebugLog("英雄不属于该村,无法探险!", DebugLevel.II); MarkDeleted = true; return; } else if (hero_status == 1) { UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID }); UpCall.DebugLog("英雄目前不在家,等待英雄返回!", DebugLevel.II); return; } bool bAvail = false; List <HeroAdventureInfo> InfoList = UpCall.TD.Adv_Sta.HeroAdventures; for (int i = 0; i < InfoList.Count; i++) { TimeSpan ts = CheckDurAvail(InfoList[i].duration); if (ts == TimeSpan.MinValue) { continue; } bAvail = true; break; } // 如果当前的探险地方尚未初始化或全部都不合适,则尝试重新抓取 if (!UpCall.TD.Adv_Sta.bIsHeroAdventureInitialize || !bAvail) { UpCall.doFetchHeroAdventures(VillageID); } cur_adv_pt = new TPoint(0, 0); int HeroLoc = UpCall.TD.Adv_Sta.HeroLocate; for (int i = 0; i < InfoList.Count; i++) { TimeSpan ts = CheckDurAvail(InfoList[i].duration); if (ts == TimeSpan.MinValue) { UpCall.DebugLog( "跳过(" + InfoList[i].axis_x + "|" + InfoList[i].axis_y + ")的探险", DebugLevel.II); continue; } TPoint tp = new TPoint(InfoList[i].axis_x, InfoList[i].axis_y); data = UpCall.PageQuery(HeroLoc, "start_adventure.php?from=list&kid=" + tp.Z.ToString()); if (data == null) { continue; } Match m_test = Regex.Match(data, "type=\"submit\" value=\".*?\" name=\"start\""); if (!m_test.Success) { continue; } Dictionary <string, string> PostData = new Dictionary <string, string>(); MatchCollection mc = Regex.Matches( data, "<input type=\"hidden\" name=\"([^\"]*?)\" value=\"([^\"]*?)\" />"); string key, val; foreach (Match m in mc) { key = m.Groups[1].Value; val = m.Groups[2].Value; PostData[key] = val; } UpCall.PageQuery(HeroLoc, "start_adventure.php", PostData); UpCall.PageQuery(HeroLoc, "build.php?gid=16&tt=1"); MinimumDelay = Convert.ToInt32(ts.TotalSeconds); cur_adv_pt = tp; break; } if (cur_adv_pt.IsEmpty) { MinimumDelay = 3600; UpCall.DebugLog("探险位置不存在或行程过长", DebugLevel.II); } else { UpCall.DebugLog("前往(" + cur_adv_pt.X + "|" + cur_adv_pt.Y + ")探险", DebugLevel.II); } hero_status = 2; UpCall.CallStatusUpdate(this, new Travian.StatusChanged() { ChangedData = Travian.ChangedType.Queue, VillageID = VillageID }); }