Skip to content

Instantly share code, notes, and snippets.

@lycis
Created February 6, 2025 13:57
Show Gist options
  • Save lycis/5cc245dacdbc644fde4bd7047d639cc9 to your computer and use it in GitHub Desktop.
Save lycis/5cc245dacdbc644fde4bd7047d639cc9 to your computer and use it in GitHub Desktop.
ANSI True Color Support in SilberlandLD mudlib (vs. Tamedhon base)
// file: /secure/simul_efun.c
// ...
/// This function maps an RGB value (each 0..255) to the nearest ANSI color.
string rgb_to_ansi(int r, int g, int b) {
// Define an array of mappings.
// The RGB values here are chosen as “representatives” of the ANSI colors.
// You can adjust these if you have a different idea of what each ANSI code should represent.
mapping *colors = ({
([ "ansi": ANSI_BLACK, "r": 0, "g": 0, "b": 0 ]),
([ "ansi": ANSI_RED, "r": 128, "g": 0, "b": 0 ]),
([ "ansi": ANSI_GREEN, "r": 0, "g": 128, "b": 0 ]),
([ "ansi": ANSI_BROWN, "r": 128, "g": 128, "b": 0 ]), // brown/dark yellow
([ "ansi": ANSI_BLUE, "r": 0, "g": 0, "b": 128 ]),
([ "ansi": ANSI_PURPLE, "r": 128, "g": 0, "b": 128 ]),
([ "ansi": ANSI_CYAN, "r": 0, "g": 128, "b": 128 ]),
([ "ansi": ANSI_GREY, "r": 192, "g": 192, "b": 192 ]),
([ "ansi": ANSI_WHITE, "r": 255, "g": 255, "b": 255 ])
});
// We'll use the squared Euclidean distance for comparison
int best_dist = 1<<30; // a very high value
string best_ansi = ANSI_WHITE; // default fallback
foreach(mapping col in colors) {
int dr = r - col["r"];
int dg = g - col["g"];
int db = b - col["b"];
int dist = dr * dr + dg * dg + db * db;
if(dist < best_dist) {
best_dist = dist;
best_ansi = col["ansi"];
}
}
return best_ansi;
}
// file: /std/player/base.c
// ...
void create() {
// ...
Set(P_ANSI_TRUE_COLOR, SAVE, F_MODE_AS);
// ...
}
// ...
// The rainbow is divided into 6 segments of 10 steps each.
// For simplicity some boundary colors are repeated.
#define ANSI_RAINBOW \
/* Segment 1: Red -> Yellow */ \
ANSI_TRUE_COLOR(255,0,0) + "█" + \
ANSI_TRUE_COLOR(255,28,0) + "█" + \
ANSI_TRUE_COLOR(255,57,0) + "█" + \
ANSI_TRUE_COLOR(255,85,0) + "█" + \
ANSI_TRUE_COLOR(255,113,0) + "█" + \
ANSI_TRUE_COLOR(255,142,0) + "█" + \
ANSI_TRUE_COLOR(255,170,0) + "█" + \
ANSI_TRUE_COLOR(255,198,0) + "█" + \
ANSI_TRUE_COLOR(255,227,0) + "█" + \
ANSI_TRUE_COLOR(255,255,0) + "█" + \
/* Segment 2: Yellow -> Green */ \
ANSI_TRUE_COLOR(255,255,0) + "█" + \
ANSI_TRUE_COLOR(227,255,0) + "█" + \
ANSI_TRUE_COLOR(198,255,0) + "█" + \
ANSI_TRUE_COLOR(170,255,0) + "█" + \
ANSI_TRUE_COLOR(142,255,0) + "█" + \
ANSI_TRUE_COLOR(113,255,0) + "█" + \
ANSI_TRUE_COLOR(85,255,0) + "█" + \
ANSI_TRUE_COLOR(57,255,0) + "█" + \
ANSI_TRUE_COLOR(28,255,0) + "█" + \
ANSI_TRUE_COLOR(0,255,0) + "█" + \
/* Segment 3: Green -> Cyan */ \
ANSI_TRUE_COLOR(0,255,0) + "█" + \
ANSI_TRUE_COLOR(0,255,28) + "█" + \
ANSI_TRUE_COLOR(0,255,57) + "█" + \
ANSI_TRUE_COLOR(0,255,85) + "█" + \
ANSI_TRUE_COLOR(0,255,113) + "█" + \
ANSI_TRUE_COLOR(0,255,142) + "█" + \
ANSI_TRUE_COLOR(0,255,170) + "█" + \
ANSI_TRUE_COLOR(0,255,198) + "█" + \
ANSI_TRUE_COLOR(0,255,227) + "█" + \
ANSI_TRUE_COLOR(0,255,255) + "█" + \
/* Segment 4: Cyan -> Blue */ \
ANSI_TRUE_COLOR(0,255,255) + "█" + \
ANSI_TRUE_COLOR(0,227,255) + "█" + \
ANSI_TRUE_COLOR(0,198,255) + "█" + \
ANSI_TRUE_COLOR(0,170,255) + "█" + \
ANSI_TRUE_COLOR(0,142,255) + "█" + \
ANSI_TRUE_COLOR(0,113,255) + "█" + \
ANSI_TRUE_COLOR(0,85,255) + "█" + \
ANSI_TRUE_COLOR(0,57,255) + "█" + \
ANSI_TRUE_COLOR(0,28,255) + "█" + \
ANSI_TRUE_COLOR(0,0,255) + "█" + \
/* Segment 5: Blue -> Magenta */ \
ANSI_TRUE_COLOR(0,0,255) + "█" + \
ANSI_TRUE_COLOR(28,0,255) + "█" + \
ANSI_TRUE_COLOR(57,0,255) + "█" + \
ANSI_TRUE_COLOR(85,0,255) + "█" + \
ANSI_TRUE_COLOR(113,0,255) + "█" + \
ANSI_TRUE_COLOR(142,0,255) + "█" + \
ANSI_TRUE_COLOR(170,0,255) + "█" + \
ANSI_TRUE_COLOR(198,0,255) + "█" + \
ANSI_TRUE_COLOR(227,0,255) + "█" + \
ANSI_TRUE_COLOR(255,0,255) + "█" + \
/* Segment 6: Magenta -> Red */ \
ANSI_TRUE_COLOR(255,0,255) + "█" + \
ANSI_TRUE_COLOR(255,0,227) + "█" + \
ANSI_TRUE_COLOR(255,0,198) + "█" + \
ANSI_TRUE_COLOR(255,0,170) + "█" + \
ANSI_TRUE_COLOR(255,0,142) + "█" + \
ANSI_TRUE_COLOR(255,0,113) + "█" + \
ANSI_TRUE_COLOR(255,0,85) + "█" + \
ANSI_TRUE_COLOR(255,0,57) + "█" + \
ANSI_TRUE_COLOR(255,0,28) + "█" + \
ANSI_TRUE_COLOR(255,0,0) + "█" + \
ANSI_PLAIN
static int stty(string str)
{
if (str!=TTY_DUMB&&str!=TTY_VT100&&str!=TTY_ANSI&&str!="reset"&&str!="truecolor")
{
write("Syntax: stty dumb|vt100|ansi oder reset\n");
write("Wenn du 'ansi' verwendest kannst du mit 'stty truecolor' den ANSI True Color Modus ein- oder ausschalten.\n");
}
if(str == "reset") {
printf("\e[30;47m\e[0mDieser Text sollte lesbar sein!\n");
return 1;
}
if(str == "truecolor") {
if(Query(P_TTY) != "ansi") {
write("ANSI True Color benötigt 'stty ansi' aktiviert.");
return 1;
}
SetProp(P_ANSI_TRUE_COLOR, !QueryProp(P_ANSI_TRUE_COLOR));
int tc = QueryProp(P_ANSI_TRUE_COLOR);
write("ANSI True Color: "+(tc?"ein":"aus")+"\n");
if(tc) {
write("\nTrueColor Support aktiviert:\n" + ANSI_RAINBOW + "\n" + "Wenn du die Farben sehen kannst, dann unterstützt dein Terminal TrueColor.\n");
}
return 1;
}
write("TTY steht jetzt auf "+SetProp(P_TTY,str)+".\n");
if(str == "ansi" || str == "vt100") {
printf("Terminal Test:\n");
printf("VT100: \e[1mfett\e[0m \e[4munterstrichen\e[0m "+
"\e[5mblinkend\e[0m \e[7minvers\e[0m\n");
if(str == "ansi") {
int fg, bg;
printf("ANSI Farben und VT100 Attribute:\n");
for(fg = 30; fg <= 37; fg++) {
for(bg = 40; bg <= 47; bg++) {
printf("\e[%d;%dm\e[1m@\e[0m", fg, bg);
printf("\e[%d;%dm\e[4m@\e[0m", fg, bg);
printf("\e[%d;%dm\e[5m@\e[0m", fg, bg);
printf("\e[%d;%dm\e[7m@\e[0m", fg, bg);
}
printf("\n");
}
printf("Sollte dieser Text hier nicht richtig lesbar\n"
"sein, benutze das Kommando stty reset!\n");
} else {
SetProp(P_ANSI_TRUE_COLOR, 0); // immer ausschalten, wenn kein ansi terminal
}
}
return 1;
}
// ...
string _query_color(object ob, string prop)
{
mixed s1;
if (!interactive(ob)) return "";
s1=ob->QueryProp(prop);
// true color support
if(pointerp(s1)) {
if(sizeof(s1) != 3) {
tell_object(this_object(), "Warnung: Ungültige Farbeinstellung für "+prop+" zurückgesetzt auf 'plain'.\n");
return ANSI_PLAIN;
}
int r = s1[0];
int g = s1[1];
int b = s1[2];
if(QueryProp(P_ANSI_TRUE_COLOR)) {
return ANSI_TRUE_COLOR(s1[0], s1[1], s1[2]);
} else {
return rgb_to_ansi(r, g, b);
}
}
// ...
}
// ...
int *hex_to_rgb(string hex) {
int r, g, b;
// Validate input
if (!stringp(hex) || strlen(hex) != 7 || hex[0] != '#') {
return 0; // Invalid format
}
// Convert hex to decimal values
r = to_int("0x" + hex[1..2]);
g = to_int("0x" + hex[3..4]);
b = to_int("0x" + hex[5..6]);
return ({ r, g, b });
}
/* Setzt Farbe fuer Properties P_COLOR_EXIT,
* P_COLOR_COMMUNICATION, P_COLOR_INFORM
*/
static void setcolor(string farbe, string prop, string name) {
if(farbe[0..0] == "#") {
int *hexcol = hex_to_rgb(farbe);
if(!pointerp(hexcol)) {
write(sprintf("Ungültige hex-Farbe. Format: #rrggbb\n", hexcol));
return;
}
// true color support
SetProp(prop, hexcol);
} else {
switch(farbe){
case "schwarz": SetProp(prop, 1);break;
case "rot": SetProp(prop, 2);break;
case "grün": SetProp(prop, 3);break;
// ...
default: write("Farbe "+farbe+" nicht erkannt.\n");
farbliste();
return;
}
}
}
// file: /sys/ansi.h
//...
#ifndef __ANSI__H_
#define __ANSI__H_
// ...
// True Color support
#define ANSI_TRUE_COLOR(r,g,b) "\e[38;2;"+r+";"+g+";"+b+"m" // Select RGB foreground color
#define ANSI_TRUE_COLOR_BG(r,g,b) "\e[48;"+r+";"+g+";"+b+"m" // Select RGB background color
// TTY constants
#define TTY_DUMB "dumb"
#define TTY_VT100 "vt100"
#define TTY_ANSI "ansi"
#define P_ANSI_TRUE_COLOR "tty_ansi_true_color" // 1 = ansi true color support enabled
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment