private HeroStatus CheckIfInAdventure(int VillageID) { TVillage CV = TD.Villages[VillageID]; HeroStatus status = HeroStatus.HERO_NOT_BELONG_HERE; foreach (TTInfo info in CV.Troop.Troops) { if (info.OwnerVillageZ != CV.Z || info.Troops[10] != 1) { continue; } if (TD.Adv_Sta.HeroLocate != VillageID) { TD.Adv_Sta.HeroLocate = VillageID; DebugLog("探测到英雄所在村,更正为:" + CV.Name + "(" + VillageID.ToString() + ")", DebugLevel.II); } if (info.VillageName.Contains("英雄冒险") && info.TroopType == TTroopType.Outgoing) { status = HeroStatus.HERO_IN_ADVANTURE; } else { status = HeroStatus.HERO_NOT_IN_ADVANTURE; } break; } return(status); }
private int CheckIfHeroHome() { TVillage CV = UpCall.TD.Villages[VillageID]; foreach (TTInfo info in CV.Troop.Troops) { if (info.OwnerVillageZ != CV.Z || info.Troops[10] != 1) { continue; } resumeTime = info.FinishTime; if (info.TroopType == TTroopType.InVillage) { return(0); } else { if (info.FinishTime == DateTime.MinValue) { MinimumDelay = 3600; } return(1); } } return(-1); }
public void tick(TVillage CV) { DateTime ThisRefreshTime = this.RefreshTime; if (LastRefreshTime < ThisRefreshTime && ThisRefreshTime < DateTime.Now) { ShouldRefresh = true; LastRefreshTime = ThisRefreshTime; } }
private bool FetchAdditionalConstruction(TVillage CV, out int gid, out int bid) { bid = -1; gid = 0; int tgid, tbid; for (int i = 0; i < Goal.Length; i++) { Goal[i].bPossible = false; } for (int i = 1; i <= 40; i++) { if (!CV.Buildings.ContainsKey(i)) { continue; } for (int j = 0; j < Goal.Length; j++) { if (CV.Buildings[i].Gid == Goal[j].req_gid && CV.Buildings[i].Level >= Goal[j].req_lvl) { if (CV.Buildings[i].Level == Goal[j].req_lvl && (CV.InBuilding[0] != null && CV.InBuilding[0].ABid == i || CV.InBuilding[1] != null && CV.InBuilding[1].ABid == i)) { continue; } Goal[j].bPossible = true; } } } for (int i = 0; i < Goal.Length; i++) { if (!Goal[i].bPossible) { continue; } tgid = Goal[i].gid; tbid = findDorf2Building(CV.Buildings, tgid); if (tbid != -1 && (!CV.Buildings.ContainsKey(tbid) || CV.Buildings.ContainsKey(tbid) && CV.Buildings[tbid].Level < Goal[i].limit_lvl)) { gid = tgid; bid = tbid; return(true); } } return(false); }
private void BalanceSourceTime(Data travianData, int VillageID) { // TODO: FIXME int total = ResourceAmount.TotalAmount; int slots = NoCrop ? 3 : 4; TResAmount targetAmount = new TResAmount(0, 0, 0, 0); if (travianData != null && travianData.Villages.ContainsKey(VillageID) && travianData.Villages[VillageID].isBuildingInitialized == 2) { TVillage TV = travianData.Villages[VillageID]; int[] fulltime = new int[slots]; int maxtime = 0, total2 = 0, totalproduce = 0, total3 = 0; for (int i = 0; i < fulltime.Length; i++) { fulltime[i] = Convert.ToInt32(TV.Resource[i].LeftTime.TotalSeconds); maxtime = Math.Max(maxtime, fulltime[i]); } for (int i = 0; i < fulltime.Length; i++) { targetAmount.Resources[i] = Convert.ToInt32(Convert.ToInt64(TV.Resource[i].Produce) * (maxtime - fulltime[i]) / 3600); total2 += targetAmount.Resources[i]; totalproduce += TV.Resource[i].Produce; } if (total2 > total) { for (int i = 0; i < fulltime.Length; i++) { targetAmount.Resources[i] = Convert.ToInt32(targetAmount.Resources[i] * Convert.ToDouble(total) / total2); total3 += targetAmount.Resources[i]; } } else { double seconds = Convert.ToDouble(total - total2) / totalproduce; for (int i = 0; i < fulltime.Length; i++) { targetAmount.Resources[i] += Convert.ToInt32(TV.Resource[i].Produce * seconds); total3 += targetAmount.Resources[i]; } } targetAmount.Resources[slots - 1] += total - total3; targetAmount.NoNegative(); } ResourceAmount = targetAmount; }
/// <summary> /// Another test for NewParseTroops ///</summary> //[TestMethod()] public void NewParseTroopsCrazy() { Travian target = new Travian(); target.TD = new Data(); int villageId = 1; TVillage village = new TVillage(); target.TD.Villages[villageId] = village; TTroop troops = new TTroop(); village.Troop = troops; target.SetGidLang(16, "Rally Point"); target.NewParseTroops(villageId, Properties.Resources.RallyPointCrazy); Assert.AreEqual(15, troops.Troops.Count); TTInfo troop = troops.Troops[0]; Assert.AreEqual(2, troop.Tribe); Assert.AreEqual("Crazy", troop.Owner); Assert.AreEqual("Return from Jeffo Village", troop.VillageName); Assert.AreEqual(1, troop.Troops[3]); Assert.IsTrue(troop.FinishTime > DateTime.Now.AddMinutes(6)); Assert.IsTrue(troop.FinishTime < DateTime.Now.AddMinutes(8)); Assert.AreEqual(TTroopType.Incoming, troop.TroopType); troop = troops.Troops[1]; Assert.AreEqual(2, troop.Tribe); Assert.AreEqual("Crazy", troop.Owner); Assert.AreEqual("Return from laraelaine40 Village", troop.VillageName); Assert.AreEqual(4, troop.Troops[0]); Assert.IsTrue(troop.FinishTime > DateTime.Now.AddMinutes(10)); Assert.IsTrue(troop.FinishTime < DateTime.Now.AddMinutes(15)); Assert.AreEqual(TTroopType.Incoming, troop.TroopType); troop = troops.Troops[7]; Assert.AreEqual(2, troop.Tribe); Assert.AreEqual("Crazy", troop.Owner); Assert.AreEqual("Own troops", troop.VillageName); Assert.AreEqual(4, troop.Troops[0]); Assert.AreEqual(1, troop.Troops[10]); Assert.AreEqual(TTroopType.InVillage, troop.TroopType); troop = troops.Troops[8]; Assert.AreEqual(TTroopType.Outgoing, troop.TroopType); Assert.AreEqual(2, troop.Tribe); Assert.AreEqual("Crazy", troop.Owner); Assert.AreEqual("Raid on hotmamapam Village", troop.VillageName); Assert.AreEqual(4, troop.Troops[0]); }
private bool FetchAvailGidAndBidWithRes(TVillage CV, out int gid, out int bid) { bid = -1; gid = 0; // 计算仓库容量和粮仓容量的比值 double extrarate = (double)CV.Resource[0].Capacity / CV.Resource[3].Capacity; // 按资源总量 int i; double min_ratio = double.MaxValue; for (i = 0; i < 3; i++) { double ratio = CV.Resource[i].CurrAmount / Travian.resrate[i]; if (ratio < min_ratio) { gid = i + 1; min_ratio = ratio; } } // Crop if (CV.Resource[3].Produce <= 2 || CV.Resource[3].CurrAmount * extrarate / Travian.resrate[3] < min_ratio) { gid = 4; } int min_level = Int32.MaxValue; for (i = 1; i <= 18; i++) { if (!CV.Buildings.ContainsKey(i)) { continue; } if (CV.Buildings[i].Gid == gid) { if (CV.Buildings[i].Level < min_level) { bid = i; min_level = CV.Buildings[i].Level; } } } return(true); }
public TTInfo GetTroopsAtHome(TVillage village) { foreach (TTInfo troop in this.Troops) { if (troop.TroopType == TTroopType.InVillage) { if (troop.OwnerVillageZ == village.Z) { return(troop); } } // if (troop.TroopType == TTroopType.MySelf) // return troop; } return(null); }
public void tick(TVillage CV, int MarketSpeed) { for (int i = MarketInfo.Count - 1; i >= 0; i--) { TMInfo x = MarketInfo[i]; if (x.FinishTime > DateTime.Now) { continue; } if (x.MType == TMType.MyBack) { MarketInfo.Remove(x); if (SingleCarry == 0) { continue; } Console.WriteLine(DateTime.Now.ToLongTimeString() + " " + ActiveMerchant.ToString()); ActiveMerchant += Convert.ToInt32(Math.Ceiling((double)(x.CarryAmount.Resources[0] + x.CarryAmount.Resources[1] + x.CarryAmount.Resources[2] + x.CarryAmount.Resources[3]) / SingleCarry)); Console.WriteLine(DateTime.Now.ToLongTimeString() + " " + ActiveMerchant.ToString()); } else if (x.MType == TMType.MyOut) { x.MType = TMType.MyBack; var distance = CV.Coord * x.Coord; var time = distance * 3600 / MarketSpeed; try { x.FinishTime = x.FinishTime.AddSeconds(time); } catch (Exception ex) { throw new InvalidOperationException( string.Format("{0}\r\nMarketSpeed:{1}\r\nMyCoord:{2}\r\nTargetCoord:{3}", ex.Message, MarketSpeed, CV.Coord, x.Coord)); } } else { for (int j = 0; j < 4; j++) { CV.Resource[j].Write(CV.Resource[j].CurrAmount + x.CarryAmount.Resources[j]); } MarketInfo.Remove(x); } } }
public int GetUsedSlots(TVillage village) { int slotsUsed = 0; foreach (TTInfo troop in this.Troops) { if (troop.TroopType == TTroopType.Incoming || troop.TroopType == TTroopType.Outgoing) { if (troop.OwnerVillageZ == village.Z) { slotsUsed++; } } } return(slotsUsed); }
public void Action() { TVillage village = UpCall.TD.Villages[VillageID]; if (!IsValid) { UpCall.DebugLog("Invalid NPC trade task discarded: " + ToString(), DebugLevel.W); RemoveQueuedTask(); return; } if (CountDown > 0) { return; } NpcTradeResult returnCode = doNpcTrade(); switch (returnCode) { case NpcTradeResult.Failure: UpCall.DebugLog("NPC trade task has failed: " + ToString(), DebugLevel.W); RemoveQueuedTask(); return; case NpcTradeResult.Delay: // Wait at least 10 minutes before retrying MinimumDelay = 600; break; case NpcTradeResult.Success: Count++; if (MaxCount != 0 & Count >= MaxCount) { RemoveQueuedTask(); return; } // This is an unfinished multiple NPC trade task, wait at least 1 hr MinimumDelay = 3600; break; } }
/// <summary> /// Test if there are enough troops in villiage to launch an attack /// </summary> /// <param name="troopsRequested">Requested troops for the attack</param> /// <returns>True if there are enough troops in the village</returns> public bool HasEnoughTroops(TVillage village, int[] troopsRequested) { TTInfo troop = this.GetTroopsAtHome(village); if (troop != null) { for (int i = 0; i < troopsRequested.Length; i++) { if (troopsRequested[i] > troop.Troops[i]) { return(false); } } return(true); } return(false); }
/// <summary> /// Estimate the target village capacity when transportantion arrives, based on /// its current resource amount, production rate, distance, and merchant speed. /// </summary> /// <param name="travianData">Contains game info</param> /// <param name="VillageID">Where the merchant starts, for computing distance</param> /// <returns>Estimated capacity</returns> private TResAmount GetTargetCapacity(Data travianData, int VillageID) { if (travianData != null && travianData.Villages.ContainsKey(this.TargetVillageID) && travianData.Villages.ContainsKey(VillageID)) { TVillage source = travianData.Villages[VillageID]; TVillage destination = travianData.Villages[this.TargetVillageID]; if (destination.isBuildingInitialized == 2) { TResource[] VR = destination.Resource; int[] resources = new int[VR.Length]; int speed = travianData.MarketSpeed == 0 ? 24 : travianData.MarketSpeed; double timecost = source.Coord * destination.Coord / speed; for (int i = 0; i < resources.Length; i++) { resources[i] = VR[i].Capacity * this.LimitRate / 100; if (destination.Market.UpperLimit != null) { resources[i] = destination.Market.UpperLimit.Resources[i]; } resources[i] -= VR[i].CurrAmount + (int)(VR[i].Produce * timecost); } TResAmount capacity = new TResAmount(resources); foreach (TMInfo transfer in destination.Market.MarketInfo) { if (transfer.MType == TMType.OtherCome) { capacity -= transfer.CarryAmount; } } capacity.NoNegative(); return(capacity); } } return(null); }
private void BalanceSourceResource(Data travianData, int VillageID) { TResAmount targetAmount = new TResAmount(0, 0, 0, 0); if (travianData != null && travianData.Villages.ContainsKey(VillageID) && travianData.Villages[VillageID].isBuildingInitialized == 2) { TVillage village = travianData.Villages[VillageID]; for (int i = 0; i < targetAmount.Resources.Length; i++) { targetAmount.Resources[i] = village.Resource[i].CurrAmount; if (village.Market.LowerLimit != null) { targetAmount.Resources[i] -= village.Market.LowerLimit.Resources[i]; } } targetAmount.NoNegative(); } this.DoBalance(targetAmount); }
public TTInfo GetTroopsAtHome(TVillage village) { foreach (TTInfo troop in this.Troops) { if (troop.TroopType == TTroopType.InVillage) { if (troop.OwnerVillageZ == village.Z) { return troop; } } // if (troop.TroopType == TTroopType.MySelf) // return troop; } return null; }
/// <summary> /// /// </summary> /// <param name="Tribe"></param> /// <param name="Villages"></param> /// <param name="CV"></param> /// <param name="Gid"></param> /// <param name="Bid"></param> /// <returns>0:directly, -1:impossible, >0:pre-upgrade gid</returns> static public int testPossibleNewNow(int Tribe, Dictionary <int, TVillage> Villages, TVillage CV, int Gid, int Bid) { // 不能在主村造的建筑 List <int> CapitalNo = new List <int> { 29, 30 }; // 只能在主村造的建筑 List <int> NotCapitalNo = new List <int> { 34, 35 }; // 可重复造的建筑 List <int> Repeatable = new List <int> { 10, 11, 23, 36, 38, 39 }; //TQueue Q = CV.Queue[QueueID]; // Extend if (Gid == 36 && Tribe != 3) { return(-1); } if (Gid == 35 && Tribe != 2) { return(-1); } if (Gid == 41 && Tribe != 1) { return(-1); } if (Gid < 5) { return(0); } // Below are building new one if (CV.isCapital && CapitalNo.Contains(Gid)) { return(-1); } if (!CV.isCapital && NotCapitalNo.Contains(Gid)) { return(-1); } // Residence/Palace problem if (Gid == 26) { int PCount = 0; foreach (var x in Villages) { if (x.Value.isBuildingInitialized == 2) { foreach (var y in x.Value.Buildings) { if (y.Value.Gid == 26 && y.Value.Level > 0) { PCount++; break; } else if (y.Value.Gid == 25) { break; } } } } if (PCount == 0) { bool NotFound = true; foreach (var x in Buildings.Depends[Gid]) { int canUp = 0; foreach (var y in CV.Buildings) { if (x.Gid == y.Value.Gid) { if (x.Level > y.Value.Level) { canUp = y.Key; } else { NotFound = false; break; } } } if (NotFound && canUp != 0) { return(canUp); } } if (NotFound) { return(-1); } else { return(0); } } else { return(-1); } } // Check duplicate int toBuild = 0; if (Repeatable.Contains(Gid)) { foreach (var x in CV.Buildings) { if (x.Key == Bid) { continue; } if (x.Value.Gid == Gid) { if (Buildings.CheckLevelFull(x.Value.Gid, x.Value.Level, CV.isCapital)) { toBuild = 0; break; } else { toBuild = x.Key; } } } if (toBuild != 0) { return(toBuild); } else { return(0); } } // Check duplicate for non-repeatable foreach (var x in CV.Buildings) { if (x.Value.Gid == Gid && x.Key != Bid) { return(-1); } } // Check depend if (!Buildings.Depends.ContainsKey(Gid)) { return(0); } bool gNotFound = false; foreach (var x in Buildings.Depends[Gid]) { bool NotFound = true; int canUp = 0; foreach (var y in CV.Buildings) { if (x.Gid == y.Value.Gid) { if (x.Level > y.Value.Level) { canUp = y.Key; } else { NotFound = false; break; } } } if (NotFound && canUp != 0) { return(canUp); } gNotFound = gNotFound || NotFound; if (gNotFound) { break; } } return(gNotFound ? -1 : 0); }
public void Action() { TVillage CV = this.UpCall.TD.Villages[VillageID]; if (this.NextExec >= DateTime.Now) { return; } this.NextExec = DateTime.Now.AddSeconds(50); if (CV.isBuildingInitialized != 2) { return; } int gid, bid; if (AIType == TAIType.Resource) { if (!FetchAvailGidAndBidWithRes(CV, out gid, out bid)) { return; } } else { if (!FetchAvailGidAndBidWithlvl(CV, out gid, out bid)) { return; } } if (!CV.Buildings.ContainsKey(bid)) { return; } int[] costs = Buildings.Cost(gid, CV.Buildings[bid].Level + 1).Resources; int inside_gid, insid_bid; if (FetchAvailInsideBuilding(CV, costs, out inside_gid, out insid_bid)) { gid = inside_gid; bid = insid_bid; } UpCall.DebugLog("AIQueue准备建造 " + DisplayLang.Instance.GetGidLang(gid) + " @" + bid, DebugLevel.II); var BQ = new BuildingQueue() { Bid = bid, Gid = gid, UpCall = UpCall, VillageID = VillageID }; Gid = gid; int cd = BQ.CountDown; if (cd <= 0) { UpCall.DebugLog("AIQueue建筑队列启动!", DebugLevel.II); BQ.Action(); } else { int delay = Math.Min(15 * 60, cd); UpCall.DebugLog("AIQueue建筑队列未能启动,建造该单位尚需等待" + cd + "秒;将于" + delay + "秒后再检查一次。" , DebugLevel.II); this.NextExec = DateTime.Now.AddSeconds(delay); // 为了防止资源未刷新而引起的问题 UpCall.PageQuery(VillageID, "dorf1.php"); } }
private bool FetchAvailInsideBuilding(TVillage CV, int[] costs, out int gid, out int bid) { bid = -1; gid = 0; // 根据当前村庄的数量平衡建造资源田所需的资源和仓库容量 // 村数 仓库容量 / 需要资源的最高项 粮仓容量 / 需要粮食量 仓库容量 / 中心大楼等级 // 1 ~ 5 2 3 3000(中心大楼9到10级,需要仓库先到27000) // 6 ~ 20 3 4 3000(中心大楼9到10级,需要仓库先到27000) // 20以上 7 8 1000(中心大楼9到10级,需要仓库先到9000) int[] rate2; if (UpCall.TD.Villages.Count > 20) { rate2 = new int[3] { 7, 8, 1000 } } ; else if (UpCall.TD.Villages.Count > 5) { rate2 = new int[3] { 3, 4, 1000 } } ; else { rate2 = new int[3] { 2, 3, 1000 } }; // 检查仓库和粮仓 int tgid, tbid; // 罗马双建: // 在内城建筑为空的情况下,优先建造内城建筑, // 那么在下轮再Tick的时候,将会跳过下面这块而开始造外城资源田 TInBuilding[] Cinb = CV.InBuilding; if (Cinb[1] == null || Convert.ToInt32(Cinb[1].FinishTime.Subtract(DateTime.Now).TotalSeconds) <= 0) { // 找到建造当前建筑需要最多的资源 int max_cost = 0; for (int i = 0; i < 3; i++) { if (costs[i] > max_cost) { max_cost = costs[i]; } } // 如果仓库的总容量低于总需求的rate2[0]倍,则需要升级仓库 if (CV.Resource[0].Capacity < max_cost * rate2[0]) { tgid = 10; tbid = findDorf2Building(CV.Buildings, tgid); if (tbid != -1) { gid = tgid; bid = tbid; return(true); } } // 如果粮仓的总容量低于粮食需求的rate2[1]倍,则需要升级粮仓 else if (CV.Resource[3].Capacity < costs[3] * rate2[1]) { tgid = 11; tbid = findDorf2Building(CV.Buildings, tgid); if (tbid != -1) { gid = tgid; bid = tbid; return(true); } } // 如果中心大楼等级的rate2[2]倍低于仓库容量,则需要升级中心大楼 else if (!Travian.NoMB) { tgid = 15; tbid = findDorf2Building(CV.Buildings, tgid); if (tbid != -1 && (!CV.Buildings.ContainsKey(tbid) || CV.Buildings.ContainsKey(tbid) && CV.Buildings[tbid].Level < 10 && CV.Buildings[tbid].Level * rate2[2] < CV.Resource[0].Capacity)) { gid = tgid; bid = tbid; return(true); } } if (FetchAdditionalConstruction(CV, out gid, out bid)) { return(true); } } return(false); }
private IQueue GetSelectedTask(TVillage village) { if (this.m_queuelist.listViewQueue.SelectedIndices.Count == 0) { return null; } int index = this.m_queuelist.listViewQueue.SelectedIndices[0]; if (index >= village.Queue.Count) { return null; } return village.Queue[index]; }
public void doFetchHeroAdventures(object o) { lock (Level2Lock) { int VillageID = (int)o; string data = PageQuery(VillageID, "hero_inventory.php"); // 查询英雄状态 if (string.IsNullOrEmpty(data)) { return; } string hero_status = HtmlUtility.GetElementWithClass( data, "div", "attribute heroStatus"); if (string.IsNullOrEmpty(hero_status)) { return; } Match m = Regex.Match(hero_status, "karte.php\\?d=(\\d+)"); int hero_loc = 0; if (m.Success) { int z = Convert.ToInt32(m.Groups[1].Value); foreach (var x in TD.Villages) { TVillage v = x.Value; if (v.Z == z) { hero_loc = x.Key; TD.Adv_Sta.HeroLocate = hero_loc; break; } } } else { hero_loc = (TD.Adv_Sta.HeroLocate == 0 ? VillageID : TD.Adv_Sta.HeroLocate); } data = PageQuery(hero_loc, "hero_adventure.php"); // 查询探险地点 if (string.IsNullOrEmpty(data)) { return; } string[] places = HtmlUtility.GetElements(data, "tr"); if (places.Length <= 1) { return; } int coord_x, coord_y; string dur, dgr, lnk; DateTime fin; TD.Adv_Sta.HeroAdventures.Clear(); for (int i = 1; i < places.Length; i++) { // 坐标 string coords = HtmlUtility.GetElementWithClass( places[i], "td", "coords"); if (coords == null) { continue; } m = Regex.Match(coords, "karte.php\\?x=(\\-?\\d+)&y=(\\-?\\d+)"); if (!m.Success) { continue; } coord_x = Convert.ToInt32(m.Groups[1].Value); coord_y = Convert.ToInt32(m.Groups[2].Value); // 持续时间 string move_time = HtmlUtility.GetElementWithClass( places[i], "td", "moveTime"); if (move_time == null) { continue; } m = Regex.Match(move_time, "\\d+:\\d+:\\d+"); if (!m.Success) { continue; } dur = m.Groups[0].Value; // 难度 string difficulty = HtmlUtility.GetElementWithClass( places[i], "td", "difficulty"); if (difficulty == null) { continue; } m = Regex.Match(difficulty, "alt=\"([^\"]*?)\""); if (!m.Success) { continue; } dgr = m.Groups[1].Value; // 难度 string timeLeft = HtmlUtility.GetElementWithClass( places[i], "td", "timeLeft"); if (timeLeft == null) { continue; } m = Regex.Match(timeLeft, "\\d+:\\d+:\\d+"); if (!m.Success) { continue; } fin = DateTime.Now.Add(TimeSpanParse(m.Groups[0].Value)); // 链接 string goTo = HtmlUtility.GetElementWithClass( places[i], "td", "goTo"); if (goTo == null) { continue; } m = Regex.Match(goTo, "href=\"([^\"]*?)\""); if (!m.Success) { continue; } lnk = m.Groups[1].Value; // 增加新的探险地点 HeroAdventureInfo adv_info = new HeroAdventureInfo() { axis_x = coord_x, axis_y = coord_y, duration = dur, danger = dgr, finish_time = fin, link = lnk }; TD.Adv_Sta.HeroAdventures.Add(adv_info); } TD.Adv_Sta.bIsHeroAdventureInitialize = true; TD.Adv_Sta.bShouldRefreshAdventureDisplay = true; TD.Dirty = true; } }
/// <summary> /// Distribute a total amount based on the distribution ratio /// </summary> public TResAmount RedistributeResources(Data travianData, int villageID, int sum) { if (!travianData.Villages.ContainsKey(villageID)) { return(null); } TVillage village = travianData.Villages[villageID]; if (village.isBuildingInitialized != 2) { return(null); } TResAmount target = new TResAmount(this.Distribution); TResAmount distribution = new TResAmount(); // Allocate by proportion int residual = sum - distribution.TotalAmount; while (target.TotalAmount > 0 && residual > 10) { double[] proportions = target.Proportions; for (int i = 0; i < proportions.Length; i++) { distribution.Resources[i] += (int)(residual * proportions[i]); if (distribution.Resources[i] > village.Resource[i].Capacity) { distribution.Resources[i] = village.Resource[i].Capacity; target.Resources[i] = 0; } } residual = sum - distribution.TotalAmount; } // Don't trade if residual exceeds 50% threshold bool tooManyResidual = true; for (int i = 0; i < this.Threshold.Resources.Length; i++) { if (residual < this.Threshold.Resources[i] * (100 - this.MinTradeRatio) / 100) { tooManyResidual = false; break; } } if (tooManyResidual) { return(null); } // Allocate by capacity for (int i = 0; i < distribution.Resources.Length; i++) { distribution.Resources[i] = Math.Min( distribution.Resources[i] + residual, village.Resource[i].Capacity); residual = sum - distribution.TotalAmount; } return(distribution); }
public void TestInitialize() { this.travianData = new Data() { Server = "none", Username = "******" }; Dictionary<string, string> Options = new Dictionary<string, string>(); this.travian = new Travian(travianData, Options, "cn"); this.villageID = 1; this.village = new TVillage(); this.travianData.Villages[villageID] = village; this.village.Name = "Home"; this.village.isTroopInitialized = 2; this.village.Troop = this.troop = new TTroop(); int[] troopsAtHome = new int[11]; troopsAtHome[0] = 8; TTInfo troopAtHome = new TTInfo { Troops = troopsAtHome, Owner = this.village.Name, TroopType = TTroopType.InVillage, VillageName = "Own troops" }; this.troop.Troops.Add(troopAtHome); int[] troopsOnTheRood = new int[11]; troopsOnTheRood[0] = 5; TTInfo troopOnTheRoad = new TTInfo { Troops = troopsAtHome, TroopType = TTroopType.MyReturnWay, FinishTime = DateTime.Now.AddSeconds(100), VillageName = "Raid on abc Village" }; this.troop.Troops.Add(troopOnTheRoad); this.troops = new int[11]; this.troops[0] = 5; this.targets = new List<TPoint>(); this.targets.Add(new TPoint(1, 2)); this.targets.Add(new TPoint(0, 0)); this.target = new RaidQueue() { UpCall = this.travian, VillageID = this.villageID, Troops = this.troops, Targets = this.targets, RaidType = RaidType.AttackRaid, }; this.pageQuerier = new MockPageQuerier(this.villageID); this.travian.pageQuerier = pageQuerier; }
private void ProduceTroopSetting_Load(object sender, EventArgs e) { mui.RefreshLanguage(this); if (TravianData == null) return; CV = TravianData.Villages[RUVillageID]; listBox1.Items.Clear(); if (checkBox3.Checked) { numericUpDown1.Value = 1; numericUpDownTransferCount.Value = 0; numericUpDown1.Enabled = false; numericUpDownTransferCount.Enabled = false; checkBox1.Enabled = false; listBox1.Enabled = false; } else { numericUpDown1.Value = 0; numericUpDownTransferCount.Value = 1; numericUpDown1.Enabled = numericUpDownTransferCount.Enabled = checkBox1.Enabled = listBox1.Enabled = true; if (CanProduce != null) foreach (var p in CanProduce) if (p.Researched | checkBox1.Checked) listBox1.Items.Add(p); } }
private TResAmount NeedCrop(Data travianData) { return(null); if (NoCrop) { return(null); } if (Distribution == ResourceDistributionType.Uniform || Distribution == ResourceDistributionType.BalanceSource || Distribution == ResourceDistributionType.BalanceSourceTime) { return(null); } if (Distribution == ResourceDistributionType.None && ResourceAmount.Resources[3] <= 0) { return(null); } if (travianData == null || !travianData.Villages.ContainsKey(TargetVillageID) || !travianData.Villages.ContainsKey(VillageID)) { return(null); } TVillage source = travianData.Villages[VillageID]; TVillage destination = travianData.Villages[TargetVillageID]; if (destination.isBuildingInitialized != 2) { return(null); } if (destination.Resource[3].Produce >= 0) { if (UpCall != null) { UpCall.DebugLog("Target Produce >= 0, no need crop rule.", DebugLevel.I); } return(null); } int speed = travianData.MarketSpeed == 0 ? 24 : travianData.MarketSpeed; int timecost = Convert.ToInt32(source.Coord * destination.Coord * 3600 / speed) + 30; int cropcap = destination.Resource[3].CurrAmount + timecost * destination.Resource[3].Produce / 3600; foreach (TMInfo transfer in destination.Market.MarketInfo) { if (transfer.MType == TMType.OtherCome && transfer.FinishTime < DateTime.Now.AddSeconds(timecost)) { cropcap += transfer.CarryAmount.Resources[3]; } } if (cropcap <= 0) { return(new TResAmount(0, 0, 0, ResourceAmount.TotalAmount)); } if (UpCall != null) { UpCall.DebugLog("Target village don't need crop, no need crop rule.", DebugLevel.I); } return(null); }
public int GetUsedSlots(TVillage village) { int slotsUsed = 0; foreach (TTInfo troop in this.Troops) { if (troop.TroopType == TTroopType.Incoming || troop.TroopType == TTroopType.Outgoing) { if (troop.OwnerVillageZ == village.Z) { slotsUsed++; } } } return slotsUsed; }
/// <summary> /// Test if there are enough troops in villiage to launch an attack /// </summary> /// <param name="troopsRequested">Requested troops for the attack</param> /// <returns>True if there are enough troops in the village</returns> public bool HasEnoughTroops(TVillage village, int[] troopsRequested) { TTInfo troop = this.GetTroopsAtHome(village); if (troop != null) { for (int i = 0; i < troopsRequested.Length; i++) { if (troopsRequested[i] > troop.Troops[i]) { return false; } } return true; } return false; }
private void TransferSetting_Load(object sender, EventArgs e) { mui.RefreshLanguage(this); if (TravianData == null) return; CV = TravianData.Villages[FromVillageID]; foreach (var v in TravianData.Villages) if (v.Key != FromVillageID) comboBoxTargetVillage.Items.Add(v.Key + " " + v.Value.Coord + " " + v.Value.Name); else comboBoxTargetVillage.SelectedIndex = comboBoxTargetVillage.Items.Count - 1; if (File.Exists("Transfer")) { var ts = File.ReadAllLines("Transfer"); foreach (var t in ts) { string[] opt = t.Split(new char[] { '|' }, 3); if (opt.Length < 3) continue; int x = 0, y = 0; if(int.TryParse(opt[0], out x) && int.TryParse(opt[1], out y)) if(Math.Abs(x) <= 400 && Math.Abs(y) <= 400) comboBoxTargetVillage2.Items.Add(opt[0] + "|" + opt[1] + " " + opt[2]); } } numericUpDown1.Increment = numericUpDown2.Increment = numericUpDown3.Increment = numericUpDown4.Increment = CV.Market.SingleCarry; numericUpDown1.Maximum = numericUpDown2.Maximum = numericUpDown3.Maximum = numericUpDown4.Maximum = CV.Market.SingleCarry * CV.Market.MaxMerchant; numericUpDownMerchantCount.Maximum = CV.Market.MaxMerchant; }
public void tick(TVillage CV, int MarketSpeed) { for (int i = MarketInfo.Count - 1; i >= 0; i--) { TMInfo x = MarketInfo[i]; if (x.FinishTime > DateTime.Now) continue; if (x.MType == TMType.MyBack) { MarketInfo.Remove(x); if (SingleCarry == 0) continue; Console.WriteLine(DateTime.Now.ToLongTimeString() + " " + ActiveMerchant.ToString()); ActiveMerchant += Convert.ToInt32(Math.Ceiling((double)(x.CarryAmount.Resources[0] + x.CarryAmount.Resources[1] + x.CarryAmount.Resources[2] + x.CarryAmount.Resources[3]) / SingleCarry)); Console.WriteLine(DateTime.Now.ToLongTimeString() + " " + ActiveMerchant.ToString()); } else if (x.MType == TMType.MyOut) { x.MType = TMType.MyBack; var distance = CV.Coord * x.Coord; var time = distance * 3600 / MarketSpeed; try { x.FinishTime = x.FinishTime.AddSeconds(time); } catch (Exception ex) { throw new InvalidOperationException( string.Format("{0}\r\nMarketSpeed:{1}\r\nMyCoord:{2}\r\nTargetCoord:{3}", ex.Message, MarketSpeed, CV.Coord, x.Coord)); } } else { for (int j = 0; j < 4; j++) CV.Resource[j].Write(CV.Resource[j].CurrAmount + x.CarryAmount.Resources[j]); MarketInfo.Remove(x); } } }
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; }
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); }
private bool FetchAvailInsideBuilding(TVillage CV, int[] costs, out int gid, out int bid) { bid = -1; gid = 0; // 根据当前村庄的数量平衡建造资源田所需的资源和仓库容量 // 村数 仓库容量 / 需要资源的最高项 粮仓容量 / 需要粮食量 仓库容量 / 中心大楼等级 // 1 ~ 5 2 3 3000(中心大楼9到10级,需要仓库先到27000) // 6 ~ 20 3 4 3000(中心大楼9到10级,需要仓库先到27000) // 20以上 7 8 1000(中心大楼9到10级,需要仓库先到9000) int[] rate2; if(UpCall.TD.Villages.Count > 20) rate2 = new int[3] { 7, 8, 1000 }; else if(UpCall.TD.Villages.Count > 5) rate2 = new int[3] { 3, 4, 1000 }; else rate2 = new int[3] { 2, 3, 1000 }; // 检查仓库和粮仓 int tgid, tbid; // 罗马双建: // 在内城建筑为空的情况下,优先建造内城建筑, // 那么在下轮再Tick的时候,将会跳过下面这块而开始造外城资源田 TInBuilding[] Cinb = CV.InBuilding; if(Cinb[1] == null || Convert.ToInt32(Cinb[1].FinishTime.Subtract(DateTime.Now).TotalSeconds) <= 0) { // 找到建造当前建筑需要最多的资源 int max_cost = 0; for (int i = 0; i < 3; i++) { if (costs[i] > max_cost) { max_cost = costs[i]; } } // 如果仓库的总容量低于总需求的rate2[0]倍,则需要升级仓库 if(CV.Resource[0].Capacity < max_cost * rate2[0]) { tgid = 10; tbid = findDorf2Building(CV.Buildings, tgid); if(tbid != -1) { gid = tgid; bid = tbid; return true; } } // 如果粮仓的总容量低于粮食需求的rate2[1]倍,则需要升级粮仓 else if(CV.Resource[3].Capacity < costs[3] * rate2[1]) { tgid = 11; tbid = findDorf2Building(CV.Buildings, tgid); if(tbid != -1) { gid = tgid; bid = tbid; return true; } } // 如果中心大楼等级的rate2[2]倍低于仓库容量,则需要升级中心大楼 else if(!Travian.NoMB) { tgid = 15; tbid = findDorf2Building(CV.Buildings, tgid); if(tbid != -1 && (!CV.Buildings.ContainsKey(tbid) || CV.Buildings.ContainsKey(tbid) && CV.Buildings[tbid].Level < 10 && CV.Buildings[tbid].Level * rate2[2] < CV.Resource[0].Capacity)) { gid = tgid; bid = tbid; return true; } } if (FetchAdditionalConstruction(CV, out gid, out bid)) return true; } return false; }
private bool EditRaidQueue(TVillage village, RaidQueue task) { if (village.isTroopInitialized != 2) { village.InitializeTroop(); return false; } RaidOptForm rof = new RaidOptForm() { mui = this.mui, dl = this.dl, TroopsAtHome = village.Troop.GetTroopsAtHome(village), Village = village, Return = task, }; if (rof.ShowDialog() != DialogResult.OK) { return false; } if (rof.Return == null || !rof.Return.IsValid) { return false; } task.CopySettings(rof.Return); return true; }
private bool EditBalancerGroupQueue(TVillage village, BalancerQueue Queue) { //return this.EditRaidQueue(village, null); BalanceForm form = new BalanceForm() { Village = village, BalancerGroup = (Queue == null) ? TBalancerGroup.GetDefaultTBalancerGroup() : Queue.BalancerGroup, mui = this.mui, }; if (form.ShowDialog() != DialogResult.OK) { return false; } if (form.BalancerGroup == null) { return false; } if (Queue != null) { village.Queue.Remove(Queue); } Queue = new BalancerQueue() { UpCall = tr, VillageID = SelectVillage, BalancerGroup = form.BalancerGroup, }; village.Queue.Add(Queue); lvi(Queue); form.Close(); return true; }
/// <summary> /// A test for NewParseTroops ///</summary> //[TestMethod()] public void NewParseTroopsTiny() { Travian target = new Travian(); target.TD = new Data(); int villageId = 1; TVillage village = new TVillage(); target.TD.Villages[villageId] = village; TTroop troops = new TTroop(); village.Troop = troops; target.SetGidLang(16, "Rally Point"); target.NewParseTroops(villageId, Properties.Resources.RallyPointTiny); Assert.AreEqual(3, troops.Troops.Count); TTInfo troop = troops.Troops[0]; Assert.AreEqual("Tiny", troop.Owner); Assert.AreEqual(270225, troop.OwnerVillageZ); Assert.AreEqual("Own troops", troop.VillageName); Assert.AreEqual(8, troop.Troops[0]); Assert.AreEqual(TTroopType.InVillage, troop.TroopType); Assert.AreEqual(DateTime.MinValue, troop.FinishTime); Assert.AreEqual(3, troop.Tribe); troop = troops.Troops[1]; Assert.AreEqual("Crazy", troop.Owner); Assert.AreEqual(217466, troop.OwnerVillageZ); Assert.AreEqual("abc's troops", troop.VillageName); Assert.AreEqual(1, troop.Troops[3]); Assert.AreEqual(TTroopType.InVillage, troop.TroopType); Assert.AreEqual(DateTime.MinValue, troop.FinishTime); Assert.AreEqual(2, troop.Tribe); troop = troops.Troops[2]; Assert.AreEqual("Tiny", troop.Owner); Assert.AreEqual(270225, troop.OwnerVillageZ); Assert.AreEqual("Reinforcement for lalala Village", troop.VillageName); Assert.AreEqual(1, troop.Troops[10]); Assert.AreEqual(TTroopType.Outgoing, troop.TroopType); Assert.IsTrue(troop.FinishTime.AddHours(-11) > DateTime.Now); Assert.IsTrue(troop.FinishTime.AddHours(-12) < DateTime.Now); Assert.AreEqual(3, troop.Tribe); }
private void ProduceTroopSetting_Load(object sender, EventArgs e) { mui.RefreshLanguage(this); if (TravianData == null) return; CV = TravianData.Villages[RUVillageID]; TResAmount TroopRes = new TResAmount(0,0,0,0); if (!initialized) { this.buttonOK.Enabled = false; numericUpDown1.Value = 0; numericUpDownTransferCount.Value = 1; numericUpDown1.Enabled = numericUpDownTransferCount.Enabled = checkBox1.Enabled = listBox1.Enabled = true; listBox1.Items.Clear(); if (CanProduce != null) foreach (var p in CanProduce) if (p.Researched | checkBox1.Checked) listBox1.Items.Add(p); initialized = true; } if (listBox1.SelectedIndices.Count == 1 || checkBox3.Checked) { int Aid = checkBox3.Checked ? 10 : (listBox1.SelectedItem as TroopInfo).Aid; int key = (TravianData.Tribe - 1) * 10 + Aid; int Amount = Convert.ToInt32(numericUpDown1.Value); if (Aid == 9 || Aid == 10) { if (Amount > 1) { Amount = 1; numericUpDown1.Value = 1; } TroopRes = Buildings.TroopCost[key] * Amount; } else TroopRes = Buildings.TroopCost[key] * Amount * (checkBox2.Checked ? 3 : 1); } if (checkBox3.Checked) { listBox1.Items.Clear(); numericUpDown1.Value = 1; numericUpDownTransferCount.Value = 0; numericUpDown1.Enabled = false; numericUpDownTransferCount.Enabled = false; checkBox1.Enabled = false; listBox1.Enabled = false; TroopRes = Buildings.TroopCost[(TravianData.Tribe - 1) * 10 + 10]; } var ResRes = CV.ResourceCurrAmount - TroopRes; this.labelA.ForeColor = this.labelB.ForeColor = this.labelC.ForeColor = this.labelD.ForeColor = Color.FromArgb(0, 0, 0); if (ResRes.Resources[0] <= 0) this.labelA.ForeColor = Color.FromArgb(255, 0, 0); if (ResRes.Resources[1] <= 0) this.labelB.ForeColor = Color.FromArgb(255, 0, 0); if (ResRes.Resources[2] <= 0) this.labelC.ForeColor = Color.FromArgb(255, 0, 0); if (ResRes.Resources[3] <= 0) this.labelD.ForeColor = Color.FromArgb(255, 0, 0); this.labelA.Text = string.Format("{2}/{1} \r\n {0}", TroopRes.Resources[0].ToString(), CV.ResourceCurrAmount.Resources[0].ToString(), ResRes.Resources[0].ToString()); this.labelB.Text = string.Format("{2}/{1} \r\n {0}", TroopRes.Resources[1].ToString(), CV.ResourceCurrAmount.Resources[1].ToString(), ResRes.Resources[1].ToString()); this.labelC.Text = string.Format("{2}/{1} \r\n {0}", TroopRes.Resources[2].ToString(), CV.ResourceCurrAmount.Resources[2].ToString(), ResRes.Resources[2].ToString()); this.labelD.Text = string.Format("{2}/{1} \r\n {0}", TroopRes.Resources[3].ToString(), CV.ResourceCurrAmount.Resources[3].ToString(), ResRes.Resources[3].ToString()); }
private void comboBoxTargetVillage_SelectedIndexChanged(object sender, EventArgs e) { this.TV = null; if (comboBoxTargetVillage.SelectedIndex == 0) { this.txtX.Enabled = this.txtY.Enabled = true; targetVillageID = 0; } else { this.comboBoxTargetVillage2.SelectedIndex = 0; comboBoxTargetVillage2_SelectedIndexChanged(this, e); this.txtX.Enabled = this.txtY.Enabled = false; this.targetVillageID = Convert.ToInt32((comboBoxTargetVillage.SelectedItem as string).Split(' ')[0]); if (TravianData.Villages.ContainsKey(this.targetVillageID)) { TVillage village = TravianData.Villages[this.targetVillageID]; this.txtX.Text = village.X.ToString(); this.txtY.Text = village.Y.ToString(); if (village.isBuildingInitialized == 2) { this.TV = village; } } } if (this.TV == null) { this.radioNormalTarget.Enabled = false; this.buttonTarget.Enabled = false; if (this.radioNormalTarget.Checked) { this.radioNormalMe.Checked = true; } } else { this.radioNormalTarget.Enabled = true; this.buttonTarget.Enabled = true; } numericUpDownMechantCount_ValueChanged(sender, e); }
// ������ׯ�Ļ�����Ϣ private void NewParseVillages(string data) { if (data == null) return; int i; int Currid = 0; MatchCollection mc; mc = Regex.Matches( data, "newdid=(\\d+).*?\\((\\-?\\d+).*?\\|[^0-9\\-]*?(\\-?\\d+)\\)[^>]*?>([^<]*?)</a>", RegexOptions.Singleline); /* * Groups: * [1]: village id * [2&3]: position * [4]: village name */ data = this.pageQuerier.PageQuery(0, "spieler.php?uid=" + TD.UserID, null, true, true); if (data == null) return; if (mc.Count == 0) { Match m = Regex.Match(data, "karte.php\\?d=(\\d+)\">([^<]*)</a>.*?</span>"); if (TD.Villages.Count < 1) { TVillage tv = new TVillage() { Name = m.Groups[2].Value, Z = Convert.ToInt32(m.Groups[1].Value), isCapital = true, UpCall = this }; string viddata = this.pageQuerier.PageQuery(0, "dorf3.php", null, true, true); if (viddata == null) return; m = Regex.Match(viddata, "newdid=(\\d+)"); tv.ID = Convert.ToInt32(m.Groups[1].Value); TD.Villages[tv.ID] = tv; Currid = tv.ID; TD.Dirty = true; } } else { for (i = 0; i < mc.Count; i++) { Match m = mc[i]; int vid = Convert.ToInt32(m.Groups[1].Value); if (TD.Villages.ContainsKey(vid)) continue; string pos_x = m.Groups[2].Value; string pos_y = m.Groups[3].Value; string v_name = m.Groups[4].Value; TD.Villages[vid] = new TVillage() { ID = vid, Name = v_name, X = Convert.ToInt32(pos_x), Y = Convert.ToInt32(pos_y), UpCall = this }; if (m.Groups[1].Value != "") Currid = vid; } } mc = Regex.Matches(data, "karte.php\\?d=(\\d+)\">([^<]*?)</a>\\s*?<[^>]*?>([^<]*?)</span>"); int CapZ = 0; foreach (Match m in mc) { if (m.Groups[3].Value.Length > 0) CapZ = Convert.ToInt32(m.Groups[1].Value); } foreach (KeyValuePair<int, TVillage> x in TD.Villages) { if (x.Value.Z == CapZ) x.Value.isCapital = true; else x.Value.isCapital = false; } TD.Dirty = true; TD.ActiveDid = Currid; }
private bool FetchAdditionalConstruction(TVillage CV, out int gid, out int bid) { bid = -1; gid = 0; int tgid, tbid; for (int i = 0; i < Goal.Length; i++) { Goal[i].bPossible = false; } for (int i = 1; i <= 40; i++) { if(!CV.Buildings.ContainsKey(i)) continue; for (int j = 0; j < Goal.Length; j++) { if (CV.Buildings[i].Gid == Goal[j].req_gid && CV.Buildings[i].Level >= Goal[j].req_lvl) { if (CV.Buildings[i].Level == Goal[j].req_lvl && (CV.InBuilding[0] != null && CV.InBuilding[0].ABid == i || CV.InBuilding[1] != null && CV.InBuilding[1].ABid == i)) continue; Goal[j].bPossible = true; } } } for (int i = 0; i < Goal.Length; i++) { if (!Goal[i].bPossible) continue; tgid = Goal[i].gid; tbid = findDorf2Building(CV.Buildings, tgid); if (tbid != -1 && (!CV.Buildings.ContainsKey(tbid) || CV.Buildings.ContainsKey(tbid) && CV.Buildings[tbid].Level < Goal[i].limit_lvl)) { gid = tgid; bid = tbid; return true; } } return false; }
private void LoadTroopsOnTheWay(TVillage village, string fromOrTo, bool inVillageTroopsParsed) { Dictionary<string, string> postData = new Dictionary<string, string>(); postData["cmd"] = "loadTroopsOnTheWay"; postData["qid"] = "0"; postData["limit"] = "10"; postData["fromOrTo"] = fromOrTo; postData["timer"] = "0"; postData["did"] = village.ID.ToString(); postData["showAllIncoming"] = ""; postData["showAllOutgoing"] = ""; TTroopType troop_type = TTroopType.Outgoing; if (fromOrTo == "to") { troop_type = TTroopType.Incoming; } int count = 0; int offset = 0; postData["offset"] = offset.ToString(); while (true) { string ret_data = this.PageQuery(village.ID, "ajax.php?cmd=loadTroopsOnTheWay", postData, true, true); if (ret_data == null) continue; ret_data = ret_data.Replace("\\n", "\r\n"); ret_data = ret_data.Replace("\\t", "\t"); ret_data = ret_data.Replace("\\/", "/"); ret_data = ret_data.Replace("\\\"", "\""); string[] troopDetails = HtmlUtility.GetElementsWithClass( ret_data, "table", "troop_details\\s*[^\"]*?"); bool postInVillageTroops = inVillageTroopsParsed; count = 0; foreach (string troopDetail in troopDetails) { TTInfo troop = this.ParseTroopDetail(troopDetail, postInVillageTroops, troop_type); if (troop != null) { count++; village.Troop.Troops.Add(troop); if (troop.TroopType == TTroopType.InVillage) { inVillageTroopsParsed = true; } } } if (count < 10) { break; } else { offset += 10; postData["offset"] = offset.ToString(); } } }
private bool FetchAvailGidAndBidWithRes(TVillage CV, out int gid, out int bid) { bid = -1; gid = 0; // 计算仓库容量和粮仓容量的比值 double extrarate = (double)CV.Resource[0].Capacity / CV.Resource[3].Capacity; // 按资源总量 int i; double min_ratio = double.MaxValue; for(i = 0; i < 3; i++) { double ratio = CV.Resource[i].CurrAmount / Travian.resrate[i]; if (ratio < min_ratio) { gid = i + 1; min_ratio = ratio; } } // Crop if (CV.Resource[3].Produce <= 2 || CV.Resource[3].CurrAmount * extrarate / Travian.resrate[3] < min_ratio) { gid = 4; } int min_level = Int32.MaxValue; for (i = 1; i <= 18; i++) { if (!CV.Buildings.ContainsKey(i)) continue; if (CV.Buildings[i].Gid == gid) { if (CV.Buildings[i].Level < min_level) { bid = i; min_level = CV.Buildings[i].Level; } } } return true; }
/// <summary> /// /// </summary> /// <param name="Tribe"></param> /// <param name="Villages"></param> /// <param name="CV"></param> /// <param name="Gid"></param> /// <param name="Bid"></param> /// <returns>0:directly, -1:impossible, >0:pre-upgrade gid</returns> public static int testPossibleNewNow(int Tribe, Dictionary<int, TVillage> Villages, TVillage CV, int Gid, int Bid) { // 不能在主村造的建筑 List<int> CapitalNo = new List<int> { 29, 30 }; // 只能在主村造的建筑 List<int> NotCapitalNo = new List<int> { 34, 35 }; // 可重复造的建筑 List<int> Repeatable = new List<int> { 10, 11, 23, 36, 38, 39 }; //TQueue Q = CV.Queue[QueueID]; // Extend if (Gid == 36 && Tribe != 3) return -1; if (Gid == 35 && Tribe != 2) return -1; if (Gid == 41 && Tribe != 1) return -1; if (Gid < 5) return 0; // Below are building new one if (CV.isCapital && CapitalNo.Contains(Gid)) return -1; if (!CV.isCapital && NotCapitalNo.Contains(Gid)) return -1; // Residence/Palace problem if (Gid == 26) { int PCount = 0; foreach (var x in Villages) if (x.Value.isBuildingInitialized == 2) foreach (var y in x.Value.Buildings) if (y.Value.Gid == 26 && y.Value.Level > 0) { PCount++; break; } else if (y.Value.Gid == 25) break; if (PCount == 0) { bool NotFound = true; foreach (var x in Buildings.Depends[Gid]) { int canUp = 0; foreach (var y in CV.Buildings) if (x.Gid == y.Value.Gid) if (x.Level > y.Value.Level) canUp = y.Key; else { NotFound = false; break; } if (NotFound && canUp != 0) return canUp; } if (NotFound) return -1; else return 0; } else return -1; } // Check duplicate int toBuild = 0; if (Repeatable.Contains(Gid)) { foreach (var x in CV.Buildings) { if (x.Key == Bid) continue; if (x.Value.Gid == Gid) if (Buildings.CheckLevelFull(x.Value.Gid, x.Value.Level, CV.isCapital)) { toBuild = 0; break; } else toBuild = x.Key; } if (toBuild != 0) return toBuild; else return 0; } // Check duplicate for non-repeatable foreach (var x in CV.Buildings) if (x.Value.Gid == Gid && x.Key != Bid) return -1; // Check depend if (!Buildings.Depends.ContainsKey(Gid)) return 0; bool gNotFound = false; foreach (var x in Buildings.Depends[Gid]) { bool NotFound = true; int canUp = 0; foreach (var y in CV.Buildings) if (x.Gid == y.Value.Gid) if (x.Level > y.Value.Level) canUp = y.Key; else { NotFound = false; break; } if (NotFound && canUp != 0) return canUp; gNotFound = gNotFound || NotFound; if (gNotFound) break; } return gNotFound ? -1 : 0; }
public void doTick() { if (!Monitor.TryEnter(Level2Lock)) { return; } try { foreach (var vid in TD.Villages.Keys) { TVillage CV = TD.Villages[vid]; if (CV.isVillageInitialized != 2) { continue; } List <int> status = new List <int>(); foreach (var task in CV.Queue) { if (task.Paused) { continue; } if (status.Contains(task.QueueGUID)) { continue; } else if (task.QueueGUID < 7) { status.Add(task.QueueGUID); } if (task.QueueGUID <= 1 && !TD.isRomans) { status.Add(1 - task.QueueGUID); } switch (task.GetType().Name) { case "BuildingQueue": if (CV.isBuildingInitialized == 0) { CV.InitializeBuilding(); continue; } else if (CV.isBuildingInitialized == 1) { continue; } break; case "DestroyQueue": if (CV.isDestroyInitialized == 0) { CV.InitializeDestroy(); continue; } else if (CV.isDestroyInitialized == 1) { continue; } break; case "ResearchQueue": if (CV.isUpgradeInitialized == 0) { CV.InitializeUpgrade(); continue; } else if (CV.isUpgradeInitialized == 1) { continue; } break; case "PartyQueue": break; case "TransferQueue": break; case "NpcTradeQueue": break; case "RaidQueue": if (CV.isTroopInitialized == 0) { CV.InitializeTroop(); continue; } break; case "AttackQueue": if (CV.isTroopInitialized == 0) { CV.InitializeTroop(); continue; } break; } if (task.CountDown <= 0) { task.Action(); } } for (int i = CV.Queue.Count - 1; i >= 0; i--) { if (CV.Queue[i].MarkDeleted) { CV.Queue.RemoveAt(i); TD.Dirty = true; } } } } catch (InvalidOperationException e) { // Good bye! Collection was modified; enumeration operation may not execute. DebugLog(e, DebugLevel.I); } try { if (Dirty) { DB.Instance.Snapshot(this); } if (TD.Dirty) { DB.Instance.Snapshot(TD); } } catch { } try { //AccountHack(); } catch { //DebugLog(e.ToString(), DebugLevel.I); } Monitor.Exit(Level2Lock); }
private void NewParseVillages(string data) { //string data = TravianData.Villages[VillageID].PageCache[TPageType.Dorf1].PageContent; if (data == null) return; int i; int Currid = 0; MatchCollection mc; mc = Regex.Matches(data, "newdid=(\\d*).*?>([^<]*?)</a>.*?\\((-?\\d*?)<.*?\">(-?\\d*?)\\)", RegexOptions.Singleline); /* * Groups: * [1]: is_default * [2]: village id * [3]: village name * [4&5]: position */ //int villagecount = mc.Count == 0 ? 1 : mc.Count; //if(villagecount <= LastVillageCount) // return -1; //int cnt = 0; data = this.pageQuerier.PageQuery(0, "spieler.php?uid=" + TD.UserID, null, true, true); if (data == null) return; if (mc.Count == 0) { Match m = Regex.Match(data, "karte.php\\?d=(\\d+)&c=.*?\">([^<]*)</a>.*?(</span>)?</td>"); if (TD.Villages.Count < 1) { TVillage tv = new TVillage() { Name = m.Groups[2].Value, Z = Convert.ToInt32(m.Groups[1].Value), isCapital = true, UpCall = this }; string viddata = this.pageQuerier.PageQuery(0, "dorf3.php", null, true, true); if (viddata == null) return; m = Regex.Match(viddata, "newdid=(\\d+)"); tv.ID = Convert.ToInt32(m.Groups[1].Value); TD.Villages[tv.ID] = tv; Currid = tv.ID; TD.Dirty = true; } } else { for (i = 0; i < mc.Count; i++) { Match m = mc[i]; int vid = Convert.ToInt32(m.Groups[1].Value); if (TD.Villages.ContainsKey(vid)) continue; TD.Villages[vid] = new TVillage() { ID = vid, Name = m.Groups[2].Value, X = Convert.ToInt32(m.Groups[3].Value), Y = Convert.ToInt32(m.Groups[4].Value), UpCall = this }; if (m.Groups[2].Value != "") Currid = vid; } } mc = Regex.Matches(data, "karte.php\\?d=(\\d+)&c=.*?\">([^<]*)</a>.*?(</span>)?</td"); int CapZ = 0; foreach (Match m in mc) { if (m.Groups[3].Value.Length > 0) CapZ = Convert.ToInt32(m.Groups[1].Value); } foreach (KeyValuePair<int, TVillage> x in TD.Villages) { if (x.Value.Z == CapZ) x.Value.isCapital = true; else x.Value.isCapital = false; } //LastVillageCount = villagecount; TD.Dirty = true; TD.ActiveDid = Currid; }