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>
486 lines
13 KiB
C#
486 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Globalization;
|
|
|
|
public struct Point : IEquatable<Point>
|
|
{
|
|
public int X { get; }
|
|
public int Y { get; }
|
|
public Point(int x, int y) { X = x; Y = y; }
|
|
public static implicit operator Point((int x, int y) tuple) => new Point(tuple.x, tuple.y);
|
|
public bool Equals(Point other) => X == other.X && Y == other.Y;
|
|
public override bool Equals(object obj) => obj is Point other && Equals(other);
|
|
public override int GetHashCode() => HashCode.Combine(X, Y);
|
|
public static bool operator ==(Point left, Point right) => left.Equals(right);
|
|
public static bool operator !=(Point left, Point right) => !(left == right);
|
|
public override string ToString() => $"({X},{Y})";
|
|
}
|
|
|
|
public class Tile
|
|
{
|
|
public int X { get; set; }
|
|
public int Y { get; set; }
|
|
public double Z { get; set; }
|
|
public Point XY => new Point(X, Y);
|
|
public Tile(int x, int y, double z = 0.0) { X = x; Y = y; Z = z; }
|
|
}
|
|
|
|
public class Duck
|
|
{
|
|
public long id { get; set; }
|
|
public Point pos { get; set; }
|
|
public Point lastpos { get; set; }
|
|
public Point vel { get; set; }
|
|
public DateTime lastseen { get; set; }
|
|
public Queue<Point> trail { get; set; } = new Queue<Point>(10);
|
|
public double spd { get; set; }
|
|
}
|
|
|
|
HashSet<Point> tiles = new HashSet<Point> {
|
|
(13,13),(14,13),(15,13),(16,13),(17,13),(18,13),(19,13),(20,13),(21,13),(22,13),(23,13),(24,13),(25,13),
|
|
(13,14),(17,14),(21,14),(25,14),(13,15),(14,15),(15,15),(17,15),(18,15),(20,15),(21,15),(23,15),(24,15),
|
|
(25,15),(13,16),(15,16),(18,16),(20,16),(23,16),(25,16),(13,17),(15,17),(16,17),(17,17),(18,17),(19,17),
|
|
(20,17),(21,17),(22,17),(23,17),(25,17),(13,18),(15,18),(19,18),(23,18),(25,18),(13,19),(14,19),(15,19),
|
|
(17,19),(18,19),(19,19),(20,19),(21,19),(23,19),(24,19),(25,19), (13,20),(15,20),(16,20),(17,20),(21,20),
|
|
(22,20),(23,20),(25,20),(12,21),(13,21),(17,21),(18,21),(19,21),(20,21),(21,21),(25,21),(26,21),(13,22),
|
|
(15,22),(16,22),(17,22),(21,22),(22,22),(23,22),(25,22), (13,23),(14,23),(15,23),(17,23),(18,23),(19,23),
|
|
(20,23),(21,23),(23,23),(24,23),(25,23),(13,24),(15,24),(19,24),(23,24),(25,24),(13,25),(15,25),(16,25),
|
|
(17,25),(18,25),(19,25),(20,25),(21,25),(22,25),(23,25),(25,25), (13,26),(15,26),(18,26),(20,26),(23,26),
|
|
(25,26), (13,27),(14,27),(15,27),(17,27),(18,27),(20,27),(21,27),(23,27),(24,27),(25,27),(13,28),(17,28),
|
|
(21,28),(25,28), (13,29),(14,29),(15,29),(16,29),(17,29),(18,29),(19,29),(20,29),(21,29),(22,29),(23,29),
|
|
(24,29),(25,29)
|
|
};
|
|
|
|
Dictionary<Point, List<Point>> adj = new Dictionary<Point, List<Point>>();
|
|
Point[] dirs = { (0,1), (0,-1), (1,0), (-1,0), (1,1), (1,-1), (-1,1), (-1,-1) };
|
|
|
|
foreach(var t in tiles)
|
|
{
|
|
var n = new List<Point>();
|
|
foreach(var d in dirs)
|
|
{
|
|
Point p = new Point(t.X + d.X, t.Y + d.Y);
|
|
if(tiles.Contains(p)) n.Add(p);
|
|
}
|
|
adj[t] = n;
|
|
}
|
|
|
|
Dictionary<long, Duck> ducks = new Dictionary<long, Duck>();
|
|
Tile tgt = null;
|
|
Point lastcmd = default(Point);
|
|
DateTime cmdtime = DateTime.MinValue;
|
|
Point prev = default(Point);
|
|
Point curr = default(Point);
|
|
Queue<Point> hist = new Queue<Point>(5);
|
|
int stuck = 0;
|
|
HashSet<Point> danger = new HashSet<Point>();
|
|
|
|
Point dest = default(Point);
|
|
bool forcedest = false;
|
|
DateTime desttime = DateTime.MinValue;
|
|
|
|
Point getpos()
|
|
{
|
|
if (Self == null) return default(Point);
|
|
if (tgt != null) return tgt.XY;
|
|
if (!lastcmd.Equals(default(Point)) && (DateTime.UtcNow - cmdtime).TotalMilliseconds < 250)
|
|
return lastcmd;
|
|
if (Self.Location != null) return new Point(Self.Location.X, Self.Location.Y);
|
|
return default(Point);
|
|
}
|
|
|
|
void go(int x, int y)
|
|
{
|
|
Move(x, y);
|
|
lastcmd = new Point(x, y);
|
|
cmdtime = DateTime.UtcNow;
|
|
tgt = null;
|
|
}
|
|
|
|
HashSet<Point> predict(int frames)
|
|
{
|
|
var zones = new HashSet<Point>();
|
|
|
|
foreach(var d in ducks.Values)
|
|
{
|
|
zones.Add(d.pos);
|
|
|
|
if(!d.vel.Equals(default(Point)))
|
|
{
|
|
for(int i = 1; i <= frames; i++)
|
|
{
|
|
Point pred = new Point(
|
|
d.pos.X + d.vel.X * i,
|
|
d.pos.Y + d.vel.Y * i
|
|
);
|
|
if(tiles.Contains(pred))
|
|
zones.Add(pred);
|
|
}
|
|
}
|
|
|
|
if(frames >= 1 && adj.ContainsKey(d.pos))
|
|
{
|
|
foreach(var n in adj[d.pos])
|
|
zones.Add(n);
|
|
}
|
|
|
|
if(frames >= 2)
|
|
{
|
|
foreach(var d1 in dirs)
|
|
{
|
|
Point p1 = new Point(d.pos.X + d1.X, d.pos.Y + d1.Y);
|
|
if(tiles.Contains(p1))
|
|
{
|
|
zones.Add(p1);
|
|
foreach(var d2 in dirs)
|
|
{
|
|
Point p2 = new Point(p1.X + d2.X, p1.Y + d2.Y);
|
|
if(tiles.Contains(p2))
|
|
zones.Add(p2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return zones;
|
|
}
|
|
|
|
Point findsafe(Point me, HashSet<Point> bad)
|
|
{
|
|
if(!bad.Any()) return tiles.First();
|
|
|
|
double best = double.MinValue;
|
|
Point spot = me;
|
|
|
|
foreach(var t in tiles)
|
|
{
|
|
if(bad.Contains(t)) continue;
|
|
|
|
double score = 0;
|
|
|
|
double mindist = double.MaxValue;
|
|
foreach(var b in bad)
|
|
{
|
|
double d = Math.Abs(t.X - b.X) + Math.Abs(t.Y - b.Y);
|
|
mindist = Math.Min(mindist, d);
|
|
score += d;
|
|
}
|
|
|
|
score += mindist * 100;
|
|
|
|
if(adj.ContainsKey(t))
|
|
{
|
|
int exits = adj[t].Count(n => !bad.Contains(n));
|
|
score += exits * 10;
|
|
}
|
|
|
|
double dist = Math.Abs(t.X - me.X) + Math.Abs(t.Y - me.Y);
|
|
score -= dist * 0.5;
|
|
|
|
if(score > best)
|
|
{
|
|
best = score;
|
|
spot = t;
|
|
}
|
|
}
|
|
|
|
return spot;
|
|
}
|
|
|
|
Point pathto(Point me, Point goal, HashSet<Point> d1, HashSet<Point> d2, HashSet<Point> d3)
|
|
{
|
|
if(!adj.ContainsKey(me)) return me;
|
|
|
|
if(hist.Count >= 3)
|
|
{
|
|
var last3 = hist.TakeLast(3).ToArray();
|
|
if(last3[0] == last3[2] && last3[0] != last3[1])
|
|
{
|
|
stuck++;
|
|
if(stuck > 2)
|
|
{
|
|
var esc = adj[me]
|
|
.Where(n => !d1.Contains(n))
|
|
.OrderBy(n => Guid.NewGuid())
|
|
.FirstOrDefault();
|
|
if(!esc.Equals(default(Point)))
|
|
{
|
|
stuck = 0;
|
|
return esc;
|
|
}
|
|
}
|
|
}
|
|
else stuck = 0;
|
|
}
|
|
|
|
double best = double.MinValue;
|
|
Point move = me;
|
|
|
|
foreach(var n in adj[me])
|
|
{
|
|
if(d1.Contains(n)) continue;
|
|
|
|
double score = 0;
|
|
|
|
if(d2.Contains(n)) score -= 800;
|
|
if(d3.Contains(n)) score -= 400;
|
|
|
|
double dist = Math.Abs(n.X - goal.X) + Math.Abs(n.Y - goal.Y);
|
|
score -= dist * 100;
|
|
|
|
foreach(var duck in ducks.Values)
|
|
{
|
|
double dd = Math.Abs(n.X - duck.pos.X) + Math.Abs(n.Y - duck.pos.Y);
|
|
score += dd * 10;
|
|
}
|
|
|
|
if(adj.ContainsKey(n))
|
|
{
|
|
int safe = adj[n].Count(x => !d1.Contains(x));
|
|
score += safe * 20;
|
|
|
|
if(safe == 0 && d2.Contains(n))
|
|
score -= 2000;
|
|
}
|
|
|
|
if(!prev.Equals(default(Point)) && n.Equals(prev))
|
|
score -= 50;
|
|
|
|
if(score > best)
|
|
{
|
|
best = score;
|
|
move = n;
|
|
}
|
|
}
|
|
|
|
return move;
|
|
}
|
|
|
|
Point getmove(Point me, Point goal, HashSet<Point> d1, HashSet<Point> d2, HashSet<Point> d3)
|
|
{
|
|
if(!adj.ContainsKey(me)) return me;
|
|
|
|
if(hist.Count >= 3)
|
|
{
|
|
var last3 = hist.TakeLast(3).ToArray();
|
|
if(last3[0] == last3[2] && last3[0] != last3[1])
|
|
{
|
|
stuck++;
|
|
if(stuck > 1)
|
|
{
|
|
var any = adj[me]
|
|
.Where(n => !d1.Contains(n))
|
|
.OrderBy(n => d2.Contains(n) ? 1 : 0)
|
|
.FirstOrDefault();
|
|
if(!any.Equals(default(Point)))
|
|
{
|
|
stuck = 0;
|
|
return any;
|
|
}
|
|
}
|
|
}
|
|
else stuck = 0;
|
|
}
|
|
|
|
double best = double.MinValue;
|
|
Point move = me;
|
|
|
|
foreach(var n in adj[me])
|
|
{
|
|
if(d1.Contains(n)) continue;
|
|
|
|
if(!prev.Equals(default(Point)) && n.Equals(prev))
|
|
continue;
|
|
|
|
double score = 0;
|
|
|
|
if(d2.Contains(n)) score -= 1000;
|
|
if(d3.Contains(n)) score -= 500;
|
|
|
|
double dist = Math.Abs(n.X - goal.X) + Math.Abs(n.Y - goal.Y);
|
|
score -= dist * 10;
|
|
|
|
foreach(var duck in ducks.Values)
|
|
{
|
|
double dd = Math.Abs(n.X - duck.pos.X) + Math.Abs(n.Y - duck.pos.Y);
|
|
score += dd * 20;
|
|
}
|
|
|
|
if(adj.ContainsKey(n))
|
|
{
|
|
int exits = adj[n].Count(x => !d1.Contains(x) && !d2.Contains(x));
|
|
score += exits * 50;
|
|
}
|
|
|
|
if(score > best)
|
|
{
|
|
best = score;
|
|
move = n;
|
|
}
|
|
}
|
|
|
|
return move;
|
|
}
|
|
|
|
OnIntercept(Out["MoveAvatar"], e => {
|
|
var pkt = e.Packet;
|
|
int x = pkt.ReadInt();
|
|
int y = pkt.ReadInt();
|
|
|
|
dest = new Point(x, y);
|
|
forcedest = true;
|
|
desttime = DateTime.UtcNow;
|
|
});
|
|
|
|
OnEnteredRoom(e => {
|
|
ducks.Clear();
|
|
hist.Clear();
|
|
prev = default(Point);
|
|
stuck = 0;
|
|
forcedest = false;
|
|
dest = default(Point);
|
|
});
|
|
|
|
OnIntercept(In["WiredMovements"], e => {
|
|
var pkt = e.Packet;
|
|
int cnt = pkt.ReadInt();
|
|
|
|
for(int i = 0; i < cnt; i++)
|
|
{
|
|
pkt.ReadInt();
|
|
int fx = pkt.ReadInt();
|
|
int fy = pkt.ReadInt();
|
|
int tx = pkt.ReadInt();
|
|
int ty = pkt.ReadInt();
|
|
pkt.ReadString();
|
|
pkt.ReadString();
|
|
int id = pkt.ReadInt();
|
|
pkt.ReadInt();
|
|
pkt.ReadInt();
|
|
|
|
long fid = id;
|
|
Point newp = new Point(tx, ty);
|
|
Point oldp = new Point(fx, fy);
|
|
|
|
if(!ducks.ContainsKey(fid))
|
|
{
|
|
ducks[fid] = new Duck { id = fid };
|
|
}
|
|
|
|
var d = ducks[fid];
|
|
d.lastpos = d.pos;
|
|
d.pos = newp;
|
|
d.vel = new Point(tx - fx, ty - fy);
|
|
d.lastseen = DateTime.UtcNow;
|
|
|
|
d.trail.Enqueue(newp);
|
|
if(d.trail.Count > 10) d.trail.Dequeue();
|
|
|
|
if((d.lastseen - DateTime.UtcNow).TotalSeconds < 1)
|
|
{
|
|
d.spd = Math.Sqrt(Math.Pow(d.vel.X, 2) + Math.Pow(d.vel.Y, 2));
|
|
}
|
|
}
|
|
});
|
|
|
|
OnIntercept(In["UserUpdate"], e => {
|
|
if(Self == null) return;
|
|
|
|
var pkt = e.Packet;
|
|
int num = pkt.ReadInt();
|
|
|
|
for(int i = 0; i < num; i++)
|
|
{
|
|
int idx = pkt.ReadInt();
|
|
int x = pkt.ReadInt();
|
|
int y = pkt.ReadInt();
|
|
string z = pkt.ReadString();
|
|
pkt.ReadInt();
|
|
pkt.ReadInt();
|
|
string act = pkt.ReadString();
|
|
|
|
if(idx == Self.Index)
|
|
{
|
|
prev = curr;
|
|
curr = new Point(x, y);
|
|
|
|
hist.Enqueue(curr);
|
|
if(hist.Count > 5) hist.Dequeue();
|
|
|
|
if(forcedest && curr.Equals(dest))
|
|
{
|
|
forcedest = false;
|
|
}
|
|
|
|
if(act.Contains("/mv"))
|
|
{
|
|
var parts = act.Split(new[] {' ', '/', ','}, StringSplitOptions.RemoveEmptyEntries);
|
|
if(parts.Length >= 4 && parts[0] == "mv")
|
|
{
|
|
if(int.TryParse(parts[1], out int mx) &&
|
|
int.TryParse(parts[2], out int my) &&
|
|
double.TryParse(parts[3], NumberStyles.Any, CultureInfo.InvariantCulture, out double mz))
|
|
{
|
|
tgt = new Tile(mx, my, mz);
|
|
lastcmd = default(Point);
|
|
}
|
|
}
|
|
}
|
|
else if(act.EndsWith("//") && !act.Contains("/mv"))
|
|
{
|
|
tgt = null;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
while(Run)
|
|
{
|
|
try
|
|
{
|
|
Point me = getpos();
|
|
if(me.Equals(default(Point))) { Delay(20); continue; }
|
|
|
|
if(ducks.Any() || forcedest)
|
|
{
|
|
var d1 = predict(1);
|
|
var d2 = predict(2);
|
|
var d3 = predict(3);
|
|
|
|
Point goal;
|
|
Point next = me;
|
|
|
|
if(forcedest && tiles.Contains(dest))
|
|
{
|
|
if((DateTime.UtcNow - desttime).TotalSeconds > 30)
|
|
{
|
|
forcedest = false;
|
|
goal = findsafe(me, d1);
|
|
next = getmove(me, goal, d1, d2, d3);
|
|
}
|
|
else
|
|
{
|
|
goal = dest;
|
|
next = pathto(me, goal, d1, d2, d3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goal = findsafe(me, d1);
|
|
next = getmove(me, goal, d1, d2, d3);
|
|
}
|
|
|
|
if(!next.Equals(me))
|
|
{
|
|
go(next.X, next.Y);
|
|
}
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
}
|
|
|
|
Delay(20);
|
|
} |