Skip to content

Instantly share code, notes, and snippets.

@paigeadelethompson
Created April 21, 2026 07:52
Show Gist options
  • Select an option

  • Save paigeadelethompson/17589d09e9e2c5ecc77ac901d4315bc6 to your computer and use it in GitHub Desktop.

Select an option

Save paigeadelethompson/17589d09e9e2c5ecc77ac901d4315bc6 to your computer and use it in GitHub Desktop.
5.21e5 card pickup for IRC
use strict;
use warnings;
use Irssi;
our $VERSION = '1.7';
our %IRSSI = (
authors => 'ChatGPT',
name => 'card_spam',
description => '5.21e5 card pickup spammer (white card tiles restored)',
license => 'Public Domain',
);
# IRC colors
my $WHITE_BG = "\x0300,00";
my $RED = "\x0304";
my $BLACK = "\x0301";
my $RESET = "\x0f";
my @suits = (
{ sym => "♠", color => $BLACK },
{ sym => "♣", color => $BLACK },
{ sym => "♥", color => $RED },
{ sym => "♦", color => $RED },
);
# joker removed
my @ranks = ("A", 2..10, "J", "Q", "K");
my $running = 0;
my $tag;
# tuning
my $LINE_WIDTH = 80;
my $LOGICAL_W = 7; # collision + visual width
my $MIN_GAP = 2;
my $MAX_CARDS = 3;
my $TICK_MS = 50;
my $BANNER_CHANCE = 0.08;
my @last_positions;
sub random_card {
my $s = $suits[int(rand(@suits))];
my $r = $ranks[int(rand(@ranks))];
# FIXED WIDTH LOGIC (handles 10 correctly)
my $rank_len = length($r);
my $gap = $LOGICAL_W - 1 - $rank_len;
$gap = 1 if $gap < 1;
my $text = $s->{sym} . (" " x $gap) . $r;
# RESTORED WHITE BACKGROUND (card tile look)
return $WHITE_BG . $s->{color} . $text . $RESET;
}
sub garish_banner {
my $msg = " 5.21e5 CARD PICKUP! ";
my @colors = (4, 7, 8, 9, 11, 12, 13);
my $out = "";
my $i = 0;
foreach my $ch (split //, $msg) {
my $fg = $colors[$i % @colors];
$out .= sprintf("\x03%02d%s", $fg, $ch);
$i++;
}
return $out . $RESET;
}
sub valid_position {
my ($pos, $current_ref) = @_;
for my $p (@$current_ref) {
return 0 if abs($p - $pos) < ($LOGICAL_W + $MIN_GAP);
}
for my $p (@last_positions) {
return 0 if abs($p - $pos) < ($LOGICAL_W + $MIN_GAP);
}
return 1;
}
sub pick_positions {
my $count = 1 + int(rand($MAX_CARDS));
my @pos;
for (1..$count) {
for (1..30) {
my $p = int(rand($LINE_WIDTH - $LOGICAL_W));
if (valid_position($p, \@pos)) {
push @pos, $p;
last;
}
}
}
return sort { $a <=> $b } @pos;
}
sub build_line {
my @pos = pick_positions();
@last_positions = @pos;
my $line = "";
my $cursor = 0;
for my $p (@pos) {
my $spaces = $p - $cursor;
$spaces = $MIN_GAP if $spaces < $MIN_GAP;
$line .= " " x $spaces;
$line .= random_card();
$cursor = $p + $LOGICAL_W;
}
return $line;
}
sub spam_tick {
my ($server, $target) = @_;
return unless $running;
return unless $server && $server->{connected};
if (rand() < $BANNER_CHANCE) {
$server->command("MSG $target " . garish_banner());
} else {
$server->command("MSG $target " . build_line());
}
}
sub cmd_cards {
my ($data, $server, $witem) = @_;
unless ($witem && $witem->{type} eq "CHANNEL") {
Irssi::print("Join a channel first.");
return;
}
if ($running) {
Irssi::timeout_remove($tag) if defined $tag;
$running = 0;
Irssi::print("5.21e5 card pickup stopped.");
return;
}
my $target = $witem->{name};
$running = 1;
$tag = Irssi::timeout_add($TICK_MS, sub {
spam_tick($server, $target);
}, undef);
Irssi::print("5.21e5 card pickup started.");
}
Irssi::command_bind('cards', 'cmd_cards');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment