Skip to content

Instantly share code, notes, and snippets.

@rdavisau
Last active March 4, 2022 20:40
Show Gist options
  • Save rdavisau/b6e23ca79fe12b54de4e to your computer and use it in GitHub Desktop.
Save rdavisau/b6e23ca79fe12b54de4e to your computer and use it in GitHub Desktop.

Revisions

  1. rdavisau revised this gist Mar 2, 2016. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion internet-is-down.linq
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ INSTRUCTIONS:
    1. open chrome, get the dinosaur 'no internet' page happening
    2. we need to tell the script where the dinosaur is; we use a highly technical approach -
    putting the mouse just behind the bottom left of the dinosaur and then pressing enter in LINQPad.
    putting the mouse just behind the bottom left* of the dinosaur and then pressing enter in LINQPad.
    when the first if statement is `if (true)`, the script waits for you to press enter in the readline box and takes
    the current cursor position. so the approach is
    @@ -40,6 +40,9 @@ INSTRUCTIONS:
    4. it's not a very smart script
    note: doesn't work with font scaling - i guess the dimensions change. some of the nugets/references probably aren't needed
    * i 'think' it's the bottom left - if the boundaries around the dinosaur look like this, it is correct: http://i.imgur.com/choOOMU.png
    */


  2. rdavisau created this gist Mar 2, 2016.
    276 changes: 276 additions & 0 deletions internet-is-down.linq
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,276 @@
    <Query Kind="Program">
    <Reference>&lt;RuntimeDirectory&gt;\System.Windows.Forms.dll</Reference>
    <Reference>&lt;RuntimeDirectory&gt;\System.Security.dll</Reference>
    <Reference>&lt;RuntimeDirectory&gt;\System.Configuration.dll</Reference>
    <Reference>&lt;RuntimeDirectory&gt;\Accessibility.dll</Reference>
    <Reference>&lt;RuntimeDirectory&gt;\System.Runtime.Serialization.Formatters.Soap.dll</Reference>
    <Reference>&lt;RuntimeDirectory&gt;\System.Deployment.dll</Reference>
    <NuGetReference>DynamicLINQ</NuGetReference>
    <NuGetReference>DynamicQuery</NuGetReference>
    <NuGetReference>Newtonsoft.Json</NuGetReference>
    <NuGetReference>Rx-Main</NuGetReference>
    <Namespace>System.Diagnostics</Namespace>
    <Namespace>System.Drawing</Namespace>
    <Namespace>System.Drawing.Imaging</Namespace>
    <Namespace>System.Reactive</Namespace>
    <Namespace>System.Reactive.Linq</Namespace>
    <Namespace>System.Reactive.Subjects</Namespace>
    <Namespace>System.Runtime.InteropServices</Namespace>
    <Namespace>System.Windows.Forms</Namespace>
    <Namespace>Newtonsoft.Json</Namespace>
    <Namespace>System.Threading.Tasks</Namespace>
    </Query>

    /*
    INSTRUCTIONS:
    1. open chrome, get the dinosaur 'no internet' page happening
    2. we need to tell the script where the dinosaur is; we use a highly technical approach -
    putting the mouse just behind the bottom left of the dinosaur and then pressing enter in LINQPad.
    when the first if statement is `if (true)`, the script waits for you to press enter in the readline box and takes
    the current cursor position. so the approach is
    - press play on LINQPad, click inside the readline box
    - move your cursor to the correct position behind the dinosaur
    - press enter
    that mouse position is saved so for as long as you don't move the chrome window you can change `if (true)` to `if (false)`
    and it will keep using the old position. alternatively, experiment with different positions to improve the dinosaur's performance
    3. that's pretty much it - once location is set the script will press space when it 'thinks' there's a threat nearby
    4. it's not a very smart script
    note: doesn't work with font scaling - i guess the dimensions change. some of the nugets/references probably aren't needed
    */


    [DllImport("user32.dll")]
    static extern bool GetCursorPos(ref Point lpPoint);

    [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
    async void Main()
    {
    Point monitorLocation = new Point();

    if (true)
    {
    Console.ReadLine();
    GetCursorPos(ref monitorLocation);
    File.WriteAllText("cursor.txt", JsonConvert.SerializeObject(monitorLocation));
    }
    else monitorLocation = JsonConvert.DeserializeObject<Point>(File.ReadAllText("cursor.txt"));

    var bounds = new {
    TopPoint = new Point(monitorLocation.X, monitorLocation.Y - 150),
    ZeroPoint = new Point(0,0),
    Size = new Size(600,150),
    };

    var barrierPoint = new {
    Top = new Point(65,bounds.Size.Height),
    Bottom = new Point(65, bounds.Size.Height-50)
    };

    var groundPoint = new {
    Start = new Point(0, bounds.Size.Height - 15),
    End = new Point(bounds.Size.Width, bounds.Size.Height - 15)
    };

    var topOfDinoPoint = new {
    Start = new Point(0, bounds.Size.Height - 50),
    End = new Point(bounds.Size.Width, bounds.Size.Height - 50)
    };

    var centerOfDino = new Point(barrierPoint.Top.X - 15 , barrierPoint.Top.Y + ((barrierPoint.Bottom.Y - barrierPoint.Top.Y)/2) - 17 );
    var cactusColor = ColorTranslator.FromHtml("#535353");

    var content = new DumpContainer();
    var stats = new { DinoCam = content, CURRENT_STATUS = new DumpContainer(), DistanceToThreat = new DumpContainer() }.Dump(); // , ThreatWidth = new DumpContainer()}.Dump();

    var p = new Pen(Color.Green, 1f);
    var redP = new Pen(Color.Red) { DashPattern = new [] { 2.0f, 2.0f } };
    var alphaRedP = new SolidBrush(Color.FromArgb(150, Color.Red));

    var distanceToSearch = 400 ;
    var minY = topOfDinoPoint.Start.Y;
    var maxY = groundPoint.Start.Y;

    Thread.CurrentThread.Priority = ThreadPriority.Highest;

    Bitmap b = null;

    var needToJump = false; var actionString = "CHILLING"; var distToThreatString = "ALL CLEAR BABY"; var threatWidthString = "";
    var threatWidth = 0;
    var threatDistance = 0;

    Action<Graphics> updateDinoCam = g =>
    {
    stats.CURRENT_STATUS.Content = needToJump ? "JUMPING" : "CHILLING";
    stats.DistanceToThreat.Content = threatDistance == 0 ? distToThreatString : threatDistance.ToString();

    g.DrawLine(p, barrierPoint.Top, barrierPoint.Bottom ); // draw dino collision point
    g.DrawLine(p, groundPoint.Start, groundPoint.End); // draw ground bound
    g.DrawLine(p, topOfDinoPoint.Start, topOfDinoPoint.End); // draw dino head bound

    content.Content = b;
    };

    while (true)
    {
    b = new Bitmap(bounds.Size.Width, bounds.Size.Height);
    using (var g = Graphics.FromImage(b))
    {
    g.CopyFromScreen(bounds.TopPoint, bounds.ZeroPoint, bounds.Size); // snap screen

    // find the nearest cactus
    var threat = Enumerable.Range(barrierPoint.Top.X, distanceToSearch)
    .SelectMany(j=> Enumerable.Range(minY, maxY - minY).Select(i=> new { X = j, Y = i }))
    .FirstOrDefault(pt => b.GetPixel(pt.X,pt.Y) == cactusColor);

    if (threat == null) { updateDinoCam(g); continue; } // no cactus, nothing to do..

    // find end of cactus
    var threatPt = new Point(threat.X, threat.Y);
    var lastCactusPixel =
    Enumerable.Range(threat.X, 100)
    .Where(x => x > 0 && x < bounds.Size.Width)
    .Select(x => new { Point = new Point(x, threat.Y), IsCactus = b.GetPixel(x, threat.Y) == cactusColor })
    .FirstWithLookhead(10, (pix, nextPixels) => pix.IsCactus && nextPixels.All(ppx=> !ppx.IsCactus));

    threatWidth = lastCactusPixel.Point.X - threatPt.X;
    threatDistance = threat.X - barrierPoint.Top.X;

    // highlight threat on dinocam
    g.DrawLine(redP, centerOfDino, threatPt);
    g.DrawLine(redP, centerOfDino, new Point(lastCactusPixel.Point.X, lastCactusPixel.Point.Y));
    g.FillRectangle(alphaRedP, new Rectangle(new Point(threatPt.X, threatPt.Y -5) , new Size(threatWidth, 10)));

    // if we need to jump, Lets Do That
    needToJump = IsThisTooCloseForComfort(threatWidth, threatDistance);
    if (needToJump)
    Keyboard.HoldKey((byte)Keys.Space, 300); // JUMP!!!!

    updateDinoCam(g);
    }
    }
    }

    public bool IsThisTooCloseForComfort (int threatWidth, int distance)
    {
    // small cactus
    if (threatWidth < 25 && (distance < 115))
    return true;
    else if (threatWidth < 40 && (distance < 105))
    return true;
    // medium cactus
    else if (threatWidth < 55 && (distance < 95))
    return true;
    // large cactus
    else if (threatWidth < 100 && (distance < 75))
    return true;

    return false;
    }

    // Define other methods and classes here
    public static class Ext
    {
    public static T FirstWithLookhead<T>(this IEnumerable<T> items, int lookAhead, Func<T, List<T>, bool> predicate)
    {
    var ahead = new List<T>();

    foreach (var item in items)
    {
    ahead.Add(item);
    if (ahead.Count > lookAhead)
    {
    var theItem = ahead[0];
    ahead.Remove(theItem);

    var result = predicate(theItem, ahead);
    if (result)
    return theItem;
    }
    }

    while (ahead.Count > 0)
    {
    var theItem = ahead[0];
    ahead.Remove(theItem);

    var result = predicate(theItem, ahead);
    if (result)
    return theItem;
    }

    return default(T);
    }

    public static T Do<T>(this T obj, Action<T> action)
    {
    action(obj);
    return obj;
    }

    public static Color Dump(this Color colour, string caption = null)
    {
    Util.RawHtml(String.Format("<div style='text-align:center;display:block;width:20px;height:20px;background-color:#ff6600'>hi</div>"))
    .Dump(caption);
    return colour;
    }
    public static object DivForColor(this Color colour)
    {
    return Util.RawHtml(String.Format("<div style='text-align:center;display:block;width:20px;height:20px;background-color:{0}'></div>",
    ColorTranslator.ToHtml(colour)));
    }

    static Bitmap screenPixel = new Bitmap(1,1, PixelFormat.Format32bppArgb);

    public static Color GetColorAt(Point location)
    {
    using (Graphics gdest = Graphics.FromImage(screenPixel))
    {
    using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
    {
    IntPtr hSrcDC = gsrc.GetHdc();
    IntPtr hDC = gdest.GetHdc();
    int retval = UserQuery.BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy);
    gdest.ReleaseHdc();
    gsrc.ReleaseHdc();
    }
    }


    return screenPixel.GetPixel(0, 0);
    }

    public static bool IsColorWithinRange(Color c, Point p, int range)
    {
    var xs = Enumerable.Range(0,range).Select(x=> p.X + x);
    var ys = Enumerable.Range(range/2,(int)(range/1.5) ).Select(y=> p.Y + y);

    return

    xs.SelectMany(x=> ys.Select(y=> new Point(x,y)))
    .Any(pt=> GetColorAt(pt) == c);

    }


    }

    public class Keyboard
    {
    [DllImport("user32.dll", SetLastError = true)]
    static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
    const int PauseBetweenStrokes = 50;
    const int KEY_DOWN_EVENT = 0x0001; //Key down flag
    const int KEY_UP_EVENT = 0x0002; //Key up flag

    public static void HoldKey(byte key, int duration)
    {
    keybd_event(key, 0, KEY_DOWN_EVENT, 0);
    Task.Delay(duration).ContinueWith(_=> keybd_event(key, 0, KEY_UP_EVENT, 0));
    Task.Delay(50).Wait();
    }
    }