AFK Macro

Idle Mafia Macro/Source/src/Knocks.cs

Knocks.cs

Trick or Treat (October only) · 241 lines · 10 KB

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
namespace IdleMafiaBot
{
sealed class KnockTab
{
public string Owner = "";
public bool Own, Used, Treat, Trick, JustNow, Loading;
public OcrLine Knock;
public int Knocks = -1, NextSeconds = -1, Paid = -1, Candy = -1;
}
sealed class MapDoor
{
public string Name;
public Point At;
}
sealed partial class Game
{
static readonly Regex KnockCount = new Regex(@"(?:^|\s)([\dOoQ])\s*/\s*[5Ss](?:\s|$)");
static readonly Regex KnockDoor = new Regex(@"['’`]?S?['’`]?\s+DOOR\s*$", RegexOptions.IgnoreCase);
static readonly Regex KnockPaid = new Regex(@"\+\s*(\d[\d,]*)\s*CANDY", RegexOptions.IgnoreCase);
static readonly Regex KnockCandy = new Regex(@"^\s*(\d[\d,]*)\s*CANDY\s*$", RegexOptions.IgnoreCase);
internal static bool KnockButton(Frame f, OcrLine l)
{
string key = Parse.Key(l.Text);
return key.EndsWith("KNOCK") && key.Length <= 8 && l.CenterY > f.Height / 2 + 3 * l.Box.Height;
}
internal KnockTab ReadKnockTab(Frame f)
{
var lines = Ocr.Read(f, BigPopupArea(f), PopupScale(f), Prep.None);
var own = lines.FirstOrDefault(l => Parse.Key(l.Text).StartsWith("YOURFAMI") && Parse.Key(l.Text).EndsWith("DOOR"));
if (own == null && !lines.Any(l => Parse.Key(l.Text).StartsWith("KNOCKAND"))) return null;
var t = new KnockTab { Own = own != null };
var door = lines.FirstOrDefault(l => l != own && KnockDoor.IsMatch(l.Text));
if (door != null) t.Owner = KnockDoor.Replace(door.Text, "").Trim();
bool spent = false;
foreach (var l in lines)
{
string s = l.Text.Trim();
var m = KnockCount.Match(s);
if (m.Success) t.Knocks = int.Parse(m.Groups[1].Value.Replace('O', '0').Replace('o', '0').Replace('Q', '0'));
if (KnockButton(f, l)) t.Knock = l;
if (Parse.Has(s, "LOADING")) t.Loading = true;
if (Parse.Has(s, "NO KNOCKS LEFT")) spent = true;
if (Parse.Has(s, "next knock is ready")) { spent = true; if (t.NextSeconds <= 0) t.NextSeconds = Parse.Duration(s.TrimEnd('.', ' ')); }
if (Parse.Has(s, "KNOCKED THIS HOUR") || Parse.Has(s, "knock here again")) t.Used = true;
if (Regex.IsMatch(s, @"^\W*Treat\b", RegexOptions.IgnoreCase)) t.Treat = true;
if (Regex.IsMatch(s, @"^\W*Trick\b", RegexOptions.IgnoreCase)) t.Trick = true;
if (Parse.Has(s, "Just now")) t.JustNow = true;
if (Parse.Has(s, "Next in")) t.NextSeconds = Parse.Duration(s);
m = KnockPaid.Match(s);
if (m.Success) t.Paid = int.Parse(Parse.Digits(m.Groups[1].Value));
m = KnockCandy.Match(s);
if (m.Success) t.Candy = int.Parse(Parse.Digits(m.Groups[1].Value));
}
if (spent) t.Knocks = 0;
return t;
}
public bool MapAllFamilies()
{
for (int tries = 0; tries < 3; tries++)
{
OcrLine mine, reset;
bool on;
using (var f = Capture())
{
var lines = Ocr.Read(f, PageArea(f), PageScale(f), Prep.None);
mine = lines.FirstOrDefault(l => Parse.Key(l.Text) == "MYFAMIIY");
if (mine == null) return false;
on = lines.Any(l => Parse.Has(l.Text, "MATCHING")) || MatchingUnder(f, mine);
reset = lines.FirstOrDefault(l => Parse.Key(l.Text).StartsWith("RESETZOOM"));
}
if (!on)
{
if (reset != null) Press("RESET ZOOM", reset.CenterX, reset.CenterY, 1200);
return true;
}
Click(mine.CenterX, mine.CenterY, 1500);
}
return false;
}
public List<MapDoor> MapDoors()
{
using (var f = Capture()) return MapDoors(f);
}
public List<MapDoor> MapDoorsDrawn()
{
List<MapDoor> doors = null;
for (int look = 0; look < 8; look++)
{
if (look > 0) Wait(1000);
doors = MapDoors();
if (doors != null && doors.Count > 0) return doors;
}
return doors;
}
internal List<MapDoor> MapDoors(Frame f)
{
OcrLine cityBox, districtBox;
string city = null;
int top = 0, foot = 0;
var area = PageArea(f);
if (TerritoryBar(f, out cityBox, out districtBox))
{
city = Districts.Cities.FirstOrDefault(c => Parse.Key(cityBox.Text).StartsWith(Parse.Key(c)));
top = districtBox.Box.Bottom + 2 * Math.Max(8, cityBox.Box.Height);
foot = cityBox.Box.Y - cityBox.Box.Height;
}
if (city == null)
{
var mine = Ocr.Read(f, area, PageScale(f), Prep.None).FirstOrDefault(l => Parse.Key(l.Text) == "MYFAMIIY");
if (mine == null) return null;
int h = Math.Max(8, mine.Box.Height);
top = mine.Box.Bottom + 2 * h;
foot = area.Bottom - 6 * h;
}
var lines = new List<OcrLine>();
foreach (var s in new[] { PageScale(f), PageScale(f) + 1 })
lines.AddRange(Ocr.Read(f, area, s, Prep.None).Where(l => l.Box.Y >= top && l.CenterY + 2 * l.Box.Height < foot));
Func<string, IEnumerable<string>> named = c => lines.Select(l => { int no; string name; return CityDistrict(l.Text, c, out no, out name) ? name : null; }).Where(n => n != null).Distinct();
if (city == null)
{
city = Districts.Cities.OrderByDescending(c => named(c).Count()).First();
if (named(city).Count() < 3) return null;
}
var got = new List<MapDoor>();
foreach (var l in lines)
{
int no;
string name;
if (!CityDistrict(l.Text, city, out no, out name)) continue;
if (!got.Any(d => d.Name == name)) got.Add(new MapDoor { Name = name, At = new Point(l.CenterX, l.CenterY + 2 * l.Box.Height) });
}
return got;
}
public List<MapDoor> DoorsInReach(List<MapDoor> doors)
{
using (var f = Capture()) return doors.Where(d => !ToastOver(f, d.At)).ToList();
}
public DistrictWindow OpenDoor(MapDoor door)
{
NotDisconnected();
Click(door.At.X, door.At.Y, 1500);
for (int look = 0; look < 3; look++)
{
if (look > 0) Wait(700);
using (var f = Capture())
{
var w = ReadDistrictWindow(f);
if (w != null) return w;
}
}
return null;
}
internal OcrLine HalloweenTab(Frame f)
{
return Ocr.Read(f, BigPopupArea(f), PopupScale(f), Prep.None).FirstOrDefault(l => Parse.Key(l.Text).StartsWith("HAIIOWEEN"));
}
public KnockTab OpenKnockTab(out bool noTab)
{
noTab = false;
OcrLine tab = null;
for (int look = 0; look < 4 && tab == null; look++)
{
if (look > 0) Wait(700);
using (var f = Capture())
{
var seen = ReadKnockTab(f);
if (seen != null) return Settled(seen);
tab = HalloweenTab(f);
if (tab == null && CloseRulingFamily(f)) Wait(500);
}
}
if (tab == null) { noTab = true; return null; }
Press(tab, 900);
for (int look = 0; look < 4; look++)
{
if (look > 0) Wait(700);
using (var f = Capture())
{
var t = ReadKnockTab(f);
if (t != null) return Settled(t);
}
}
return null;
}
static bool KnockKnown(KnockTab t) { return t.Own || t.Used || t.Knock != null || t.Knocks == 0; }
KnockTab Settled(KnockTab t)
{
for (int look = 0; (look < 3 || (t.Loading && look < 14)) && !KnockKnown(t); look++)
{
Wait(700);
using (var f = Capture())
{
var again = ReadKnockTab(f);
if (again != null) t = again;
}
}
return t;
}
public KnockTab Knock(KnockTab tab)
{
Press(tab.Knock, 2000);
KnockTab used = null;
for (int look = 0; look < 12; look++)
{
if (look > 0) Wait(1000);
using (var f = Capture())
{
var t = ReadKnockTab(f);
if (t != null && t.JustNow) return t;
if (t != null && t.Used) used = t;
}
}
return used;
}
}
}