<RuntimeDirectory>\System.Windows.Forms.dll <RuntimeDirectory>\System.Security.dll <RuntimeDirectory>\System.Configuration.dll <RuntimeDirectory>\Accessibility.dll <RuntimeDirectory>\System.Runtime.Serialization.Formatters.Soap.dll <RuntimeDirectory>\System.Deployment.dll DynamicLINQ DynamicQuery Newtonsoft.Json Rx-Main System.Diagnostics System.Drawing System.Drawing.Imaging System.Reactive System.Reactive.Linq System.Reactive.Subjects System.Runtime.InteropServices System.Windows.Forms Newtonsoft.Json System.Threading.Tasks /* 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(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 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(this IEnumerable items, int lookAhead, Func, bool> predicate) { var ahead = new List(); 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(this T obj, Action action) { action(obj); return obj; } public static Color Dump(this Color colour, string caption = null) { Util.RawHtml(String.Format("
hi
")) .Dump(caption); return colour; } public static object DivForColor(this Color colour) { return Util.RawHtml(String.Format("
", 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(); } }