feat(sandbox): add mouton program

This commit is contained in:
Guillaume ARM 2026-06-11 20:59:50 +02:00
parent a452335b33
commit 97efdcf638
3 changed files with 255 additions and 2 deletions

View File

@ -6,7 +6,7 @@
"trapos-net": "0.3.0", "trapos-net": "0.3.0",
"trapos-ui": "0.2.2", "trapos-ui": "0.2.2",
"trapos-ai": "0.6.9", "trapos-ai": "0.6.9",
"trapos-sandbox": "0.2.1", "trapos-sandbox": "0.2.2",
"trapos": "0.8.11" "trapos": "0.8.11"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "trapos-sandbox", "name": "trapos-sandbox",
"version": "0.2.1", "version": "0.2.2",
"description": "TrapOS sandbox programs for ccpm experiments and Lua learning", "description": "TrapOS sandbox programs for ccpm experiments and Lua learning",
"dependencies": ["trapos-core"], "dependencies": ["trapos-core"],
"files": [ "files": [
@ -8,6 +8,7 @@
"apis/libmcpcomputer.lua", "apis/libmcpcomputer.lua",
"programs/carre.lua", "programs/carre.lua",
"programs/creeper.lua", "programs/creeper.lua",
"programs/mouton.lua",
"programs/mcp-computer.lua", "programs/mcp-computer.lua",
"servers/mcp-computer-server.lua" "servers/mcp-computer-server.lua"
], ],

252
programs/mouton.lua Normal file
View File

@ -0,0 +1,252 @@
local createVersion = require('/apis/libversion');
local args = table.pack(...);
-- Tete de mouton style Minecraft: un carre de laine avec un visage carre au centre.
-- Les lettres sont des pixels de couleur. Le point est le fond.
local SHEEP = {
'..WWWWWWWWWWWW..',
'.WWwwWWwwWWwwWW.',
'WWwwWWwwWWwwWWww',
'Wwwwwwwwwwwwwwww',
'WWwwKKKKKKKKwwWW',
'WwwwKkkkkkkKwwww',
'WWwwKfkkkkfKwwWW',
'WwwwKfkkkkfKwwww',
'WWwwKkkMMkkKwwWW',
'WwwwKkkmmkkKwwww',
'WWwwKkkkkkkKwwWW',
'WwwwKKKKKKKKwwww',
'WWwwwwwwwwwwwwWW',
'WwWWwwWWwwWWwwWw',
'.WWwwWWwwWWwwWW.',
'..WWWWWWWWWWWW..',
};
local THEMES = {
classic = {
title = 'Mouton Minecraft',
background = colors.black,
text = colors.white,
palette = {
['.'] = colors.black,
W = colors.white,
w = colors.lightGray,
K = colors.gray,
k = colors.lightGray,
f = colors.black,
M = colors.gray,
m = colors.black,
},
},
rose = {
title = 'Mouton Rose',
background = colors.black,
text = colors.pink,
palette = {
['.'] = colors.black,
W = colors.pink,
w = colors.magenta,
K = colors.white,
k = colors.lightGray,
f = colors.black,
M = colors.pink,
m = colors.black,
},
},
nuage = {
title = 'Mouton Nuage',
background = colors.lightBlue,
text = colors.white,
palette = {
['.'] = colors.lightBlue,
W = colors.white,
w = colors.lightGray,
K = colors.gray,
k = colors.white,
f = colors.black,
M = colors.lightGray,
m = colors.black,
},
},
arcenciel = {
title = 'Mouton Arc-en-ciel',
background = colors.black,
text = colors.yellow,
rainbow = true,
palette = {
['.'] = colors.black,
K = colors.white,
k = colors.lightGray,
f = colors.black,
M = colors.pink,
m = colors.black,
},
},
};
local THEME_NAMES = { 'classic', 'rose', 'nuage', 'arcenciel' };
local RAINBOW = {
colors.red,
colors.orange,
colors.yellow,
colors.lime,
colors.cyan,
colors.blue,
colors.purple,
colors.magenta,
};
local function printUsage()
print('mouton usage:');
print();
print(' mouton');
print(' mouton <theme>');
print(' mouton --theme <theme>');
print(' mouton --random');
print(' mouton --version');
print(' mouton --help');
print();
print('themes: classic, rose, nuage, arcenciel');
end
local function drawRun(x, y, len, color)
term.setBackgroundColor(color);
term.setCursorPos(x, y);
term.write(string.rep(' ', len));
end
local function themeNamesText()
return table.concat(THEME_NAMES, ', ');
end
local function parseArgs(argv)
local selectedTheme = 'classic';
local selectedExplicitly = false;
local randomTheme = false;
local index = 1;
while index <= argv.n do
local arg = argv[index];
if arg == '--random' or arg == '-random' then
if selectedExplicitly then
return nil, '--random ne peut pas etre combine avec un theme';
end
randomTheme = true;
elseif arg == '--theme' or arg == '-theme' then
if randomTheme or selectedExplicitly then
return nil, arg .. ' ne peut pas etre combine avec un autre theme';
end
index = index + 1;
selectedTheme = argv[index];
if selectedTheme == nil then
return nil, 'theme manquant apres ' .. arg;
end
selectedExplicitly = true;
elseif THEMES[arg] ~= nil then
if randomTheme or selectedExplicitly then
return nil, arg .. ' ne peut pas etre combine avec un autre theme';
end
selectedTheme = arg;
selectedExplicitly = true;
else
return nil, 'option ou theme inconnu: ' .. tostring(arg);
end
index = index + 1;
end
if randomTheme then
math.randomseed(os.epoch('utc'));
selectedTheme = THEME_NAMES[math.random(1, #THEME_NAMES)];
end
if THEMES[selectedTheme] == nil then
return nil, 'theme inconnu: ' .. tostring(selectedTheme)
.. ' (disponibles: ' .. themeNamesText() .. ')';
end
return THEMES[selectedTheme];
end
local function tokenColor(theme, token, row, col)
if theme.rainbow and (token == 'W' or token == 'w') then
-- Pour le mouton arc-en-ciel, seules les boucles de laine changent de couleur.
return RAINBOW[((row + col) % #RAINBOW) + 1];
end
return theme.palette[token] or theme.background;
end
local function drawSheep(theme)
local width, height = term.getSize();
local pixelW = math.max(1, math.floor(width / 20));
local pixelH = math.max(1, math.floor(height / 20));
if pixelW < 2 and width >= #SHEEP[1] * 2 then pixelW = 2; end
if pixelW > 4 then pixelW = 4; end
if pixelH > 2 then pixelH = 2; end
local artW = #SHEEP[1] * pixelW;
local artH = #SHEEP * pixelH;
local startX = math.max(1, math.floor((width - artW) / 2) + 1);
local startY = math.max(1, math.floor((height - artH) / 2) + 1);
term.setBackgroundColor(theme.background);
term.setTextColor(theme.text);
term.clear();
for row = 1, #SHEEP do
for sy = 0, pixelH - 1 do
local y = startY + ((row - 1) * pixelH) + sy;
local col = 1;
while col <= #SHEEP[row] do
local token = SHEEP[row]:sub(col, col);
local run = 1;
local color = tokenColor(theme, token, row, col);
while col + run <= #SHEEP[row]
and SHEEP[row]:sub(col + run, col + run) == token
and tokenColor(theme, token, row, col + run) == color do
run = run + 1;
end
drawRun(startX + ((col - 1) * pixelW), y, run * pixelW, color);
col = col + run;
end
end
end
term.setBackgroundColor(theme.background);
term.setTextColor(theme.text);
if height >= startY + artH then
term.setCursorPos(math.max(1, math.floor((width - #theme.title) / 2) + 1), startY + artH + 1);
term.write(theme.title);
end
term.setCursorPos(1, height);
end
local command = args[1];
if command == '-help' or command == '--help' or command == 'help' then
printUsage();
return;
end
if command == '-version' or command == '--version' or command == 'version' then
print('v' .. createVersion().forSelf());
return;
end
local theme, err = parseArgs(args);
if not theme then
print(err);
print('utilise: mouton -help');
return;
end
drawSheep(theme);