Added scripts from C:\Users\ploet\Desktop\Habbo\Xabbo Scripte: - 39 KI/Chatbot scripts (ChatGPT, Gemini, Grok, DeepSeek, Ollama) - Game solvers (Domino, Dodgeball, Obsidian Maze, IceBall) - Collision avoidance bots (5 versions) - Plant/breeding automation (12 scripts) - Trading tools, packet debuggers, room utilities - Navigation & teleport helpers Removed: 9 files (3 empty, 2 trivial, 4 cross-duplicates) Updated README with full categorized index of all 230+ scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
226 lines
6.3 KiB
C#
226 lines
6.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
const int GAME_MIN_X = 9;
|
|
const int GAME_MAX_X = 28;
|
|
const int GAME_MIN_Y = 11;
|
|
const int GAME_MAX_Y = 30;
|
|
|
|
const int BLOCKED_MIN_X = 17;
|
|
const int BLOCKED_MAX_X = 20;
|
|
const int BLOCKED_MIN_Y = 19;
|
|
const int BLOCKED_MAX_Y = 22;
|
|
|
|
const int KIND_SNAKE = 7100;
|
|
const int KIND_FOOD = 5068;
|
|
|
|
const int CTRL_UP = 2147418172;
|
|
const int CTRL_RIGHT = 2147418173;
|
|
const int CTRL_DOWN = 2147418174;
|
|
const int CTRL_LEFT = 2147418175;
|
|
|
|
List<(int x, int y)> body = new List<(int x, int y)>();
|
|
HashSet<(int x, int y)> prevSnake = new HashSet<(int x, int y)>();
|
|
(int x, int y) head = (-1, -1);
|
|
string dir = "DOWN";
|
|
string targetDir = "";
|
|
DateTime lastCmd = DateTime.MinValue;
|
|
int length = 0;
|
|
|
|
int GetKind(dynamic item) { try { return (int)item.Kind; } catch { return -1; } }
|
|
|
|
bool IsWall(int x, int y) => x < GAME_MIN_X || x > GAME_MAX_X || y < GAME_MIN_Y || y > GAME_MAX_Y;
|
|
bool IsBlocked(int x, int y) => x >= BLOCKED_MIN_X && x <= BLOCKED_MAX_X && y >= BLOCKED_MIN_Y && y <= BLOCKED_MAX_Y;
|
|
|
|
bool Bad(int x, int y)
|
|
{
|
|
if (IsWall(x, y)) return true;
|
|
if (IsBlocked(x, y)) return true;
|
|
for (int i = 0; i < body.Count - 1; i++)
|
|
if (body[i].x == x && body[i].y == y) return true;
|
|
return false;
|
|
}
|
|
|
|
bool BadFull(int x, int y)
|
|
{
|
|
if (IsWall(x, y)) return true;
|
|
if (IsBlocked(x, y)) return true;
|
|
foreach (var p in body)
|
|
if (p.x == x && p.y == y) return true;
|
|
return false;
|
|
}
|
|
|
|
(int, int) Next(int x, int y, string d)
|
|
{
|
|
if (d == "UP") return (x, y - 1);
|
|
if (d == "DOWN") return (x, y + 1);
|
|
if (d == "LEFT") return (x - 1, y);
|
|
if (d == "RIGHT") return (x + 1, y);
|
|
return (x, y);
|
|
}
|
|
|
|
string Opp(string d) => d == "UP" ? "DOWN" : d == "DOWN" ? "UP" : d == "LEFT" ? "RIGHT" : "LEFT";
|
|
|
|
int Fill(int sx, int sy)
|
|
{
|
|
if (BadFull(sx, sy)) return 0;
|
|
var v = new HashSet<(int, int)> { (sx, sy) };
|
|
var q = new Queue<(int, int)>();
|
|
q.Enqueue((sx, sy));
|
|
int c = 0;
|
|
while (q.Count > 0 && c < 200)
|
|
{
|
|
var (x, y) = q.Dequeue();
|
|
c++;
|
|
foreach (var (nx, ny) in new[] { (x, y-1), (x, y+1), (x-1, y), (x+1, y) })
|
|
if (!v.Contains((nx, ny)) && !BadFull(nx, ny)) { v.Add((nx, ny)); q.Enqueue((nx, ny)); }
|
|
}
|
|
return c;
|
|
}
|
|
|
|
void Cmd(string d)
|
|
{
|
|
if (d == "UP") Send(Out["ClickFurni"], CTRL_UP, 0);
|
|
else if (d == "DOWN") Send(Out["ClickFurni"], CTRL_DOWN, 0);
|
|
else if (d == "LEFT") Send(Out["ClickFurni"], CTRL_LEFT, 0);
|
|
else if (d == "RIGHT") Send(Out["ClickFurni"], CTRL_RIGHT, 0);
|
|
lastCmd = DateTime.Now;
|
|
}
|
|
|
|
string Best(int hx, int hy, int fx, int fy, string cur)
|
|
{
|
|
string opp = Opp(cur);
|
|
var results = new List<(string d, bool safe, int dist, int space)>();
|
|
|
|
foreach (var d in new[] { "UP", "DOWN", "LEFT", "RIGHT" })
|
|
{
|
|
if (d == opp) continue;
|
|
var (nx, ny) = Next(hx, hy, d);
|
|
|
|
bool hitBody = false;
|
|
for (int i = 0; i < body.Count - 1; i++)
|
|
if (body[i].x == nx && body[i].y == ny) { hitBody = true; break; }
|
|
|
|
if (IsWall(nx, ny) || IsBlocked(nx, ny) || hitBody) continue;
|
|
|
|
int space = Fill(nx, ny);
|
|
int dist = Math.Abs(fx - nx) + Math.Abs(fy - ny);
|
|
bool safe = space >= length + 3;
|
|
|
|
results.Add((d, safe, dist, space));
|
|
}
|
|
|
|
if (results.Count == 0) return cur;
|
|
|
|
var safeOpts = results.Where(r => r.safe).ToList();
|
|
if (safeOpts.Count > 0)
|
|
return safeOpts.OrderBy(r => r.dist).First().d;
|
|
|
|
return results.OrderByDescending(r => r.space).First().d;
|
|
}
|
|
|
|
Log("═══════════════════════════════════════════");
|
|
Log(" SNAKE BOT V7 - Self Body Tracking");
|
|
Log("═══════════════════════════════════════════");
|
|
|
|
while (Run)
|
|
{
|
|
Delay(10);
|
|
|
|
var snake = new HashSet<(int x, int y)>();
|
|
foreach (var item in FloorItems)
|
|
{
|
|
if (item == null) continue;
|
|
int x = item.Location.X;
|
|
int y = item.Location.Y;
|
|
if (IsWall(x, y)) continue;
|
|
int k = GetKind(item);
|
|
if (k == KIND_SNAKE) snake.Add((x, y));
|
|
}
|
|
|
|
if (snake.Count == 0)
|
|
{
|
|
body.Clear();
|
|
head = (-1, -1);
|
|
continue;
|
|
}
|
|
|
|
length = snake.Count;
|
|
|
|
var newP = snake.Except(prevSnake).ToList();
|
|
var removed = prevSnake.Except(snake).ToList();
|
|
bool moved = newP.Count == 1;
|
|
|
|
if (moved)
|
|
{
|
|
var nh = newP[0];
|
|
if (head.x != -1)
|
|
{
|
|
int dx = nh.x - head.x;
|
|
int dy = nh.y - head.y;
|
|
if (dy == -1) dir = "UP";
|
|
else if (dy == 1) dir = "DOWN";
|
|
else if (dx == -1) dir = "LEFT";
|
|
else if (dx == 1) dir = "RIGHT";
|
|
}
|
|
head = nh;
|
|
|
|
body.Insert(0, head);
|
|
while (body.Count > length) body.RemoveAt(body.Count - 1);
|
|
|
|
targetDir = "";
|
|
}
|
|
else if (prevSnake.Count == 0)
|
|
{
|
|
head = snake.OrderByDescending(p => p.y).First();
|
|
dir = "UP";
|
|
body = snake.OrderByDescending(p => p.y).ToList();
|
|
Log($"[INIT] Len:{length} Head:X{head.x},Y{head.y}");
|
|
}
|
|
|
|
prevSnake = new HashSet<(int x, int y)>(snake);
|
|
|
|
if (head.x == -1) continue;
|
|
|
|
int fx = -1, fy = -1;
|
|
foreach (var item in FloorItems)
|
|
{
|
|
if (item == null) continue;
|
|
if (GetKind(item) == KIND_FOOD)
|
|
{
|
|
fx = item.Location.X;
|
|
fy = item.Location.Y;
|
|
break;
|
|
}
|
|
}
|
|
if (fx == -1) continue;
|
|
|
|
if (moved || targetDir == "")
|
|
{
|
|
targetDir = Best(head.x, head.y, fx, fy, dir);
|
|
if (targetDir != dir)
|
|
Log($"[{length}] X{head.x},Y{head.y} {dir}->{targetDir} F:X{fx},Y{fy}");
|
|
}
|
|
|
|
var (nx, ny) = Next(head.x, head.y, dir);
|
|
bool danger = IsWall(nx, ny) || IsBlocked(nx, ny);
|
|
for (int i = 0; i < body.Count - 1 && !danger; i++)
|
|
if (body[i].x == nx && body[i].y == ny) danger = true;
|
|
|
|
if (danger)
|
|
{
|
|
targetDir = Best(head.x, head.y, fx, fy, dir);
|
|
Cmd(targetDir);
|
|
Delay(3);
|
|
Cmd(targetDir);
|
|
Delay(3);
|
|
Cmd(targetDir);
|
|
Log($"[!!!] X{head.x},Y{head.y} DANGER! ->{targetDir}");
|
|
}
|
|
else if ((DateTime.Now - lastCmd).TotalMilliseconds > 20)
|
|
{
|
|
Cmd(targetDir);
|
|
}
|
|
}
|