Friday, December 02, 2022

baloo_file ?

 Je tente une migration de ma VM ubuntu au bureau. De 18.04 à 20.04, en espérant que ça me permettra de partager plus facilement les produits de builds avec les machines de tests tournant en 20.04 ...

Mais au moment où j'essaie de prendre la machine en main, je suis face à un système tellement peu réactif que passer en mode console est à peu près ma seule option. Le coupable, c'est kswapd ... enfin non. Le coupable, ce serait plutôt baloo_file, qui semble s'être décidé à indexer l'entièreté du système (à travers un process fils baloo_file_extractor) en même temps que d'autres opérations de bienvenue (regarder si il y a une mise à jour dispo) sont aussi en cours. Sur un système avec 2G de mémoire au total, ça ne pardonne pas vraiment.

Le message d'erreur quand le programme de mise à jour d'une distribution à l'autre aurait pu être plus clair, cela dit. https://ubuntu.com/blog/how-to-upgrade-from-ubuntu-18-04-lts-to-20-04-lts-today ... Voire, l'outil aurait pu auto-installer ses dépendances plutôt que de signaler une erreur :-P

L'outil de mise à jour voulait me virer e17 ... mais pas de panique: c'est juste parce que le package a été rebaptisé "enlightenment". Heureusement, il est possible de passer le 'nettoyage des anciens packages' le temps de vérifier que tout se passe comme il faut, découvrir les alternatives de la nouvelle distro puis valider le nettoyage avec apt auto-remove (ou quelque-chose du genre suggéré au premier apt-get remove e17)

La bonne nouvelle c'est que je vais pouvoir utiliser terminology dans cette VM aussi. à moi les tyls et autres tycat pour avoir des images en ligne de commande $_$

Par contre, terminology n'a pas de support pour la ruse "un 2eme fond d'écran parfaitement ajusté pour qu'on puisse lire le texte par-dessus" que j'utilisais avec Eterm... 'faudra peut-être que je travaille à une PR.

Sunday, November 27, 2022

Tué par la caméra

C'est devenu un problème récurrent pendant que je progresse dans les niveaux de Super Mario 3D World: tôt ou tard, je finis en-dehors du niveau, et régulièrement, c'est suite à un mauvais mouvement avec le stick-caméra.

Le jeu a fait le pari d'un mélange 2D/3D qui (globalement) marche plutôt bien. la perspective montre une généreuse partie du sol, ce qui autorise la création de "salles" dans lesquelles les quatre joueurs peuvent aller et venir, coopérer ou entrer en compétition. La manipulation des personnages y est d'ordinaire plus proche d'un Link's Awakening Switch que d'un Super Mario. ça, c'était prévisible. Elle est aussi plus proche d'un Link's Awakening Switch que d'un Mario 64, et ça, ça vaut peut-être la peine qu'on y regarde de plus près.
Dans Mario 64, le personnage peut normalement prendre n'importe quel angle sur le stick. Le contrôle est doublement direct (pour reprendre le terme défini par Kirby Kid dans The Coefficient of Clean ): la direction du stick s'applique directement à l'orientation de Mario et l'amplitude du stick s'applique directement à sa vitesse (ou à son accélération ... ma mémoire du jeu me joue un tour). En comparaison, les mouvements de Mario dans 3D World sont confinés aux 8 directions accessibles à un D-Pad, comme si le jeu avait été conçu sur SNES. 
En soi, le 3D world étant principalement consitué d'objets alignés sur une grille cubique, c'est un excellent choix de design: quand il va y avoir une passerelle un peu étroite à franchir, le joueur aura toujours moyen d'être pile dans l'axe où il ne se met pas à tomber au bout de trois pas. Mario 64, au contraire, était construit avec des polygones "libres". Une passerelle pouvait se trouver sous n'importe quel angle entre deux plate-formes qui adoptaient une géométrie polygonale quelconque (croyez-en un vieux qui y a joué au pavé numérique sur émulateur, et qui donc devait zig-zagger dans ce genre de situation)
Les mouvements de caméra eux aussi ont été discrétisés. On regarde de face, de profil, ou sous un angle de 45° entre les deux. Un léger mouvement du stick droit de la switch nous fait basculer d'une perspective à l'autre dans un mouvement adouci dans le temps mais déclenché d'un coup quoi qu'il en soit. Et ça, en jeu solo, ça fait mal: le stick caméra est alors normalement sous les 4 boutons d'actions. Le moment où vous avez le plus de risque de l'accrocher par mégarde, c'est au milieu d'un saut un peu long. Pour peu que vous soyez dans un niveau qui reproduit en réalité un parcours 2D dans un moteur 3D, il ne faudra pas longtemps pour que ce changement d'orientation se traduise par un changement de la trajectoire de Mario (la direction imposée par le stick est relative à la vue, pas à Mario lui-même, or la vue vient de changer). Le temps de s'en rendre compte, il est trop souvent trop tard pour réagir et on aura au mieux le droit à 2 ou 3 wall-kicks pathétiques avant de ouahaouhouahouahoahahahahaaa au fond du niveau.


Et pour ne rien arranger, le jeu nous met sur la même input (stick directionnel vers le haut) deux mécaniques: avancer vers le fond de l'écran ou grimper vers le haut. On casse ici le principe d'individualité des contrôle (chaque mécanique a son morceau de manette qu'il ne partage avec aucune autre mécanique, toujours d'après le lexique de Kirby Kid).


 Dans la plupart des niveaux, c'est plutôt un bon compromis: ça rend le fait d'escalader un mur spontané par rapport au déplacement sur le sol bidirectionnel, de même qu'il paraît naturel d'utiliser le DPAD vers le haut pour monter les escaliers dans un Zelda 2D (et si on avait pu y escalader les montagnes, ça aurait marché aussi). Mais revoilà les niveaux linéaires où les traceurs de parcours ont décidé de nos faire profiter de la vue splendide sur les nuages en arrière plan plutôt que de nous coller un mur devant les yeux. Soit.

Sauf que si vous ajoutez une grille à escalader (direction vers le haut), une fois Mario arrivé en haut de la grille, vous avez assez peu de temps pour relacher la direction 'vers le haut'. Faute de quoi, vous irez dire coucou aux jolis nuages d'un peu plus près. "Dommage", comme dirait Bowser. 

Notez que les concepteurs ont réalisé qu'il y avait un problème, et qu'ils ont ajouté une grille-de-fond par-derrière la grille-à-escalader. ça rattrapera le J.L.N qui avait mis uniquement son stick vers le haut (et donc ira s'accrocher à la grille du fond une fois arrivé en haut de la grille-qui-bouge), mais pas le papa qui avait maintenu haut et avant simultanément dans une habitude d'optimisation des mouvements sur les lianes de la Jungle Jaja.


 

Notez aussi que le problème ne se limite pas aux niveaux sans mur en arrière plan. Ici, par exemple, on est supposé se promener en rebondissant sur les fourmis invincibles tandis qu'on passe par-dessus des pics. Fort bien tant qu'on ne se met pas en tête d'utiliser la 3eme dimension pour aller s'accrocher au mur avec le costume de chat. Parce qu'en réalité il y a un espace de la taille d'un Mario entre les fourmis et le mur, donc vous pouvez parfaitement vous retrouver à les louper parce que vous êtes par-derrière alors que ce tronçon de niveau est conçu pour être joué sur un seul plan. Et vous pouvez aussi vous retrouver à tomber par-devant le niveau suite à un rebond mal calculé sur le mur du fond, naturellement.

Sunday, November 20, 2022

#RIPTwitter ?

C'était un drôle de vendredi, ou tout Internet semblait convaincu qu'on vivait les dernières heures de twitter.

Cette année-ci, j'ai une bonne raison de ne pas me laisser affecter par ce genre de nouvelle, mais ça ne m'a pas empêché de voir que j'étais loin d'être indépendant de ce réseau social, même si j'ai pris pas mal de distance (plus de #screenshotsaturday ou de #OneTagPerWeek, par exemple)

Il faut dire que twitter a pris la place des forums quand j'ai migré hors de l'environnement universitaire (enfin, ceux qui étaient encore existants). Il a aussi bouché tant bien que mal le trou laissé par la disparition de Google Reader et des flux RSS. Et il me sert de va-et-vient pour les images et vidéos provenant de ma switch comme de ma 'liseuse' avant d'en faire quelque-chose de précis pour mon blog.

Mais plus gênant, j'ai pris l'habitude de faire des liens vers des conversations twitter quand il y a eu des discussions préalables, ou quand une image full HD d'un jeu switch est en ligne mais qu'une version réduite suffit pour les besoins d'illustration du blog. Et tout ça, ça veut dire que mon blog lui-même perd un membre si twitter disparaît.

J'ai donc demandé une archive de mes données twitter. Mais le 'takeout' est loin d'être automatique, et quelques heures plus tard, ne voyant toujours rien venir, je prend une archive de mon blog (instantanée) et je greppe tout ça un bon coup pour trouver tous les liens du blog vers twitter (enfin, je pense).

Mauvaise nouvelle, les pages correspondantes ne sont que des coquilles vides, dans lesquelles du code javascript ira écrire le contenu des tweets. Le seul outil capable de faire ça, c'est un navigateur complet (je pense). C'est donc au clavier-souris que j'ai passé presque la totalité de mon samedi à copier-coller les tweets identifiés dans un gros .odt sous google-document (365+ pages au final) avec les URLs par-devant pour pouvoir retrouver et reconstruire le contenu-satellite au cas où ...

edit: il aura fallu finalement près d'une semaine pour recevoir l'archive de 1Go avec entre autres toutes les images et toutes les vidéos postées dans mes tweets.

Bref, ça m'a permis de fortifier un peu mon compte Mastodon.

Et il faudra que je vous parle de ce https://goodboygalaxy.com/



Sunday, November 06, 2022

Scorpeye... Enfin!

 Oui, je l'avoue, j'ai été lent. J'ai été distrait (au sens attention détournée). J'ai été démoralisé par cette "carapace" qui ne voulait pas faire demi-tour à chaque fois ou qui faisait des demi-tours intempestifs. J'ai douté, de cet empilement de couches qui devait me permettre de laisser des personnes non éduquées au C++ de bricoler aussi leur propres personnages. Sauf que tout ça, c'est bien joli mais que quand vous avez un dysfonctionnement quelque-part, le débugger vous balance des instructions machines alors que le problème est dans le bytecode qu'elles interprètent. Et mon "inspector widget" (pas encore fonctionnel dans le projet 3 rooms) est loin de valoir ddd.

It's been a long time, I have to admit. I've been slow to get things running; I've had lost the hope that I could get that scorpio-shell turning back when it hits a wall... and only when it hits a wall. It felt like I had built a Jenga stack of complexity in order to have a 'simple' interpreter for state machines. But a language is never less complex than the tools you provide to debug it. And Inspector Widget fell short when trying to explain the issue (partly because it is surprisingly not yet working on Dreams.nds)

Une intuition pendant mes vacances ... j'ai retracé la machine d'état de mon scorpion-cyclope. J'ai bien identifié deux ou trois incohérences, mais rien qui ne conduise au bon comportement une fois corrigé.

Oui, je sais aussi, par rapport à ce que je bricolais sur le côté pendant mes semaines de vacances, c'est maigre. C'était des vacances un peu ... particulières.

Puis hier, j'ai repris la machine d'état de pendat. Lui aussi, il réagit quand il fait demi-tour en se prenant un mur. Et il n'est peut-être pas parfait, mais il marche en général bien mieux que cette satanée carapace.

Alors que scorpeye tentait de reconnaître l'absence de sol à l'aide d'un testpoint, pendat se contentait de "dire" "ah bin si la vitesse horizontale est tombée à zéro, c'est qu'on s'est pris un mur. Sinon, c'est qu'on a plus de sol. C'est forcé."

I found only a small evening of ndsdev during my summer holiday this year, and I used it to map the state machine of Scorpeye. It helped me finding a few weird stuff, but it would not make things run properly enough, unfortunately. Then I realised past Inktober that I already had a 'working' monster that bounced off walls. That was the running pendat. And I started mapping its state machine too (granted, after all these years of dsgametools, I should have given myself a tool to make that automatically). To my surprise, it almost never used the same tricks to perform the same task.

For instance, I used a TestPoint below scorpeye to tell me whether there was ground underneath when it claims it failed to slide on the ground. But this is unreliable because it checks only one point to decide for ground while the WalkController checks the whole surface. Instead, the pendat would test whether it came to a halt horizontally. If it did, that means there has been a wall. Otherwise, it bets there's no ground left.

Same with fall/slide transition: the scorpeye tried to use a testpoint to know whether it FAILed because of a ground. Pendat code author (past self) knew the only thing that can make GobGravityController FAIL was a ground. Being stopped by a wall triggers an event. That means no testpoint validation is required.

Finally, I gave myself an extra variable (there are still plenty available for scorpeye) to remember the sliding speed so that we can bounce walls without having to rely on an ImpactController to save the last speed, because so far I don't think GobWalkerController is an ImpactController. It requires to double some states (like left-thrown vs. right-thrown), but that should not be a big deal.

Still, there's one thing that I'll need to fix with unit testing: from times to times, being stopped by a wall while 'walking' doesn't make the move FAIL, but it does clears the speed. Pendat doesn't suffer for that because it has an "increase horizontal speed" statement in its running states that prevents the speed to stay null. I had to add the same statement to the shell, but it shouldn't be required. that's a todo item for XMAS, I guess.

Il me fallait un double-état pour la carapace lancée, une variable supplémentaire pour retenir la vitesse à la place de la 'variable d'impact'... ce genre de choses. Mais il y a un élément suspect. Pour qu'il n'y ait aucun soucis, je suis obligé de mettre une instruction forçant la carapace à accélérer. Sans ça, il reste des situations dans lesquelles je retrouve ma carapace toujours dans l'état "on glisse vers la droite" mais avec une vitesse nulle est un mur juste à ça droite.

Comme si GobWalkerController avait un bug qui l'empèchait parfois de signaler l'échec (FAIL) même si la vitesse tombe à zéro. ça, ce sera une tâche pour un test unitaire.


Super Mario Bros 5

Ai-je eu raison de snobber Mario Maker ? jusque là, je n'en doutais pas. Parce que jusque là, les niveaux présentés étaient essentiellement des niveaux quasi-impossibles ou des productions fafelues avec des canons à Bullet-Bill accrochés sur le dos d'un parakoopa qui lancent des spineys ... ce genre de choses. Mais l'ami Antistar nous a annoncé il y a quelques jours qu'il allait tenter de traverser un jeu qui a retenu mon attention: Super Mario Bros. 5.  

Il s'agit toujours bien d'un titre Mario Maker, mélangeant essentiellement les thèmes SMB3 et SMW (miam) dont l'auteur cherche à rester fidèle à l'esprit des jeux de Nintendo tout en proposant des idées et du contenu original.

Replay Twitch du 29/09/2022 avec un let's play de Super Mario Maker 2 dédié au super monde "Super Mario Bros. 5" conçu par MetroidMike64, qui contient 8 mondes de 5 niveaux chacun. En voici le code : 0G9-XN4-FNF Session de jeu effectuée et streamée depuis une Nintendo Switch.

N'ayant toujours pas Mario Maker2 (essentiel pour tester ce titre puisque le 1 ne permettait pas encore de lier ses niveaux sur une map), je me contente donc du stream d'Antistar. Et au milieu de pas mal de bonnes idées, je me rends compte que les niveaux "maison fantôme" offrent probablement un excellent point de comparaison pour le type de niveaux qu'il faudrait que je réalise pour la pyramide de Bilou's Dreamland ...

Voyons un peu ... on y retrouve régulièrement des portes en apparence difficiles d'accès qui nécessiteront de récupérer un objet pour les atteindre. D'autres objets qui *pourraient* les rendre accessibles (les fantômes n'auraient-ils pas envie de se changer en blocs ?) sauf que non, et des objets qui pourraient aussi (les plantes grimpantes, sauf qu'ils ne sont pas au bon endroit.

On y retrouve également des portes *carrément* inaccessibles. enfermées. Des portes pour plus tard qui détournent l'attention du joueur. En particulier parce qu'il ne sait pas dire à l'avance s'il s'agit d'entrées ou de sorties.

Et pour compléter le tableau, des sorties d'écrans qui sont ... hors de l'écran et que la caméra tente de garder invisible le plus longtemps possible.

 

Sunday, October 23, 2022

Ori and the winning strategy

Immobilisé, incapable d'enregistrer des chapitres de HPMOR à cause de ma toux et ma fée en formation plusieurs soirs par semaine, tout ça après que j'aie redémarré une partie d'Ori and the Blind Forest, il n'en fallait pas beaucoup plus pour que je me refasse le jeu presqu'en entier. Mais suite à un bug casse-pied, j'y rejoue sur un nouveau compte de ma Switch, plutôt que "à côté" de la partie terminée. Pas question, donc, de retourner jeter un œil sur la carte d'une partie plus avancée pour renifler où sont les power-ups cachés et améliorer plus vite ses compétences.

Vous vous doutez bien que, depuis le temps, je n'ai pas non plus retenu leurs emplacements. Mais par
contre, je n'ai pas oublié que le jeu propose les compétences "voir les cellules de vie sur la carte" et autres annotations du genre. Ma stratégie sera donc la suivante :
  • mettre tout sur la branche de compétences qui mène aux cartes complètes, dès le début du jeu, et ne regarder aux autres qu'en cas d'absolue nécessité.
Une autre chose que je n'ai pas oubliée : le terrier noirracine, avec son DASH (disponible dès le téléporteur avant la baignade interdite) et surtout sa petite lumière-à-lancer (disponible presqu'immédiatement après), vu que je sais qu'elle va permettre de déverrouiller l'accès à pas mal de points de compétence "gratuits".
Eh bien cette stratégie s'avère plutôt gagnante, puisqu'à l'arrivée à l'entrée du 2eme "donjon" du jeu, j'arrive à débloquer malgré tout le triple-saut, tout en pouvant échanger 1 point de Mana contre 2 points de vie lors d'une sauvegarde. J'ai aussi tellement de points de vie que les obstacles qui pourraient me one-shotter sont devenus rares, et tellement de points de Mana que je n'ai presque plus besoin de me retenir de faire des Sauvegardes. Bref, on est loin du feeling de "die and retry" injuste ressenti lors de ma toute première partie.

Friday, October 07, 2022

Finally doing some pthread stuff

For years and years, I've staid away from multi-threaded programming. Not that I dislike threads per se: I once made a multi-threaded micro-kernel myself after I spent countless hours studying IA32 Task State Segments. But who needs threads when you have two ARM cores, hardware interrupts for driving your sound DSPs and proper multi-layers video chip anyway ?

Even for network / system programming, I tend to prefer use pipes or socketpairs over threaded stuff. They strace better. You can actually see the flow of acknowledgements between entities. For most things, this is preferable over raw performance.

But a couple of years ago, I've been thrown in a pool where threads are already there and I need to swim with them. Parts of the pool use boost abstractions and are usually not too hard to work with because my colleagues did a great job at building robust RIAA things around those abstractions. But other parts of the pool use plain pthread + plain Windows thread/event/locks API. And as you can guess, upgrading corporate project to use C++11 threads is usually not easy (not that I know these any better, though).

One function that is used a lot in that code is pthread_cond_timedwait(). And there are a few things you must not do with that:

  • do not call it if you're not holding the mutex argument
  • a corresponding pthread_cond_signal is lost (not buffered) if no one is waiting on the condition at the moment of cond_signal

(more to come)