using System; using System.Collections.Generic; using System.Linq; namespace IdleMafiaBot { sealed partial class Bot { const bool KnocksOn = false; DateTime nextKnock; string knockHour; readonly HashSet knockTried = new HashSet(); readonly Dictionary knockTricked = new Dictionary(); bool knockSaid; void DoKnocks() { nextKnock = DateTime.UtcNow.AddMinutes(40); string hour = DateTime.UtcNow.ToString("yyyyMMddHH"); if (hour != knockHour) { knockHour = hour; knockTried.Clear(); } if (!game.OpenTab(Tab.Territory)) { nextKnock = DateTime.UtcNow.AddMinutes(10); return; } if (!game.MapAllFamilies()) { Log("Trick or Treat: the map's MY FAMILY filter didn't read - looked at again in 30 minutes"); nextKnock = DateTime.UtcNow.AddMinutes(30); return; } int noTabs = 0, lost = 0; for (int tries = 0; tries < 15; tries++) { var doors = game.MapDoorsDrawn(); if (doors == null && lost++ < 2) { if (game.ProfileShowing()) game.CloseProfile(); game.CloseDistrict(); if (game.OpenTab(Tab.Territory) && game.MapAllFamilies()) doors = game.MapDoorsDrawn(); } if (doors == null) { Log("Trick or Treat: the Territory page didn't read - looked at again in 10 minutes"); game.Snapshot("knock map unread", 60); nextKnock = DateTime.UtcNow.AddMinutes(10); return; } var open = doors.Where(d => !knockTried.Contains(d.Name)).ToList(); if (open.Count == 0) { Log("Trick or Treat: no door left to knock on in sight - looked at again in 20 minutes"); nextKnock = DateTime.UtcNow.AddMinutes(20); return; } var door = game.DoorsInReach(open).FirstOrDefault(); if (door == null) { game.Wait(3000); continue; } knockTried.Add(door.Name); if (game.OpenDoor(door) == null) continue; try { bool noTab; var t = game.OpenKnockTab(out noTab); if (noTab) { game.Snapshot("knock no halloween tab", 60); if (++noTabs < 3) continue; Log("Trick or Treat: no HALLOWEEN tab in 3 districts' windows - the event is over. Looked at again in 6 hours"); nextKnock = DateTime.UtcNow.AddHours(6); return; } if (t == null) continue; noTabs = 0; if (!knockSaid) { knockSaid = true; Log("Trick or Treat: the event is on - knocking on other families' doors with the free knocks"); } if (t.Knocks == 0) { KnockAgain(t); return; } if (t.Own || t.Used) continue; if (t.Knock == null) { Log("Trick or Treat: couldn't read " + door.Name + "'s HALLOWEEN tab - looked at again in 30 minutes"); game.Snapshot("knock tab unread", 60); nextKnock = DateTime.UtcNow.AddMinutes(30); return; } DateTime until; string family = Parse.Key(t.Owner); if (knockTricked.TryGetValue(family, out until) && DateTime.UtcNow < until) continue; var after = game.Knock(t); if (after == null) { Log("Trick or Treat: pressed KNOCK on " + door.Name + ", no result seen - looked at again in 30 minutes"); game.Snapshot("knock no result", 60); nextKnock = DateTime.UtcNow.AddMinutes(30); return; } if (after.Trick) { knockTricked[family] = DateTime.UtcNow.AddHours(6); Log("Trick or Treat: " + t.Owner + " tricked you at " + door.Name + " - left alone for 6 hours"); SnapshotOnce("trick or treat trick"); } else Log("Trick or Treat: " + t.Owner + "'s " + door.Name + " paid " + (after.Paid >= 0 ? after.Paid + " Candy" : "something") + (after.Candy >= 0 ? " (" + after.Candy + " in all)" : "")); if (after.Knocks == 0) { KnockAgain(after); return; } } finally { if (game.ProfileShowing()) game.CloseProfile(); game.CloseDistrict(); } } } void KnockAgain(KnockTab t) { int wait = t.NextSeconds > 0 ? t.NextSeconds + 30 * 60 : 40 * 60; nextKnock = DateTime.UtcNow.AddSeconds(wait); Log("Trick or Treat: no knocks left - back in " + wait / 60 + " minutes"); } } }