Prince of Persia libéré !

April 18th, 2012 par fgallaire

Prince of Persia est un jeu vidéo culte qui a réellement marqué l’histoire des jeux vidéo, en particulier pour son innovante technique d’animation rotoscopique. Or sa version originelle, sortie sur Apple II en 1989, vient d’être libérée par Jordan Mechner.

C’est son père qui, il y a trois semaines, en faisant du rangement, a retrouvé dans un carton trois vieilles disquettes 3.5″, âgées de plus de 20 ans, dans lesquelles se trouvait encore le précieux code source du jeu.

Le code source, qui est maintenant disponible sur GitHub, est de l’assembleur pour 6502, un processeur utilisé sur une très grande variété de machines différentes, ce qui laisse pas mal d’espoir de voir apparaître de nouveaux portages. La riche documentation technique, fournie à l’époque par Jordan pour aider les développeurs effectuant les portages commerciaux, devrait alors être encore une fois d’un grand secours.

La disponibilité du code source rend les choses beaucoup plus simples, bien que la programmation en assembleur puisse paraître effrayante pour beaucoup de programmeurs “modernes”, et évite d’avoir recours au reverse engineering comme lors du superbe travail de portage de Prince of Persia sur Commodore 64, économisant ainsi beaucoup d’énergie et de talent.

Le choix de la licence utilisée n’est pas encore très clair, Jordan indiquant juste dans le README:

We did this for fun, not profit. As the author and copyright holder of this source code, I personally have no problem with anyone studying it, modifying it, attempting to run it, etc. Please understand that this does NOT constitute a grant of rights of any kind in Prince of Persia, which is an ongoing Ubisoft game franchise. Ubisoft alone has the right to make and distribute Prince of Persia games.

Je lui ai demandé des précisions sur son Twitter, moyen de communication qu’il semble privilégier, et j’espère qu’il répondra rapidement. En attendant, vous pouvez toujours jouer au clone Flash de POP :

Flash n’est pas installé ? Tant mieux !

Et ainsi réfléchir aux Ghz de CPU et aux Go de RAM que vous utilisez, alors que la version dont on a aujourd’hui le code source faisait que le Mhz du 6502 et ses quelques Ko de RAM suffisaient à obtenir le même résultat.

À l’époque où un jeu vidéo était une œuvre indissociable de son développeur, inventeur aussi bien de l’idée originale que du scénario, créateur aussi bien du code source que des graphismes ; et où chaque instruction assembleur utilisée était un trésor d’optimisation de code (when men were men and wrote their own device drivers)…


4 Comments »

Zack 3.0

April 15th, 2012 par fgallaire

Stefano Zacchiroli (Zack) vient d’être re-réélu Debian Project Leader.

Il devance très largement Wouter Verhelst (déjà candidat malheureux en 2007 et 2010) et Gergely Nagy (déjà malheureux lui en 2004) :

Zack a annoncé pendant la campagne que ce troisième mandat consécutif de DPL serait son dernier. Souhaitons qu’il se déroule aussi bien, et même encore mieux !, que les deux premiers, et que Zack puisse mettre en œuvre au mieux son programme.


2 Comments »

Android pour les Abribus !

April 5th, 2012 par fgallaire

En  passant place de la Bastille à Paris (j’ai cours tout près, à l’EFB, rue de Charenton), j’ai croisé un Abribus d’un nouveau genre, aux allures de soucoupe volante, doté d’un design futuriste et de nombreux écrans :

Cet Abribus est un prototype de JCDecaux, faisant partie des 40 projets de mobilier urbain intelligent retenus par la ville de Paris. Le grand écran de 42 pouces en pleine action :

Les deux écrans de l’arrière :

Les écrans sont tous tactiles multitouch et proposent de nombreux services que je ne détaillerai pas car là n’est pas mon propos. En effet, c’est le système d’exploitation utilisé par cet Abribus qui m’intéresse, et l’utilisateur de smartphone un peu perspicace que je suis a tout de suite reconnu Android, un système d’exploitation libre basé sur le noyau Linux !

Ceci est une réelle bonne nouvelle, car jusqu’à présent JCDecaux utilise pour ses différentes bornes des solutions basées sur Microsoft Windows, ce qui présente pas mal d’inconvénients. Ainsi, tous les utilisateurs réguliers de Vélib’ ont été au moins une fois confrontés à une station totalement plantée, ce que JCDecaux résout tant bien que mal en redémarrant ses bornes toutes les nuits…

Si, à l’avenir, Android devait remplacer Windows, les utilisateurs y gagneraient donc des stations plus stables et plus fonctionnelles, et JCDecaux ferait des économies de licence (ce qui devrait impliquer des économies pour la Ville de Paris et donc pour les contribuables parisiens…).


11 Comments »

Quel DPL pour 2012 ?

March 19th, 2012 par fgallaire

Le temps passe vite, et cela fait déjà presque un an que Stefano Zacchiroli, dit Zack, a vu son mandat de Debian Project Leader (DPL) renouvelé. Sans concurrent en 2011, Zack est cette année en compétition avec Wouter Verhelst (candidat malheureux en 2007 et 2010) et Gergely Nagy (malheureux lui en 2004). Il a justifié sa nouvelle candidature par le proverbe italien “Non c’è due senza tre“, qui semble bien être l’équivalent de notre “Jamais deux sans trois”.

Le plus important est bien sûr de lire les programmes de chacun des candidats :

Les presque mille développeurs Debian sont maintenant libres de faire leur choix lors d’un vote utilisant la méthode Condorcet. Le nombre de trois candidats est un peu inférieur à la moyenne des années précédentes, qui est de quatre environ, mais il permet tout de même un belle campagne qui ouvre publiquement certains débats, que chacun peut suivre sur la mailing list debian-vote.


No Comments »

Complément à l’article de Carl sur SQLite et Python

February 14th, 2012 par fgallaire

Carl vient de publier, dans le dernier Linux Pratique Hors-Série sur Python, un article sur le module sqlite3, disponible dans la bibliothèque standard depuis Python 2.5, et qui permet d’utiliser facilement SQLite.

C’est un article très didactique, qui tombait à point nommé pour moi puisque j’ai récemment eu plusieurs idées d’intégration de SQLite dans txt2tags. Je suis parti totalement de zéro, puisque j’ai toujours fui aussi bien le langage SQL que la configuration des systèmes de gestion de bases de données, et j’ai quelques remarques complémentaires à faire qui pourront aider les personnes dans le même situation que moi.

Sur le shell sqlite3

Le shell sqlite3 est très pratique pour interagir avec les bases de données SQLite, et en particulier vérifier celles générées par nos programmes Python. Cependant, l’affichage standard est un peu spartiate :

sqlite> select * from tab;
1|gpl|3|premier test
2|linux|5|deuze

Pour une meilleur visualisation, on peut ajouter les noms des champs :

sqlite> .header on
sqlite> select * from tab;
id|title|length|comment
1|gpl|3|premier test
2|linux|5|deuze

Afficher en colonnes :

sqlite> .mode column
sqlite> select * from tab;
1           gpl         3           premier test
2           linux       5           deuze

Et même les deux à la fois :

sqlite> select * from tab;
id          title       length      comment
----------  ----------  ----------  ------------
1           gpl         3           premier test
2           linux       5           deuze

Sur la table sqlite_master

Dans l’article il est précisé comment obtenir la liste des tables d’une base de données grâce à une commande du shell sqlite3 :

sqlite> .tables
tab

Mais pas comment obtenir le même résultat d’une requête SQL que vous pouvez effectuer en Python, et qui utilise la table sqlite_master automatiquement créée par SQLite :

sqlite> select name from sqlite_master;
tab

Sur la méthode iterdump()

Deux remarques :

  1. Elle n’est disponible que depuis Python 2.6
  2. C’est selon Gerhard Hæring lui-même, l’auteur du module sqlite3, la seule méthode pour dupliquer une base en mémoire vers une base sur disque (oui, c’est vraiment très moche qu’il n’y ai pas de manière plus élégante de le faire, mais c’est comme ça !)

Sur les ? et les chaînes de caractères

Pour construire dynamiquement le contenu des requêtes SQL, Carl utilise sans le justifier des ? et un tuple de valeurs comme second argument de la méthode execute(). Il est en fait très important de suivre cette manière de faire, car si vous utilisez les opérations classiques de concaténation des chaîne de caractères, vous vous exposez à des risques d’attaque par injection SQL !

L’autre article de Carl sur l’utilisation du module smtplib est aussi très intéressant, les autres articles du Hors-Série formant en fait un gros tutoriel d’initiation au langage Python.


2 Comments »

Héros de jeu vidéo, dans FLARE !

February 9th, 2012 par fgallaire

FLARE, pour Free/Libre Action Roleplaying Engine, est un jeu vidéo libre disponible sous Windows, Mac OS X et Linux. Le projet a commencé sous le nom OSARE, pour Open Source Action Roleplaying Engine, et en a changé suite à une discussion entre Clint Bellanger, le principal développeur du projet, et l’inusable Richard Stallman.

Le jeu y a gagné un nom “éthique”, puisque défendant ouvertement nos valeurs, ainsi qu’un logo, puisque flare signifie en gros flamme en anglais.

C’est la licence GNU GPL version 3 qui est utilisée pour le code source du moteur du jeu, et la licence Creative Commons BY-SA 3.0 pour toutes les données et fichiers artistiques (desseins, textures, musique, etc.).

Justin Nichol, un jeune artiste qui souhaitait produire des données créatives utilisables dans FLARE , tout en finançant la fin de sa formation à la Concept Design Academy, a donc créé en décembre 2010 le projet Creative Commons Fantasy Portrait Marathon sur le site de financement collaboratif Kickstarter.

Il a ainsi récolté 2 567 dollars auprès de 33 donateurs, ayant donné chacun entre 10 et 250 dollars. J’ai personnellement donné 100 dollars pour un pack “Spellslinger” que je me suis offert à moi-même comme cadeau de Noël, et qui ne me permet pas moins que de devenir un vrai héros de jeu vidéo !

One of the characters in the set will be based on your likeness and you will have additional creative input during the painting process into the background, concept and costuming of the character. You will receive a print of the portrait.

Après plus d’un an de travail, Justin vient juste de publier la trentaine de portraits promis. En plus d’être licenciés sous Creative Commons BY-SA, ils ont été créés uniquement à l’aide de logiciels libres, principalement GIMP.

Je trouve le rendu des portraits très concluant, et je suis en particulier très content du mien. Et un jour prochain, en étant un peu patient, je pourrai faire apt-get install flare (c’est-à-dire installer FLARE sur ma Debian ou ma Ubuntu) et jouer avec Moi l’Unique !

Je crois que ce genre d’initiative est à même de donner un sacré coup de vieux à l’énorme industrie des jeux vidéo propriétaires, que les jeux libres ont pour l’instant bien du mal à concurrencer, la disparité de moyen semblant particulièrement insurmontable (les grands jeux vidéos se développent à coup de dizaines de millions d’euros) .

En effet, les jeux vidéos sont des logiciels d’une espèce hybride, avec des spécificités très fortes qui les différencient des logiciels classiques (importance du non logiciel comme les visuels, la musique, le scénario, etc.), et on ne concurrence donc pas World of Warcraft aussi facilement que IIS si l’on est juste un bon développeur.

Nous avons besoin de Clint Bellanger, mais nous avons aussi besoin de Justin Nichol, l’alliance des deux permettant d’ouvrir des voies qui resteront pour toujours fermés aux jeux propriétaires, et qui pourraient donc permettre la réussite des jeux vidéo libres auprès du grand public.

Mise à jour du 10 février 2012 : Tous les portraits sont maintenant disponibles aux formats PNG, JPEG et XCF (le format natif de Gimp, à utiliser si vous souhaitez modifier les fichiers).


5 Comments »

Django 1.4 passe à HTML5 ! et autres nouveautés

January 3rd, 2012 par fgallaire

Le 22 décembre dernier est sorti Django 1.4 alpha 1. Comme on peu l’imaginer pour un projet d’une telle ampleur, cette nouvelle version apporte beaucoup de nouveautés. Je me contenterai d’en détailler rapidement cinq qui me semblent particulièrement intéressantes :

    1. Le passage au Doctype HTML5, tous les templates fournis avec Django, en particulier ceux de l’interface d’administration, utilisant donc désormais <!DOCTYPE html>. C’est un choix logique, qui permet d’utiliser toutes les nouvelles fonctionnalités de HTML5 sans plus se soucier de devoir corriger le Doctype.
    2. L’abandon du support de Python 2.4, datant de 2004, mais pas le passage à Python 3. Django supporte et est testé sur Python 2.5, 2.6 et 2.7.
    3. Le nouveau framework de test LiveServerTestCase, compatible avec Selenium et Windmill, pour tester l’interface de votre application web côté client (dans le navigateur web).
    4. La nouvelle option --template pour les commandes startapp et startproject, permettant de leur spécifier aisément un template personnalisé.
    5. La nouvelle clause elif pour la balise if. Elle permettra de ne plus avoir à imbriquer plusieurs if then else et autant d’indentations ou à se définir une balise personnalisée. Alors oui j’ose le dire : c’est pas trop tôt !

On voit donc qu’encore une fois Django continue d’avancer dans la bonne direction, bonifiant sans cesse une base déjà excellente. La seule chose que je regrette encore et toujours, c’est la défiance manifeste de la core team envers l’intégration de django-nonrel… peut-être pour Django 1.5 ?


2 Comments »

Le Barreau !

December 28th, 2011 par fgallaire

Ce post est un cadeau de Noël pour tous mes fans, avec bien sûr une spéciale dédicace pour Michel Houellebecq :-) .

J’ai réussi à ma première tentative ce qu’il est convenu d’appeler le concours d’avocat, le concours du Barreau, ou encore le Pré-CAPA, c’est-à-dire l’examen d’entrée à l’École de Formation du Barreau, le CRFPA parisien.

Pour illustrer, une très mauvaise photo du panneau d’affichage public des notes de l’Université Paris 1 Panthéon-Sorbonne, prise le 6 décembre dernier :

Je commence les cours spécifiques à la profession d’avocat, comme la déontologie, à partir de janvier. Et après deux stages dont le dernier en cabinet d’avocat, Maître Eolas devra donner du Cher Confrère à celui qu’il avait cru pouvoir définir comme un blogueur s’affirmant juriste.

En France, après Olivier Hugot chez qui j’ai effectué mon stage de Master, les logiciels libres auront donc bientôt un deuxième avocat réellement spécialisé. C’est important, car les développeurs de logiciels libres doivent pouvoir trouver des interlocuteurs compétents à qui parler, et par qui se faire représenter, y compris Pro-bono.

Avec la progression inéluctable de l’utilisation des logiciels libres, le contentieux ne pourra qu’augmenter, car les licences de logiciels libres et Creative Commons ne sont pas là pour faire joli, mais pour être respectées !


7 Comments »

La compréhension de liste en Python, une syntaxe moderne pour map() et filter()

December 5th, 2011 par fgallaire

La compréhension de liste est un syntactic sugar pour les fonctions classiques de la programmation fonctionnelle que sont map() et filter(). Disponible depuis Python 2.0, la compréhension de liste devrait à terme amener à la disparition des fonctions map() et filter() du langage Python, ce que Guido van Rossum avait déjà envisagé pour Python 3.

Ainsi, si vous avez du “vieux code” utilisant ces fonctions, je vous encourage à le porter vers cette nouvelle syntaxe beaucoup plus lisible et plus pythonique. J’espère que cet article pourra aider certains à éviter les pièges qui pourraient apparaître devant eux lors de cette démarche.

map()
Commençons d’abord par la fonction map(), dont la syntaxe est map(fonction, liste). Prenons un exemple très simple, avec une fonction anonyme lambda qui à tout x élément de la liste des chiffres de 0 à 9 associe 2 fois x.

>>> map(lambda x: 2*x, range(10))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

On obtient l’équivalent de la fonction map() avec une compréhension de liste de la forme [fonction(x) for x in liste], ce qui donne pour notre exemple :

>>> [2*x for x in range(10)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

filter()
La syntaxe de la fonction filter() est filter(fonction, liste). Prenons ici aussi un exemple très simple, avec une fonction anonyme lambda qui n’est Vrai pour chaque x élément de la liste des chiffres de 0 à 9 que s’il est strictement supérieur à 5.

>>> filter(lambda x: x>5, range(10))
[6, 7, 8, 9]

On obtient l’équivalent de la fonction filter() avec une compréhension de liste de la forme [x for x in liste if fonction(x)], et donc notre exemple devient :

>>> [x for x in range(10) if x>5]
[6, 7, 8, 9]

Un des grands intérêts des fonctions est de pouvoir être composées. Cependant, cette opération de composition n’est pas anodine, et il faut bien envisager les différents cas pour ne pas commettre d’erreur.

map o filter()
La composition notée map o filter() revient à map(filter()), c’est-à-dire à appliquer d’abord la fonction filter(), puis la fonction map(). Si nous combinons nos deux premiers exemples, nous obtenons :

>>> map(lambda x: 2*x, filter(lambda x: x>5, range(10)))
[12, 14, 16, 18]


On obtient l’équivalent de la composition de fonction map o filter() avec une compréhension de liste de la forme [fonction_map(x) for x in liste if fonction_filter(x)], ce qui donne ici :

>>> [2*x for x in range(10) if x>5]
[12, 14, 16, 18]

La composition de fonction map o filter() ne pose pas de problème.

On remarque que plus l’on compose des fonctions map() et filter(), plus l’avantage syntaxique de lisibilité et de compréhensibilité des compréhensions de liste augmente.

filter o map()
Mais qu’en est-il de la composition notée filter o map(), qui revient à filter(map()), c’est-à-dire à appliquer d’abord la fonction map(), puis la fonction filter(). Si nous combinons ici aussi nos deux premiers exemples, nous obtenons :

>>> filter(lambda x: x>5, map(lambda x: 2*x, range(10)))
[6, 8, 10, 12, 14, 16, 18]

Le résultat retourné est différent de celui obtenu à l’exemple précédent avec une compréhension de liste de la forme [fonction_map(x) for x in liste if fonction_filter(x)]. En fait, la bonne compréhension de liste est :

>>> [2*x for x in range(10) if 2*x>5]
[6, 8, 10, 12, 14, 16, 18]

Nous voyons que la composition de fonction filter o map() pose des problèmes, et qu’il faudra y porter une attention particulière en cas de conversion de vieux code fonctionnel en compréhensions de liste.

filter o filter()
La composition notée filter o filter() revient à filter(filter()), c’est-à-dire à appliquer deux fois de suite la fonction filter(). Nous allons donc rajouter une deuxième condition à notre premier exemple de filter(), qui sera que chaque élément x devra en plus être strictement inférieur à 8.

>>> filter(lambda x: x<8, filter(lambda x: x>5, range(10)))
[6, 7]

Le même résultat est obtenu en inversant l’ordre des deux conditions :

>>> filter(lambda x: x>5, filter(lambda x: x<8, range(10)))
[6, 7]

La composition filter o filter() est commutative, et peut en fait facilement se factoriser sous la forme :

>>> filter(lambda x: x>5 and x<8, range(10))
[6, 7]

On obtient l’équivalent de la composition de fonction filter o filter() avec une compréhension de liste de la forme [x for x in liste if fonction_filter_1(x) and fonction_filter_2(x)], ce qui donne ici :

>>> [x for x in range(10) if x>5 and x<8]
[6, 7]

La composition de fonction filter o filter() ne pose pas de problème.

map o map()
Mais qu’en est-il de la composition notée map o map(), qui revient à map(map()), c’est-à-dire à appliquer deux fois de suite la fonction map() ? Rajoutons une deuxième fonction à notre premier exemple de map(), qui à chaque x associera x plus 1.

>>> map(lambda x: x+1, map(lambda x: 2*x, range(10)))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

et

>>> map(lambda x: 2*x, map(lambda x: x+1, range(10)))
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

ne donnent pas les mêmes résultats. La composition map o map() n’est pas commutative. On obtient l’équivalent de la composition de fonction map o map() avec une compréhension de liste de la forme [fonction_map_2(x) for x in [fonction_map_1(x) for x in liste]], ce qui donne ici :

>>> [x+1 for x in [2*x for x in range(10)]]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

et

>>> [2*x for x in [x+1 for x in range(10)]]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Il est possible de factoriser les deux fonctions map() comme nous l’avons fait pour les fonctions filter(), mais il faut faire très attention à l’ordre de composition des fonctions. Dans le premier cas on a (2*x)+1 = 2*x+1 qui donne :

>>> [2*x+1 for x in range(10)]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

et dans le deuxième cas on obtient 2*(x+1) = 2*x+2 qui produit :

>>> [2*x+2 for x in range(10)]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Nous voyons que la composition de fonction map o map() pose des problèmes.

Pour ne pas tomber dans des pièges, il suffit de retenir que toutes les compositions de fonctions qui commencent par une fonction map() sont dangereuses, alors que celles commençant par une fonction filter() sont sans danger.

Pour mon plus grand bonheur, la syntaxe de compréhension de liste rend particulièrement pythonique et centrale au langage Python une partie de la sémantique de la programmation fonctionnelle qui y était jusqu’à présent mal intégrée et mal aimée. Encore une fois, et même si certains de mes professeurs d’informatique ne l’ont jamais accepté, sans une bonne syntaxe, une sémantique géniale n’est rien.


5 Comments »

Steve Jobs est mort, un pionnier de l’informatique disparaît

October 6th, 2011 par fgallaire

Steve Jobs est mort hier, seulement un mois et demi après s’être retiré de son poste de CEO d’Apple. Il aura donc mené sa passionnante vie jusqu’à la toute dernière limite de ses possibilités physiques.

En tant qu’informaticien, et en tant que simple utilisateur d’ordinateur, je le remercie d’être allé voler les idées géniales et inexploitées d’interfaces graphiques et de souris au PARC, le Palo Alto Research Center de Xerox, dont la photo orne toujours la porte de ma chambre.

Et d’en avoir conçu en 1983 le premier ordinateur personnel utilisable par une personne normale, nommé Lisa (le prénom de sa fille).

Quand il fut viré d’Apple par John Sculley en 1985, il fonda une entreprise nommée NeXT. Le nom de domaine que j’utilise, FLeXT, y fait directement référence.

Avec NeXTSTEP, il créa le premier Unix doté d’une interface graphique innovante tant d’un point de vue technique qu’ergonomique, que l’on connaît encore aujourd’hui sous le nom de Mac OS X (avec un look un peu plus eye candy), et dont le projet GNUstep est une réimplémentation libre des APIs.

J’ai très longtemps utilisé exclusivement Window Maker, un gestionnaire de fenêtre libre pour X11 réimplémentant l’ergonomie de NeXTSTEP.

Merci à toi Steve d’avoir été à l’origine de certains des plus beaux designs de l’histoire de l’informatique, comme la première version de la NeXTstation, avec son écran noir et blanc NeXT MegaPixel de 17″ dont un exemplaire est encore stocké dans ma cave, alors qu’une NeXTstation TurboColor est toujours présente sur mon bureau pour rehausser mon écran ;

comme l’Apple Cube dans l’esprit duquel, avec l’aide de Philou, j’ai essayé de réaliser un boîtier en plexiglas pour une carte mère mini-ITX ;

et bien sûr comme le sublime iMac Tournesol, dont je serais très heureux de récupérer un modèle 20″ !

 

Merci aussi d’avoir longtemps été l’un des seuls à tenir tête à Bill Gates et à son empire de médiocrité informatique nommé Microsoft. Bravo pour avoir eu l’intelligence technique d’utiliser massivement les logiciels libres, qui sont la composante principale des systèmes Mac OS X et iOS diffusés par Apple, même si tu n’en as pas compris la puissance politique.

Alors bien sûr, l’Apple d’aujourd’hui, première valorisation boursière mondiale, l’Apple des bobos, des DRM et des iBidules, très peu pour moi comme pour tous les libristes. Mais Steve Jobs a fait bien d’autres choses que cela, c’est un exceptionnel pionnier de l’informatique qui nous a quitté hier.

 

 


8 Comments »