xabbo-scripts/Scripts/Flappy Bird [28.12.25] V1.0.csx
Administrator 7a548130a3 Move all scripts into Scripts/ subfolder
Keeps the repo root clean - only README.md visible on landing page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 09:49:37 +01:00

165 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
const int BIRD_X = 17;
const int BIRD_KIND = 9039;
const int PIPE_KIND = 5986;
const int CONTROL_ID = 630985637;
int GetKind(dynamic item) { try { return (int)item.Kind; } catch { return -1; } }
void Flap() { Send(Out["UseFurniture"], CONTROL_ID, 0); }
int GetBirdY()
{
foreach (var item in FloorItems)
{
if (item == null) continue;
if (GetKind(item) != BIRD_KIND) continue;
if (item.Location.X == BIRD_X) return item.Location.Y;
}
return -1;
}
(int gapMin, int gapMax, int pipeX) FindNextPipe()
{
var pipesByX = new Dictionary<int, List<int>>();
foreach (var item in FloorItems)
{
if (item == null) continue;
if (GetKind(item) != PIPE_KIND) continue;
int x = item.Location.X, y = item.Location.Y;
if (!pipesByX.ContainsKey(x)) pipesByX[x] = new List<int>();
pipesByX[x].Add(y);
}
var ahead = pipesByX.Keys.Where(x => x >= BIRD_X).OrderBy(x => x).ToList();
if (ahead.Count == 0) return (-1, -1, 99);
int closestX = ahead.First();
var wallYs = new HashSet<int>(pipesByX[closestX]);
int bestStart = -1, bestEnd = -1, bestSize = 0, gapStart = -1;
for (int y = 7; y <= 24; y++)
{
if (!wallYs.Contains(y)) { if (gapStart < 0) gapStart = y; }
else
{
if (gapStart >= 0)
{
int size = (y - 1) - gapStart + 1;
if (size > bestSize) { bestSize = size; bestStart = gapStart; bestEnd = y - 1; }
}
gapStart = -1;
}
}
if (gapStart >= 0)
{
int size = 24 - gapStart + 1;
if (size > bestSize) { bestStart = gapStart; bestEnd = 24; }
}
return (bestStart, bestEnd, closestX);
}
Log("FLAPPY BOT V19 - SILENT MODE"); // Output spam reduced
long lastFlap = 0;
int tick = 0;
int lastY = -1;
while (Run)
{
tick++;
int birdY = GetBirdY();
if (birdY < 0) { Delay(25); continue; }
var (gapMin, gapMax, pipeX) = FindNextPipe();
int dist = pipeX - BIRD_X;
long now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
bool shouldFlap = false;
string reason = "";
// MINIMUM COOLDOWN = 120ms
int cooldown = 120;
if (gapMin > 0 && dist <= 15)
{
bool aboveGap = birdY < gapMin;
bool belowGap = birdY > gapMax;
int gapCenter = (gapMin + gapMax) / 2;
int afterFlap = birdY - 3;
bool wouldOvershoot = afterFlap <= gapMin;
if (belowGap)
{
shouldFlap = true;
reason = "BELOW";
}
else if (aboveGap)
{
shouldFlap = false;
reason = "ABOVE";
}
else
{
if (dist <= 4)
{
if (birdY >= gapMax && !wouldOvershoot)
{
shouldFlap = true;
reason = "CLOSE-SAVE";
}
else { reason = "CLOSE-OK"; }
}
else if (dist <= 10)
{
if (birdY > gapMax && !wouldOvershoot)
{
shouldFlap = true;
reason = "MED-LOW";
}
else if (birdY > gapCenter + 2 && !wouldOvershoot)
{
shouldFlap = true;
reason = "MED-ADJ";
}
else { reason = "MED-OK"; }
}
else
{
if (birdY > gapCenter + 3 && !wouldOvershoot)
{
shouldFlap = true;
reason = "FAR-LOW";
}
else { reason = "FAR-OK"; }
}
}
}
else
{
if (birdY > 16) { shouldFlap = true; reason = "HOVER"; }
}
if (birdY >= 22) { shouldFlap = true; reason = "EMERG"; }
if (birdY <= 8) shouldFlap = false;
int dy = lastY > 0 ? birdY - lastY : 0;
string gapStr = gapMin > 0 ? $"gap={gapMin}-{gapMax}" : "NO_GAP";
if (shouldFlap && (now - lastFlap) >= cooldown)
{
// Nur noch Loggen wenn er wirklich springt
Log($">>> FLAP! Y={birdY} | d={dist} {gapStr} | {reason}");
Flap();
lastFlap = now;
}
// Der Code-Block, der sonst hier war (else if dist <= 3...), wurde entfernt.
// Dadurch hört der Spam auf.
lastY = birdY;
Delay(25);
}