AFK Macro

Idle Mafia Macro/Source/src/Turns.cs

Turns.cs

Several accounts in turns · 73 lines · 2 KB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace IdleMafiaBot
{
sealed class Turns
{
const double WaitPointsPerMinute = 10;
sealed class Waiter { public DateTime Since, Seen; public int Need; }
readonly object gate = new object();
readonly List<Bot> order;
readonly Dictionary<Bot, Waiter> waiting = new Dictionary<Bot, Waiter>();
Bot holder;
public Turns(IEnumerable<Bot> bots) { order = bots.ToList(); }
internal static double Score(int need, double waitedMinutes) { return Math.Max(0, need) + waitedMinutes * WaitPointsPerMinute; }
public bool Take(Bot b, int need, Func<bool> stopped, int maxMs)
{
int end = Environment.TickCount + maxMs;
lock (gate)
while (true)
{
if (stopped()) throw new StopException();
if (!order.Contains(b)) return true;
Waiter me;
if (!waiting.TryGetValue(b, out me)) waiting[b] = me = new Waiter { Since = DateTime.UtcNow };
me.Need = need;
me.Seen = DateTime.UtcNow;
if (holder == null && Next() == b) { holder = b; waiting.Remove(b); return true; }
int left = end - Environment.TickCount;
if (left <= 0) return false;
Monitor.Wait(gate, Math.Min(500, left));
}
}
Bot Next()
{
var now = DateTime.UtcNow;
return waiting.Where(w => now - w.Value.Seen < TimeSpan.FromMinutes(1))
.OrderByDescending(w => Score(w.Value.Need, (now - w.Value.Since).TotalMinutes)).ThenBy(w => w.Value.Since).First().Key;
}
public bool Wanted(Bot b) { lock (gate) return waiting.Keys.Any(o => o != b); }
public void Pass(Bot b)
{
lock (gate)
{
if (holder == b) holder = null;
Monitor.PulseAll(gate);
}
}
public void Leave(Bot b)
{
lock (gate)
{
if (!order.Remove(b)) return;
waiting.Remove(b);
if (holder == b) holder = null;
Monitor.PulseAll(gate);
}
}
}
}