Mots-clé : geek

Php : challenge ASCII art

J’ai fait un pari. Petit challenge à réaliser : faire un script (peu importe le langage) qui prend en paramètre un fichier image, et qui en sort de l’ASCII art.
Il faut qu’il soit rapidement paramétrable sur la taille des fontes.

Je l’ai fait « théorique » en 59 minutes, mais entièrement fonctionnel en une heure trente. J’ai fait deux scripts : un qui génère le fichier des fontes, et le principal qui lit le fichier image des fontes, et le fichier image en paramètre, et sort de l’ASCII art.

Exemple de résultat (si si c’est bien du texte, vous pouvez le sélectionner et copier coller en tant que texte !) :

BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB¨ MBBBBBBMM0BBB
BBBBBBBBBBBBBBBBBBBBBBBBBP'`BB  ,BBBP¨    MBB
BBBBBBBBBBBBBBBBBBBBBBBBB&  %BMBPBBL  ,a  ¨BB
BBBBBBBBBBBBBBBBBBBBBBBBBB  jBB  MBBaBBP   BB
BBBBBBBBBBBBBBBBBBBBBBBBPM   BB  ¨BBB^  ,  0B
BBBBBBBBBBBBBBBBBBBBBBP`     BBb  BB'  mB  jB
BBBBBBB@P'BBBBBB@M@BBB   mB  $BK  0B  jBP  ¨B
BBBBBBBK  BBBP^`   MBB  dBB  MBB  jB   ¨ L,aB
B^¨ 'BBB  %BB  ,a   BB  &BBL  BB   Bh  ,WBBBB
B    ¨BB  jBB,mBM^  $B  'BBF  BBL  BBBBBBBBBB
BL    `BL  BBBP¨    jB   ^^   %B&mBBBBBBBBBBB
B&  w  ¨&  BBP  wB   B&    wamBBBBBBBBBBBBBBB
BB  %w     MBL  BB¨  BBBwamBBBBBBBBBBBBBBBBBB
BB  MBw    ¨BK  ¨`, ,&BBBBBBBBBBBBBBBBBBBBBBB
BBL  BBN    BB,  aBBBBBBBBBBBBBBBBBBBBBBBBBBB
BB&  BBBh   0BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBB  MBBBhwmBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBB  OBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

Ne regardez pas la suite si vous voulez essayer de le faire pour vous !

<?php
function usage_et_exit($message = '', $exit_error = -1) {
    global $argv;
    if ($message != '') {
        echo $message."\n";
    }
    echo $argv[0]." {image gif reference} {image noir et blanc jpg}\n";
    exit($exit_error);
}

function noir_ou_blanc($r, $g, $b) {
    /* http://stackoverflow.com/questions/254388/how-do-you-convert-an-image-to-black-and-white-in-php */
    if (((0.299*$r) + (0.587*$g) + (0.114*$b))> 0x7F) {
        return 0xFFFFFF;
    } else {
        return 0x000000;
    }
}

function cherche_meilleure_correspondance(
    $img_src, $x, $y, $img_fonts, $font_size, $tab_base
) {
    $meilleur = -1;
    $retour = '';
    foreach ($tab_base as $idx => $ch) {
        $match = 0;
        for ($t_y=0; $t_y<$font_size; $t_y++) {
            for ($t_x=0; $t_x<$font_size; $t_x++) {
                if (imagecolorat($img_src, $t_x+$x, $t_y+$y)
                    != imagecolorat(
                        $img_fonts,
                        ($idx*$font_size) + $t_x, $t_y
                    )
                ) {
                    $match++;
                }
            }
        }
        if ($match>$meilleur) {
            $retour = $ch;
            $meilleur = $match;
        }
    }
    return $retour;
}

function convert_img_noir_et_blanc($filename, $img)
{
    list($width, $height, $type, $attr) = getimagesize($filename);
    /* Conversion en noir et blanc */
    for ($y=0; $y<$height; $y++) {
        for ($x=0; $x<$width; $x++) {
            $rgb = imagecolorat($img, $x, $y);
            $r = ($rgb >> 16) & 0xFF;
            $g = ($rgb >> 8) & 0xFF;
            $b = $rgb & 0xFF;
            $nb = noir_ou_blanc($r, $g, $b);
            imagesetpixel($img, $x, $y, $nb);
        }
    }
}

$tab_base = array(
    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
    'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
    'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
    '5', '6', '7', '8', '9', '&', '\'', ',', ';', ':', '?', '.', '/', '!',
    '%', '^', '¨', '$', '~', '#', '(', ')', '[', ']', '|', '-', '`', ' '
);
$font_size = 14;
$min_width  = 400;
$min_height = 400;

if ($argc!=3) {
    usage_et_exit("Arguments invalides", -1);
}

$img_tmp = imagecreatefromstring(file_get_contents($argv[1]));
$width = imagesx($img_tmp);
$height = imagesy($img_tmp);
$img_fonts = imagecreatetruecolor($width, $height);
imagecopy($img_fonts, $img_tmp, 0, 0, 0, 0, $width, $height);
imagedestroy($img_tmp);
unset($img_tmp);
if ($img_fonts===false) {
    usage_et_exit("Erreur chargement de ".$argv[1], -1);
}

/* Conversion en noir et blanc des fontes */
convert_img_noir_et_blanc($argv[1], $img_fonts);
imagepng($img_fonts, './resultat_fonts.png', 0);

list($width, $height, $type, $attr) = getimagesize($argv[2]);
if ($width<$min_width) {
    usage_et_exit("Largeur trop petite de ".$argv[1].", taille min = ".$width_min, -1);
}
if ($width<$min_height) {
    usage_et_exit("Hauteur trop petite de ".$argv[1].", taille min = ".$width_min, -1);
}

$img_src = imagecreatefromjpeg($argv[2]);
if ($img_src===false) {
    usage_et_exit("Erreur chargement de ".$argv[2], -1);
}
convert_img_noir_et_blanc($argv[2], $img_src);
/* Ok on a l'image en noir et blanc. Parcourir toute l'image */
imagepng($img_src, './resultat_noir_et_blanc.png', 0);

$y = 0;
$max_result = 0;
while (($y + $font_size) < $height) {
    $x = 0;
    while (($x + $font_size) < $width) {
        echo cherche_meilleure_correspondance(
            $img_src, $x, $y, $img_fonts, $font_size, $tab_base
        );
        $x += $font_size;
    }
    echo "\n";
    $y += $font_size;
}
echo "Done.\n";
?>

Et le fichier qui génère les fontes (22 minutes de perdues à le faire…) :

<?php
$tab_base = array(
    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
    'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
    'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
    '5', '6', '7', '8', '9', '&', '\'', ',', ';', ':', '?', '.', '/', '!',
    '%', '^', '¨', '$', '~', '#', '(', ')', '[', ']', '|', '-', '`', ' '
);
$x=0;
$font_size = 14;
$width = count($tab_base)*$font_size;
echo 'width='.var_export($width,true)."\n";
$height = $font_size*4;
$img = imagecreatetruecolor($width, $height);
if ($img===false) {
    throw new Exception("Erreur");
}
imagefilledrectangle($img, 0, 0, $width, $height, 0xFFFFFF);
foreach ($tab_base as $idx => $char) {
    $ok = imagettftext(
        $img,
        $font_size, 0,
        $idx * $font_size, $font_size,
        0x000000,
        './consola.ttf', $char
    );
}
imagegif($img, './test.gif');
echo "Done.\n";
?>

Steam : d’où l’intérêt de travailler avec des gens compétents

Je vous fais part du message du directeur de steam, à vous d’en penser ce que vous voulez :

10 février 2012
Chers utilisateurs Steam et des forums Steam :

Des investigations sont en cours avec l’aide d’experts en sécurité informatique depuis l’intrusion dont nous avons été victime l’année dernière. Dans ma dernière communication à ce sujet, je décrivais comment les intrus avaient pu accéder à notre base de données Steam sans avoir trouvé d’évidence sur une captation d’information à partir de cette base de données.

Récemment, nous avons appris qu’il est probable que les intrus aient obtenu une copie du fichier de sauvegarde contenant les transactions effectuées sur Steam entre 2004 et 2008. Ce fichier de sauvegarde contenait les noms d’utilisateurs, les adresses email, les adresses encryptées de facturation et les informations encryptées des cartes bancaires. Ce fichier ne contenait pas les mots de passe Steam.

Nous n’avons aucune évidence nous permettant de penser que les informations bancaires encryptées ou que les adresses de facturation (également encryptées) aient été compromises. Cependant, comme je vous en informais en novembre, il convient de surveiller l’activité de vos cartes bancaires et/ou de crédit. Il est également une bonne idée d’activer Steam Guard sur votre compte Steam.

L’enquête poursuit son cours et nous travaillons avec les autorités compétentes. Certains états nécessitent un mode de communication plus formel et vous recevrez l’information en conséquence mais je souhaitais vous tenir informé de l’évolution de la situation.

Gabe

Mes tshirts de geek sont arrivés ! Geek ou nerd ?

Ca y est je les ai reçu !

Question quizz : savez vous à quoi chaque t-shirt correspond ?

Photo de mes tshirts de geek

Pour information, j’étais inquiet sur la qualité de l’impression, mais la méthode utilisée semble très résistante, et les couleurs ne devraient pas changer sur les quelques prochains lavages à venir (d’après le site c’est une centaine de lavages, ce qui ferait que je pourrais tenir presque un an avec ces trois tshirts…).

Python, débutant et jeu : Soko-ban version geek

Avez-vous déjà entendu parler de Sokoban, le jeu ?
J’ai eu la formidable idée (c’est de l’humour…) de le coder en Python, et encore mieux (c’est encore de l’humour…) de le coder pour pouvoir y jouer en mode console.

\o/

J’ai commencé à développer pour qu’il soit international, donc les commentaires sont pour la plupart en anglais.

La première chose que je voulais faire c’est pouvoir faire des affichages différents. Donc, selon que votre console le supporte ou pas, vous pourrez changer l’affichage :

# Different drawings:
glob_tab_chars = \
[
    # Ground / GroundStoneDest / Wall / Player / Stone
    [ ' ', '.', '█', '☺', '☻', '○','♦' ],
    [ ' ', '.', '#', '@', '+', '$','*' ],
    [ ' ', '.', '░', '☺', '☻', '○','◙' ]
]

Voici l’écran de base :

Copie d'écran de PySoko

Voici l’écran, si on veut changer les graphismes (en cliquant sur « + » ou sur « -« ) :
Copie d'écran de PySoko

Voici l’écran, si on veut encore changer les graphismes (en cliquant sur « + » ou sur « -« ) :
Copie d'écran de PySoko

Le code orienté objet

Les classes de base

Et ensuite le plus important à mon sens : le code orienté objet. J’ai voulu apprendre l’orienté objet de python. J’ai donc crée des classes qui correspondent aux objets de base (dans l’ordre, classe du Sol sans rien, classe du Sol où il faut ranger une pierre, classe Mur, et classe Joueur) :

# Different drawings:
class Ground(object):
    def __init__(self):
        super(Ground,self).__init__() # Parent call:

class GroundStoneDest(object):
    def __init__(self):
        super(GroundStoneDest,self).__init__() # Parent call:

class Wall(object):
    def __init__(self):
        super(Wall,self).__init__() # Parent call:

class Player(object):
    def __init__(self):
        super(Player,self).__init__() # Parent call:

Classe Level

Et de la même façon j’ai crée la classe Level qui est la plus complexe, et qui contient les fonctions les plus utilisées :

  • apply_drawings_set()
    Calculer les motifs pour dessiner le tableau (oui, oui c’est plus complexe que ça n’en a l’air) ;
  • draw()
    Dessiner les motifs en cours à l’écran ;
  • register_player_move()
    Se souvenir des mouvements du joueur, soit pour pouvoir faire un « undo » (pas implémenté), soit pour pouvoir les sauver pour les rejouer (pas implémenté non plus) ;
  • move()
    Essai de déplacer un objet situé en (x,y) du décalage (add_x, add_y), sachant que le décalage peut être négatif ;
  • solved()
    Test si toutes les pierres sont bien rangées.

Classe LevelsReader

De la même façon, j’ai crée la classe LevelsReader qui lit un niveau, et l’analyse pour voir s’il est un minimum cohérent. Pas la peine d’entrer dans le détail, les fonctions sont suffisamment explicites je pense.

Bibliothèque curses

Et pour terminer, la fonction de la boucle principale qui concerne l’unité curses : def curses_main(stdscr, code). C’est ici qu’on affiche le menu, qu’on attend qu’on tape sur une touche, etc.

Notez bien : le code n’est pas terminé. C’est un début de code, relativement correctement fait. J’ai passé à peine deux jours dessus pour réussir à faire cela, donc ne m’en voulez pas trop, il n’est pas peaufiné, mais il fonctionne.

Si jamais vous l’améliorez, ce serait gentil de me faire parvenir la nouvelle version 🙂

Le lien que tout le monde attend avec impatience, la bave aux lèvres :

Cliquez ici : pysoko.tar.bz2

Le Commodore 64 est de retour !

Voici, comme à mon habitude, une traduction de quelque chose que j’ai particulièrement apprécié. Comme d’habitude, pour mes quelques 300 lecteurs abonnés à mes flux, cela ne concerne qu’une infime partie de la population : ceux qui veulent bidouiller, et / ou, ceux qui connaissent le Commodore 64.

Le nouveau Commodore 64 vu de face

Le Commodore 64 est de retour, et il laisse la version de 1982 dans la poussière !

Le Commodore 64 était une excellente machine 8 bits, et le second de ma jeunesse.
Il semblerait bien qu’il fasse un come-back en 2011 !
Commodore USA a fait un truc super sympathique : ils ont mis un mini PC embarqué (Mini-ITX) dans la coque d’un Commodore 64. Il est donc possible de démarrer sur un système classique de type Windows ©, ou de charger l’OS Commodore 1.0, avec une sélection de jeux classiques, quelques applications et tout un paquet de programmes open-source. Il semblerait que cette dernière option arrive un peu plus tard, mais pour l’instant la machine est livrée avec un copie d’Ubuntu 10.04.

Le nouveau Commodore 64 vu de dos

Alors, comparé au modèle originel, qu’y a-t-il de mieux ou de moins bien ?

C64 (prix : 595 dollars en 1982, soit 1367 dollars ajourd’hui)

  • Processor 8-bits 6510 à 0.985MHz, technologie MOS
  • 64 Kb RAM (38Kb pour les programmes BASIC)
  • Chipset graphique VIC-II, technologie MOS (16 couleurs, 112 sprites maximum)
  • Chipset sonore SID, technologie MOS

C64x (Price: starting at $595)

  • Processur Intel Atom 1.80GHz
  • Jusqu’à 4Gb RAM
  • Chipset graphique Nvidia ION2 (nombre illimité de sprites (enfin on suppose))
  • Audio 6 canaux Realtek HD

Je ne vais rentrer plus dans les détails, mais les nostalgiques vont se régaler !
De plus, le clavier n’était à l’époque pas mauvais, surtout comparé aux claviers d’aujourd’hui !

L’article original est ici.

Linux : astuces bashrc

Lorsqu’on lance un nouveau shell sous Linux, il exécute un fichier ~/.bashrc.
Dans ce fichier, on peut y mettre des choses intéressantes, notamment :

export HISTCONTROL=erasedups
export HISTSIZE=10000
shopt -s histappend

Cela signifie :

  • effacer les lignes de commande en double ;
  • se souvenir au plus de 10000 lignes de commande (on n’en a jamais assez en fait) ;
  • dire au shell d’ajouter tout cela au fichier historique existant (et non pas ré-écrire par dessus (ce qui est fait par défaut)).

Apache : développement C et tutoriaux apr

Mes petits articles vont peut être me rendre célèbre.
Enfin chez les geeks. Et les asiatiques (les deux pages sur lesquelles je suis cité sont en Japonais)

Voilà la réponse du type qui a fait les exemples les plus pratiques, question « tutoriaux apr » :

Hi,

Sorry for the late reply.

I appreciate what you’ve done.

I put the links on the following pages (the former is written in Japanese).

http://dev.ariel-networks.com/column/tech/libarp_tutorial/
http://dev.ariel-networks.com/apr/

Thanks again.

Labyrinthes Trackmania : ça a fonctionné !

J’ai écrit un énorme générateur de labyrinthes pour Trackmania :

Forum Trackmania sur mes labyrinthes

Et plein de personnes ont répondu, il y en a même une qui a crée un topic sur un forum Espagnol :

http://tm.maniazones.com/forum/index.php?topic=20292.0

Enfin, comme les liens ne fonctionnent pas forcément, voilà le lien pour aller récupérer tous les fichier de folie que mon générateur a fait :

http://olivier.pons.free.fr/archives/

Et n’oubliez pas la meilleure page concernant ces labyrinthes, qui se trouve directement sur ce site même :

Trackmania et labyrinthes

Je joue trop à Dofus quand….

Petits extraits de « Je joue trop à Dofus quand…. » récupérés du forum officiel.

Notez qu’il faut trier y’a plein de répétitions, plein de fautes d’orthographe, bref ici c’est plus rapide :

Je joue trop à Dofus quand :

  • je dis que je vais drop un pack de bières ;
  • je demande au vendeur à combien de kamas est l’objet ;
  • je dis à mes parents que plus tard je veux devenir paysan ;
  • quand je me dis « Mince j’ai 50 amis, je ne peux plus m’en faire » ;
  • une application plante sans que j’aie sauvegardé et que je dis « P*tain d’EC ! » ;
  • quand, lorsque je marche sur du carrelage, je compte les PM que ca me coûte ;
  • lorsque je répond « La fonction ignorer pour éviter d’entendre des conneries » quand une copine me demande « Qu’est-ce qui est bien sur Dofus ? » ;
  • quand je regarde mes habits le matin en me demandant avec lesquels j’aurais les meilleures statistiques ;
  • je peins ma voiture en rose bonbon pour qu’elle me donne de l’intel ;
  • je me rend compte que c’est mardi grâce a la maintenance du matin ;
  • quelqu’un parle tout lentement et que je me dis « purée ça laggue » ;
  • je traite Thésée de boulet parce qu’il a cru qu’il pouvait soloter le minotaure ;
  • je dois acheter du pain et que j’ai la « flemme d’aller a l’hdv boulanger » ;
  • je me dis en voyant un car de vieux : « Tiens, une confrérie d’Enutrof s’est rassemblée ! » ;
  • je vois ma copine et que je pense à utiliser le sort « Roulage de pelle » ;
  • je vais devant une porte et que j’attends que je sois sorti automatiquement après un bref « chargement de la carte » ;
  • quand, en appelant ma fille, je lui dis « viens ici dragodinde » ;
  • quand, avant de partir au travail, je me dis « j’espère qu’il n’y aura pas trop de monde a la mine ce matin » ;
  • quand, le 24 décembre, je veille toute la nuit avec une batte de baseball pour pouvoir dire que j’ai soloté le papa Noël. ;
  • je cherche le petit rond jaune en bas des portes. ;
  • que je pense que les gagnants du loto sont des Enutrof. ;
  • je vide le chariot de courses et que je dis « on récolte le perco » ;
  • ma petite cousine me demande si le Père Noël existe et que je lui répond : « Ouais, il est dernière salle du 2 ème Donjon de l’ île de Nowel » ;
  • quand mon pote arrive avec une chemise et que je m’exclame : « j’ai la même dans mon inventaire ! » ;
  • quand j’ai dit à ma copine pour qu’on innove : « ça te dit qu’on installe la MAJ ? » ;
  • je dis « les verres de Pastis, je les one shoot » ;
  • je vois l’état des pâtes que j’ai préparé, et que je me dis « La recette est bonne mais a échoué ! » ;
  • quand, dans un magasin de jouets, je trouve une épée en plastique et que je crie : « Qui pour test arme SVP ? » ;
  • j’étais heureux de trouver une culotte de ma copine… je me suis dis « une culotte de Roissingue… ENFIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIN » ;
  • je nourris ma chienne et que je dis « tu l’as bien mérité, t’as réussi challenge va ».

Si vous en avez d’autres n’hésitez pas à les ajouter, je les mettrais dans l’article !