xabbo-scripts/Flood-IT [28.12.25] V1.0.csx
Administrator 7bfc390ed6 Initial commit: 68 Xabbo Scripter scripts
Habbo Hotel automation scripts including:
- Game solvers (Snake, Color Puzzle, Tetris, Flappy Bird, Flood-IT)
- Room utilities (Autogate, One-Way Door, Furni Scanner)
- Bot tools (Heal Bot, Pet Trainer, User Collector)
- Trading & economy (Furni-Matic, Seed Trade, Trade Spam)

Cleaned up: removed 5 duplicates and 2 broken scripts,
renamed 37 gibberish filenames to descriptive names.
2026-03-16 09:38:59 +01:00

245 lines
7.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
const int CLICK_DELAY = 2500;
const int GAME_MIN_X = 9;
const int GAME_MAX_X = 26;
const int GAME_MIN_Y = 12;
const int GAME_MAX_Y = 29;
const int GRID_W = 18;
const int GRID_H = 18;
const int TOTAL = 324;
const int KIND_TILE = 3666;
Dictionary<int, int> tileIdByColor = new Dictionary<int, int>();
int[,] grid = new int[GRID_W, GRID_H];
int GetState(dynamic item) { try { return int.Parse(item.State?.ToString() ?? "0"); } catch { return 0; } }
int GetId(dynamic item) { try { return (int)item.Id; } catch { return 0; } }
int GetKind(dynamic item) { try { return (int)item.Kind; } catch { return -1; } }
void ReadGrid()
{
Array.Clear(grid, 0, grid.Length);
tileIdByColor.Clear();
foreach (var item in FloorItems)
{
if (item == null) continue;
if (GetKind(item) != KIND_TILE) continue;
int x = item.Location.X, y = item.Location.Y;
if (x < GAME_MIN_X || x > GAME_MAX_X || y < GAME_MIN_Y || y > GAME_MAX_Y) continue;
int gx = x - GAME_MIN_X, gy = GAME_MAX_Y - y;
int state = GetState(item), id = GetId(item);
if (gx >= 0 && gx < GRID_W && gy >= 0 && gy < GRID_H)
{
grid[gx, gy] = state;
if (!tileIdByColor.ContainsKey(state)) tileIdByColor[state] = id;
}
}
}
HashSet<(int,int)> Flood(HashSet<(int,int)> area, int color)
{
var result = new HashSet<(int,int)>(area);
var q = new Queue<(int,int)>();
foreach (var p in area) q.Enqueue(p);
while (q.Count > 0)
{
var (x, y) = q.Dequeue();
foreach (var (nx, ny) in new[]{(x-1,y),(x+1,y),(x,y-1),(x,y+1)})
{
if (nx < 0 || nx >= GRID_W || ny < 0 || ny >= GRID_H) continue;
if (result.Contains((nx,ny))) continue;
if (grid[nx,ny] == color) { result.Add((nx,ny)); q.Enqueue((nx,ny)); }
}
}
return result;
}
HashSet<(int,int)> InitArea()
{
var area = new HashSet<(int,int)>{(0,0)};
return Flood(area, grid[0,0]);
}
HashSet<int> BorderColors(HashSet<(int,int)> area)
{
var c = new HashSet<int>();
foreach (var (x,y) in area)
{
if (x > 0 && !area.Contains((x-1,y))) c.Add(grid[x-1,y]);
if (x < GRID_W-1 && !area.Contains((x+1,y))) c.Add(grid[x+1,y]);
if (y > 0 && !area.Contains((x,y-1))) c.Add(grid[x,y-1]);
if (y < GRID_H-1 && !area.Contains((x,y+1))) c.Add(grid[x,y+1]);
}
return c;
}
HashSet<int> RemainingColors(HashSet<(int,int)> area)
{
var colors = new HashSet<int>();
for (int x = 0; x < GRID_W; x++)
for (int y = 0; y < GRID_H; y++)
if (!area.Contains((x,y))) colors.Add(grid[x,y]);
return colors;
}
int CountRegions(HashSet<(int,int)> area)
{
var visited = new bool[GRID_W, GRID_H];
foreach (var (x,y) in area) visited[x,y] = true;
int regions = 0;
for (int sx = 0; sx < GRID_W; sx++)
{
for (int sy = 0; sy < GRID_H; sy++)
{
if (visited[sx,sy]) continue;
regions++;
var q = new Queue<(int,int)>();
q.Enqueue((sx,sy));
visited[sx,sy] = true;
int c = grid[sx,sy];
while (q.Count > 0)
{
var (x,y) = q.Dequeue();
foreach (var (nx,ny) in new[]{(x-1,y),(x+1,y),(x,y-1),(x,y+1)})
{
if (nx < 0 || nx >= GRID_W || ny < 0 || ny >= GRID_H) continue;
if (visited[nx,ny]) continue;
if (grid[nx,ny] == c) { visited[nx,ny] = true; q.Enqueue((nx,ny)); }
}
}
}
}
return regions;
}
int Heuristic(HashSet<(int,int)> area)
{
var remaining = RemainingColors(area);
int regions = CountRegions(area);
return Math.Max(remaining.Count, (regions + 1) / 2);
}
bool EliminatesColor(HashSet<(int,int)> area, int color)
{
var newArea = Flood(area, color);
for (int x = 0; x < GRID_W; x++)
for (int y = 0; y < GRID_H; y++)
if (!newArea.Contains((x,y)) && grid[x,y] == color) return false;
return true;
}
int Eval(HashSet<(int,int)> area, int depth, int alpha)
{
if (area.Count == TOTAL) return 1000 - depth;
if (depth <= 0) return area.Count - Heuristic(area) * 10;
var borders = BorderColors(area);
int best = -999;
var moves = borders.Select(c => {
var next = Flood(area, c);
bool elim = EliminatesColor(area, c);
return (c, next.Count - area.Count, elim, next);
}).OrderByDescending(m => m.Item3 ? 1000 : 0)
.ThenByDescending(m => m.Item2).ToList();
foreach (var (c, gain, elim, next) in moves)
{
int score = Eval(next, depth - 1, best);
if (score > best) best = score;
if (best >= alpha) break;
}
return best;
}
(int color, int score) BestMove(HashSet<(int,int)> area, int depth)
{
var borders = BorderColors(area);
int bestC = 0, bestS = -9999;
var moves = borders.Select(c => {
var next = Flood(area, c);
bool elim = EliminatesColor(area, c);
return (c, next.Count - area.Count, elim, next);
}).OrderByDescending(m => m.Item3 ? 1000 : 0)
.ThenByDescending(m => m.Item2).ToList();
foreach (var (c, gain, elim, next) in moves)
{
int score;
if (next.Count == TOTAL) score = 10000;
else score = Eval(next, depth - 1, bestS) + (elim ? 50 : 0);
if (score > bestS) { bestS = score; bestC = c; }
}
return (bestC, bestS);
}
List<int> Solve()
{
var moves = new List<int>();
var area = InitArea();
while (area.Count < TOTAL && moves.Count < 32)
{
int remaining = TOTAL - area.Count;
int depth = remaining > 200 ? 3 : remaining > 100 ? 4 : remaining > 50 ? 5 : 6;
var (c, s) = BestMove(area, depth);
if (c == 0) break;
moves.Add(c);
area = Flood(area, c);
}
return moves;
}
void Click(int color)
{
foreach (var item in FloorItems)
{
if (item == null) continue;
if (GetKind(item) != KIND_TILE) continue;
int x = item.Location.X, y = item.Location.Y;
if (x < GAME_MIN_X || x > GAME_MAX_X || y < GAME_MIN_Y || y > GAME_MAX_Y) continue;
int state = GetState(item);
if (state == color)
{
Send(Out["ClickFurni"], (int)item.Id, 0);
return;
}
}
}
Log("═══════════════════════════════════════════");
Log(" FLOOD-IT BOT - RESEARCH BASED");
Log("═══════════════════════════════════════════");
while (Run)
{
ReadGrid();
var area = InitArea();
Log($"Start: {area.Count}/{TOTAL}");
if (area.Count == TOTAL) { Log("COMPLETE!"); Delay(2000); continue; }
Log("Solving...");
var sw = System.Diagnostics.Stopwatch.StartNew();
var solution = Solve();
sw.Stop();
Log($"Solution: {string.Join(",", solution)} ({solution.Count} moves) in {sw.ElapsedMilliseconds}ms");
foreach (var c in solution)
{
Click(c);
Log($"Click {c}");
Delay(CLICK_DELAY);
}
Delay(1000);
}