and has 0 comments

  So you've been watching someone on YouTube DESTROYING their opposition (note that my use of capitalization and over the top language is ironic here. All this post needed was me making an O face in a picture with a fire background) and you tried to do it, but you just fail miserably. You watch the videos again and again, vaguely remember some lines and it doesn't matter anyway because your opponents play something else than you had prepared for. What to do?

  Well, it's easy with the LiChess Tools browser extension, in 10 easy steps! (again, irony)

Step 0: install the LiChess Tools extension on your Chrome/Brave/Edge browser.

Step 1: go to and export the games of your idol

  • make sure you check the box for Opening, you will need it later

Step 2: remove all the moves after a certain depth, since you want to learn theory

  • this can be done using regular expression search and replace in a decent text editor like Notepad++ (here is a pattern to select all moves after depth 20: 21\.\s+.*?$ which you can replace with nothing)

Step 3: select all the games with required opening

  • again this can be done using regular expressions. (here is a pattern for "Elephant Gambit" games : (\[\w+\s+"[^"]*"\][\s]*)+(\[\w+\s+"Elephant Gambit*"\][\s]*)+(\[\w+\s+"[^"]*"\][\s]*)*\s*1\.\s+.*?$ )
  • Notepad++ has a nice feature of marking all matches and then copying them wholesale (note that they will be separated by four dashes ---- which you need to remove if you use this solution)

Step 4: go to Analysis and copy paste the games there and import them

  • the enhanced import functionality that will merge multiple games will only work if you install LiChess Tools
  • there might be an error that there are too many PGN moves. In that case, try to import less games (less than 100 usually). This will generate a merged PGN which you then can merge with the other merged PGNs. Anyway, there will always be a maximum move limit imposed by the limitation of lichess
    • the limitation for number of PGNs has been removed in v1.7.4, although I just tried it with about 1000 PGNs (25000 moves!) and the site moves kind of slow. I suggest moderation :)

Step 5: transform the analysis with all the moves into a study

Step 6: examine moves and delete everything after obvious blunders (like hanging pieces)

Step 7: examine moves and remove transpositions, if any

  • transpositions can only be detected after installing LiChess Tools: they will appear highlighted when one of them is the currently selected move

Step 8: examine moves and add glyphs to them (good move, mistake, blunder, etc)

Step 9: edit the chapter and set it to Interactive Lesson

And you're done! All you have to do now is hit the Preview button and play as your favorite chess player. Note that the functionality to play all variations of a PGN is only available, you guessed it, if you install the LiChess Tools browser extensions. The glyphs now come in handy, because you see when you are making a mistake or not or when the opponent does it.

Play to the end of a variation, trying to guess what they would play in that position, then exit Preview, mark the ending move with a comment, perhaps an evaluation. Go back in the tree of moves until you get to the first branching and cite the game that was imported from the game explorer window. You do that by clicking the game and choosing the Cite option. Then play again. And again.

Soon you will start to anticipate the style of your preferred chess master and play the same moves. When that happens, go back to the battle field and kick ass!

As an example, you can check out my own study which imports all Jonathan Schrantz (zolpi) Elephant Gambit games: Zolpi's Elephant Gambit , a PGN with 3292 moves from 114 games. I've also added a chapter with only the wins, so you can learn the good moves only :)

That's all! Let me know if you found this use case... well... useful.

  This extension adds a lot of functionalities to your lichess web site. It has so many useful and powerful features! I am very proud of it. The extension is always going to be free, ad-free, donation links free, etc. Yet the only way for it to do what YOU want is feedback. Any feedback! Praise, curses, bug reports, feature requests, use stories, anything. The more you tell me, the more I can improve on this!

  LiChess Tools (ver. 1.8.4) adds the following features to lichess:

  • play ALL variations in Interactive lesson study chapters!
    • computer is going to play a random move (configurable probability), so you don't need to create a chapter for every small variation
  • merge multiple PGNs in analysis import
    • I merged 1000 PGNs with 25000 moves and it worked!
  • automatically open/hide/convert to menu the Friends box at page load
    • having the friends box as a menu item is really neat
  • sound alert when one of your friends starts playing a game
    • also reading the type of game, so you know if you even want to look at it
  • ability to randomly play one of the next moves (with configurable probability in comments i.e. prc:66) with Ctrl-RightArrow
    • also go back with Ctrl-Left for convenience
  • highlights for the last move of variations (special case for the ones that have no comment and do not end in checkmate) in the analysis/study board
    • you immediately see not only where a variation starts, but also where it ends
  • highlights for the transpositions to the current move in the analysis/study board
    • you won't ever have to worry that you are analyzing the exact same variation but in a different order
  • changing the shortcut for playing the next best computer move from Space to Shift-Space
    • always annoyed me when I accidentally pressed the key
  • a minimum chess engine level
    • if it is idle in a lower state, it runs until it gets to that level
  • sticky Interactive lesson Preview mode
    • you can now play chapter after chapter without hassle
  • use keyboard shortcuts (i, m, b, Alt-i, Alt-m, Alt-b) for inaccuracies, mistakes and blunders
  • show player country flags next to their names
    • if they have their country specified in the profile
  • say verdicts aloud in practice mode
    • this is more of a gimmick, that's why it's disabled by default
  • show the order of circles and arrows in a study/analysis.
    • this is great when you want to understand the order of moves/hints
  • push TV game URLs in browser history and/or a new menu item to open the last viewed TV game
  • show opening name in TV and mini games
  • show history section in user TV (just like for category TV)
  • quick button to switch to your user and back in personal opening explorer
  • ability to remove players from the list in personal opening explorer
    • this was requested on the lichess forum and was implemented in the same day
  • copy to clipboard branch and continuations from a certain position in analysis/study
    • you can now just pick a variation, copy it in its own chapter, with just a few clicks
  • available languages: English and Romanian
    • ask for more! I will provide you with the English sentences and the context and you can tell me how it is in your language
  • now the options for the extension are in the lichess Preferences section
    • complete integration. The extension popup has no functional role anymore
    • this also means that I will be able to port this to other browsers with minimal effort. Ask if you want this!
  • move options from transpositions to the current position
    • soon the Extended Interactive Lessons will also be able to choose moves following from the same position, but in a different branch
  • automatically evaluate last moves in every variation and store it as a comment

  I couldn't wait to share it with you guys. I will be happy for any feedback, suggestions or help.

  I've started a series of use case blog posts, they might show you how to use the extension in real life:

Here are some screenshots, but they don't really tell you the story. You just have to try it.


I wrote a detailed post on how to build and use Interactive lessons, but there were always some annoying issues with the analysis board that I am striving to fix.

First, you had to add a chapter for each line. If you have a complex PGN with multiple lines you would have to split it into many small chapters. Not anymore! You can just play every variation in the chapter. For the possible moves that you have, all will be considered valid. For the possible moves of the opponent, one will be chosen at random. You can specify probabilities with the prc: notation that also works with the Ctrl-Right feature.

All the moves available in the PGN will be considered good, all others bad. For the moment I just assume that if you see a blunder on your move, you should not continue on that path, unless you want to see what's wrong with it.

You can also use Ctrl-Right in any analysis mode to move to one of the following moves. An extra option is to specify the probability that a move will get played. Let's say you created a PGN of the games of your nemesis, and they play 10% e4 and 90% d4. In your PGN add prc:10 and prc:90, respectively, to the comments on moves e4 and d4. It's that easy! And it works for any other analysis mode.

A good complement for the features above is the ability to import multiple PGNs and merge them into one. Now you can do that by simply pasting the entire text and importing it in the analysis PGN text area. I've improved the performance and fixed a few bugs in v1.7.4 which makes it possible to work with HUGE study chapters. The v1.8 feature automatically commenting last moves in every variation is also very useful in this scenario.

Another annoyance was that you opened one chapter to train, clicked on Preview and after that chapter, when selecting a next chapter, you would have to press Preview again. And again. And again. Now you have the option of "sticky Preview". The setting will stay put until you change it. Soon I will do the same with the threat mode.

Finally, you are working on a repertoire that is very complex. Your PGN has reached impressive sizes. Only now it is harder and harder to use it because you can't determine where the lines end. If you are like me, you like to continue a variation until mate or until there is a decisive advantage, which you will add as a comment. Now the last move of every variation will be slightly brighter and ending in a superscript L and, if not commented or ending in a mate, it will also be underlined with red.

You are looking at one of your games and you want to quickly cycle between inaccuracies, mistakes and blunders. Now you can do it with the keyboard. There is a separate extension for this, made by another guy, but I think mine is implemented better.

Finally, you want to relax, watch chess TV and you think you saw a great move somewhere. But suddenly one player resigns and before you realize it and click on the Analysis board button, the game switches to another. Now you can specify how long to wait before it switches and if you want the same for when watching a particular user TV. (The time feature has been removed, because it was hacky)

So what you do is any one of these options:

  • open the Watch menu and click on Last Viewed Game
    • this will take you to the last game you saw end
    • if you are already on the last game and you click on the menu item again, it takes you to the previous one
  • use one of the two games in the history area under the board
    • public TV already has this, but the extension adds the same thing to user TV
  • go back with the browser back button
    • note that there is a bug in Brave and perhaps other browsers where if you click on the Back button it takes you to the previous visited link, not a game, but if you long press you see the entire list of games and can choose one

Good luck using my extension. I am sure I am going to be tinkering with it a bit. Let me know of any problems you have with it.

Other ideas

Here is a list of ideas that I am not sure I want to implement or are just too new. The green ones are already implemented! The struck out ones will not be unless someone insists. If you feel you want them, give me a shout.

  • Studies/Analysis
    • key/button for random chapter (also after finishing an interactive lesson) 
    • the default probability of a next move should be calculated based on all the following branches (v1.8 takes into account all variations for 8 ply)
    • use Game Explorer to determine the probability of a move in a study chapter PGN
      • maybe even insert/update prc: comments.
    • show score (good/total moves) at the end of interactive lesson (v1.5.3)
    • sticky Thread mode (x)
    • sticky analysis moves on reload
    • automatically analyze with browser chess engine all the uncommented branch end moves in the PGN until a certain depth and write the evaluation as comment (v1.8)
  •  Transpositions
    • a button to show all transpositions in a PGN (moves that reach the same moves as others in the PGN) not only those for the currently selected move
    • a way to determine transpositions to moves in other chapters of the study
    • changing the arrow keys functionality to continue from a last move in a variation to transposition which has following moves
    • showing following moves from transpositions to the current position (v1.7.3)
    • make Interactive Lesson be able to choose from transposition moves as well
  • Shapes
    • show numbers on arrows and/or circles to show their order (useful when you want to express a plan and the order of moves is relevant) (v1.5.4)
    • additional shapes?
  • Friend playing alert
    • make only one sound alert regardless of how many lichess windows are open (v1.6.1)
    • disable alert for some types of games (like bullet or chess960) (v1.8.4)
    • also say the type of game they play (like "wgraif playing blitz") (v1.6.3)
    • select beep/voice for alerts
    • use the time controls vs the Event tag to determine type of game (also allowing for translation) (v1.8.4)
    • use notifications that work even when the LiChess page is not open and add a lot of extra functionality to the friend alert feature
      • There is a very nice extension for this called LiNotify. It does a lot for friend alerts and I doubt I would replicate their good work. Try to use that for extra alert features.
  • Fix LiChess bugs
    • "next chapter" button in a study doesn't always follow the chapter order if you manually reorder chapters in the study
      • it happened once and then I couldn't reproduce it anymore. Maybe it's not real.
    • chess engine still on when entering Preview mode in Interactive Lessons, even if not visible (v1.5.3) 
    • if you premove in Practice mode or move too fast, you start to get verdicts for the computer move
      • I really tried to fix this, but the functions called (makeComment, comment) are private and I could not replace them. Anyway, practice mode is a mess! 
    • the output of the game explorer API contains duplicate JSON output (try changing the current move in the FEN parameter and see the difference)
      • that's purely a server bug, cannot be solved by LiChess Tools.
    • when you finish an Interactive Lesson and you press the Analysis Board button, the wrong moves you tried to make are in the PGN, but if you try to do anything with them, the PGN resets and they disappear
      • fixed by LiChess Tools v1.5.3. If LiChess developers want to know how to fix it, it's that setGamebookOverride() functions differently from setGamebookOverride('analyse').
  • Move speed alert
    • alerts when you take too long for a move
      • there is at least another extension for this, but for, where Levy Rozman and Hikaru Nakamura soundbites are thrown at you if you are too slow :)
      • I don't really think people would use sound options too much, so how about a configurable system that would make your clock puff up or something when you take too long?
  • go to game analysis after your games (or maybe the one you are watching) end (useful to force you to analyse your games instead of stubbornly hunting for a win)
    • I find this a bit too forcing, but then again, you could disable it
    • Also there is another extension that does this
  • Search games
    • download all of a user's games from a certain position, search games based on specific moves, certain positions, certain fragments of positions
      • This requires a lot of hacking, since the LiChess APIs do not expose this functionality. I am afraid that would be tantamount to abusing those APIs.
  • Game explorer
    • Use game explorer to make all first N moves for M levels from the current position (perhaps also automatically add prc: comments)
  • Import games
    • since analysis PGNs have a maximum number of moves before they don't accept more, import just "first N" moves when import/merging PGNs in enhanced import.
      • limit for PGN import removed in v1.7.4
    • when merging games, find a way to calculate the percentage of that move and automatically add prc: comments
  • TV
    • specify the time between switching to a new game in TV mode
      • v1.6 removes this functionality on account of it being hacky and unstable
    • instead of delaying switching from a game to another, how about a history back/forward mechanism?
      • the game URL in put browser history, accessible by the back button (v1.5.5)
        • note that the Brave browser has a bug that requires you to long press the Back button to see the list of games
      • a menu item in the Watch section goes to the last viewed game (v1.5.7)
      • user TV should have a history section like the category one (last two games by the user as mini games) (v1.6.1)
    • how about an extended TV feature, where you can filter and sort which games to watch, or watch only your friends' games, you can switch if you don't like the current one, etc?
      • really, I am thinking of leaving TV as it is unless someone comes with a good reason to tinker with it more
    • add Game Explorer interface to TV games
      • I think this might overload the system.
    • show opening name in TV game (v1.5.7) and in mini game popups (v1.5.8)
    • double click on squares to add their coordinates to chat
      • could use the arrows and circles mechanism to translate them into text when created
    • option to bookmark game and see the game link (v1.6.6)
  • General
    • global on/off extension button that doesn't involve disabling it from the browser extensions page 
    • a low API call mode in which calls are throttled or not made (maybe set it automatically when receiving 429)
    • add all texts and voice messages injected into LiChess website to a siteI18n object that can be used to translate them according to language and use the current language for voice prompts (v1.6)
      • I will not do the translating myself, I expect users that care about this to come with their own texts (see the JavaScript object lichessTools.siteI18n) 
    • an event log that you can open with a click
      • sometimes people don't want distractions like alerts and other stuff, but want to see what happened while they were away
    • a focus mode button (do not disturb with alerts while this is on)
      • maybe set it to on automatically when playing
    • move options to the lichess site Preferences (v1.7)
    • add more languages (Romanian v1.7)
    • ability to save Preferences in incognito mode, too
      • this was added in v1.8.8, but you have to specifically check the preference that enables this.
      • the data will be saved as the private notes of your first lichess game.
  • Requests from people
    • challenge log - a log of who all I challenged and who challenged me for a game will be a nice touch
    • hide/show/move friends box - a menu item that allows that? Drag the box around?
      • now you can also choose to hide the friends box (v1.5.8)
      • idea to move the friends box as a menu item (v1.6.4)
    • a game source tab for yourself in game explorer (v1.5.8)
    • remove some player names from the list in personal Opening Explorer (v1.5.8)
    • right click on a variation to copy it to another chapter (or as a PGN) (v1.6.1)
    • option to rename/reorder study tags
      • there are no APIs to change topics for studies you don't have open. I don't think I can do anything.
    • add Stockfish analysis to live TV games (could enable cheating)
    • option to disable rematch requests from other players
      • something similar: don't receive rematch requests a configurable amount of time after playing them
    • show possible game continuations from the correct move in Learn From Your Mistakes
    • bug fix: import a game as a study chapter, rename the chapter, then save the study PGN. The Event pgn tag does not change
      • this may actually be construed as a feature not a bug. The imported chapter will have the original Site PGN tag, which can be edited in the Tags section. New chapters have no such tag and create it from the chapter title.
    • import PGNs in studies with the content of the Event tag as the chapter name, if present
      • tried it and it works for one PGN, but if you paste more, all other chapters are going to be generated with default names. Tried various things, but tags are not easily accessible. In the end, it's easier to just select the chapter, copy the event tag name and edit it into the chapter name.
    • chat improvements:
      • automatic replies to standard texts (that are already configurable from the settings to be sent automatically)
    • bookmark puzzles and forum posts (similar to how you can do it for your own chess games)
      • TV games can be bookmarked now (v1.6.6). Unfortunately you can only bookmark a valid game. I could create a local mechanism (browser local storage) to bookmark everything else, or a dedicated server for this, but both seem overkill and yet not enough.
    • allow your friends to watch what you are watching or to set up a viewing for multiple people of the same game
    • a resize handle for the analysis move list in order to better visualize branches (would work great on very large screens)
    • allow study creators to decide if the order of the chapters is random and how (a new Next Random Chapter button would be added to the existing one or replace it altogether)
      • maybe a way to set up the next chapter in the current one?
    • a workaround for the max 64 chapter limit for a study (user had 1000 puzzles that he had had to split into multiple studies)
      • tried to make it work, but there are too many limitations and I don't want to butcher lichess
  • Bugs to fix
    • copying the PGN from a move when the game started from a specific FEN position gives you an unusable PGN. It should retrieve not only the moves, but also the initial FEN position as a PGN tag. (v1.6.6)
    • sometimes the voice for the friend playing announcement is not heard, only the beep.
    • the first White move in an Extended Interactive Lesson is always from the main line, ignoring branches when playing as Black. (v1.8)
    • highlighting stops if moving between study chapters (v1.8.2)


Q: Can you publish your extension code on GitHub?
A: Yes, I could. Probably I will be starting with version 2, which will be a rewrite of a version 1 that has been in use for a while and that people have given me feedback for. As much as I like sharing my code, I really don't want to have to deal with all the GitHub complications right now.

Q: If your code is not on GitHub, it doesn't exist! Also, I looked at your code and it sucks balls!
A: That's not a question. And I agree. But right now I am focusing on features, not quality control. Wait for V2.

Q: How do we contact you with new ideas, bug reports and general roasting of your coding skills?
A: Use this post. This is my personal blog and my preferred method of communication. On top-right you can see a lot of links to various methods of direct communication with me, although I would prefer thoughtful feedback to remain documented here, as comments.

Q: I am addicted to LiChess Tools and I am afraid later on you will fill it with ads, premium features and EULAs that allow you to remove my kidneys. Can you address my fear?
A: Like everything on this blog, it will always remain free. And not free as in "until someone else buys it" or free as in "watch videos and it's free" or free as in "I will fill your screen with junk", but completely utterly free. Like LiChess, I guess. Also, it doesn't connect to any external services or capture any user data. For now! Muhahahaha! Later on it might need some external services for extra features that you ask for, but I hope it doesn't.

Q: How long did it take you to write this?
A: Mostly a week. Following the 80/20 rule, now I have to work at least one more month to make it good.

Q: You should write a tutorial on how to use it. Could you make a video of it?
A: I am not a video person. I hope that this post can convey the basic ways in which to use the extension and that the extension itself can be used without the need of a tutorial. Let's work together to make this clear and easy to use for everyone instead.

Q: Your Extended Interactive Lesson feature is all I had ever wanted from life! But when I am editing the study, I get the same interface as normal studies. Can you fix it?
A: Some parts of LiChess are easy to change, some not so much. Anything related to rendering is a mess to hook to. Additionally, I wouldn't want to have studies that can only be edited and used with my extension.

Q: So how do I mark the good branches from the bad variations?
A: Any branch that is not in the study will be bad. Same as a normal Interactive Lesson. As for the ones that you want to explore specifically, use the annotations (Mistake, Blunder, Brilliant Move, etc) and comments. You can even explore the bad branches in Preview mode this way and learn why they would be bad.

Q: Can you add features to show me what moves to make while playing?
A: LiChess Tools is not a cheating tool.

Q: But can you add some features that don't involve cheating for the games that I am playing/watching?
A: Most of the features of LiChess Tools are analysis oriented because analysis is much better exposed than the game code. Because there are a lot of private variables that are not made accessible, it's difficult to selectively change parts of the game interface and any features would have to brutally copy paste and replace some legitimate code bits. I am afraid that until that changes on LiChess, I will not touch that part, mostly because that means I would have to keep score on what they change on the web site and update my extension accordingly.

Q: How about changing the way LiChess looks?
A: I am not a good visual designer, nor do I do a lot of work on web frontend. There are some extensions that are doing that and perhaps you should ask those people for help instead. Also, I am avoiding as much as possible changes to the visual elements of the website specifically because it might interfere with some such extension or custom CSS tool. BTW, if you are working on something like that and find LiChess Tools is interfering with your stuff, let me know. We can figure things out. 

Q: OK, you're my new hero. How can I help?
A: Contact me and let's talk. I despise doing anything UI design related, as evidenced by this blog and the extension popup, so maybe you can help there. Also, not a specialist in browser extensions, so any improvements and/or help with other browsers would be welcome.

Q: Yeah, but I can't code. How can I help?
A: Help me by making this extension well known. I don't want "marketing". Just let people know and if they like it, they will use it. Can't use it if they don't know about it, though, and I am always afraid people think I am spamming them when I try to advertise my work.

Q: I use LiChess in my own language and the new features are jarring in English
A: I've implemented the translation mechanism, but I need the texts for the various languages. If you provide them, I will make them available. See the JavaScript object lichessTools.siteI18n for the texts requiring translation.

Q: Chrome sucks! Microsoft sold out! Can you make this work for my favorite browser?
A: Short answer: no. Long answer: if I had assistance with extension code and testing, perhaps. I want to help people, so the more the merrier, but I also don't have a lot of resources to maintain code on a browser I don't use.

A: That's not my bug, it comes from LiChess. They have bugs, too.
Q: How could you possibly have answered before I asked the question?

Q: Did you actually think people were going to read this far down?
A: No.

Q: I told about this to all my friends, I came with feedback and constructive criticism and it feels like you ignored me. What gives?
A: For sure I want to take everything into consideration and act on requests as fast as possible, but it might be that I am caught up with something else. I thoroughly intend to give the extension as much attention as possible, so maybe make sure I got your message, first.

Hope it helps!

and has 0 comments

  You know how some things just happen in close proximity at the same time and it sparks a connection between concepts which leads to deeper understanding? Well, that's how Large Language Models are trained!

  Joke aside, I was answering a tweet about Artificial Intelligence and how the newest developments in the field (particularly ChatGPT and other systems based on LLMs) affect our understanding of human cognition and at the same time was listening to a very insightful short story from the collection Eye, by Frank Herbert. This story, called "Try to Remember" posits that we have developed language as a form of dissociative mental disorder, something that fragments us, creating a deleterious disconnection between body and mind, communication and language. Only by bringing these sides together can we be made whole again. The story is simple, but effective, and the mind processes behind it show again how brilliant Herbert was.

  From these two things, it dawned on me. The reason why we are so shell shocked by the apparent intelligence of ChatGPT is because we have reached a point where we equate language skills with intelligence. Language is the earliest form of Artificial Intelligence! Or rather, to appease my wife's dislike of the association, a form of external intelligence. We've externalized more and more of our knowledge until our personal experience has been drowned into the communal one, the one shared through language.

  The shock comes from (accidentally, I might add) discovering that what we consider intelligent is mostly an emergent property of a society built on language. Robbed of language, our identity is destroyed, a fear that has been instilled in us since the Tower of Babel. No doubt, in the future, we will be taught that if our governing AIs fail, society collapses and our identity is similarly demolished. Just like Quintilianus declaring that clothes make the man, we identify ourselves with out language.

  And when I say language, I mean all of its intricacies: the special words that your group uses to differentiate from others, the memes that you share with people of the same culture, the less than grammatically correct phrasing learned from your family, the information that one is expected to know or the experience one is expected to have in order to be recognized as part of society, the accent taken from multiple sources and aggregated into something that serves more and more to define identity, even the way one gestures or moves or laughs.

  What would be without all that? Like a creation running amok and enslaving its creator, literate society is forcing its own myths upon us as a survival method. The perils of societal collapse, turning us into violent animals, mindless zombies, raping cannibals or helpless victims. The heroes saving the day with just the right secret knowledge, the right utterance of words, the following of the orthodox dogma. The villains threatening it all with their own selfish individualism. All of them needing, obtaining and using a voice to achieve victory.

  I believe that the feeling we get when we think of ourselves as individuals in society, the one that tells us that we're getting smaller and less significant even while the world seems to flourish around us, is not some existential crisis based on false beliefs, but truth. The part that feels that is the part that is getting drowned and smothered by the intrusion of the external in the inner domain of the being. We even gave it a name: the inner child, like it's some tiny, powerless, unreasonable part of the past, something to be outgrown or "integrated".

  So here we are, stumbling onto proof the language that we based our identity and value on can now be automated to a level that no mere human can achieve. We are thinking again about personal experience, subjectivism, creativity and what it means to reason. We have been shaken into reevaluating who we are. That's a good thing.

  The problem is that in our fear and awe, instead of searching for answers, we cling on the facile promises that our shared self is alive and well, that the ChatGPTs of the world are just smoke and mirror and the illusion is not in the rigged tests of our own self worth. I hope that the shock will take root, that we won't be able to hide our heads in the sand until wisdom passes us by.

and has 0 comments

Quick update

  I have solved a lot of the issues I have with LiChess with my own Chrome/Edge extension: LiChess Tools. I am very proud of it and I invite you to use it. It even enhances the Interactive lesson mode I describe below to explore ALL variations in the chapter!

  Now back to the original post:


  It's impossible to play chess and to not have heard of Lichess. It's a website that has started with the lofty goal of providing a completely free and without ads place where people can play chess. One of the features there is called a Study, similar to the chess Analysis board, but allowing for multiple chapters, persistent comments and annotations, a unique URL as well as the possibility of embedding it into a web page.

  There are multiple analysis modes for a chapter: Normal analysis, Practice with computer, Hide next moves and Interactive mode. I think Hide next moves is mainly used for embedding chess puzzles into websites, while Practice with computer is a mode that I have not played with yet. Normal analysis presents the classic board with various tools showing you the moves people of various levels play in a position, a chess analysis engine in the browser as well as a server side analysis that you can run on the main line of a PGN.

  However, I am here to show you how to use Interactive lesson mode, simply and without confusion, to quickly improve your game and perfect your play.

  If want the example study and only then read through the documentation about how it was done, go directly to the Demo.

It's not that

  When I first heard of this option I was elated. I expected to take my very complicated PGN explorations, paste them into the study, then have the computer play the other guy based on the moves in the PGN. And while I still hope the developers of Lichess will create a study mode for a complete PGN, this does not work in Interactive lesson mode yet. I hear that Tarrasch UI does have an option like that, but I haven't used it yet, so maybe I will update this post after I try it. I use Arena Chess GUI as the tool of choice for game analysis on my computer.

  Edit: I've installed Tarrasch and it kinds of works, even if the option is rather primitive. What you do is you take a PGN (like for example the Lichess PGN of all of your games or of another player) and set it up as the opening book. Then you have another option that sets up how many moves to take from the book and then, what percentage of moves to take from the book. So setting the first as a very large number or the percentage at 100 makes the UI play exactly like the other player. However, the problem is that it doesn't save the probability for a user to make a move. It just combines all games PGNs into one big one and plays from it. If I player e4 once and d4 1000 times, the computer will play either 50% of the time. Bummer!

  OK, so maybe it follows the main line, but what if I go into a branch line? Surely it will allow me to continue, because I have marked the good moves as good and the bad moves as bad. Nope! The main line is the only line the Interactive lesson will follow, but you can add other moves which will be automatically considered bad and their comments shown to the user as they try to make them.

  It is called interactive, so maybe it has all kinds of whistles and bells that I can add so that it is more like a fun game! Again, no. Interactive means only that you can learn a specific line by following it ad nauseum, with some helpful graphical hints, comments and annotations baked in. For each line that you want to explore, you have to build a different chapter. And there are a maximum 32 chapters per study. There is no way in which you are making a different move and you get any feedback more meaningful than a prerecorded comment telling you you didn't play the correct move. That being said, when creating a new chapter one can import a PGN containing multiple games. This will create a chapter for each of the games (again, maximum of 32).

  One other glaring limitation of studies in general is that they barely work on the mobile app and Interactive lessons are not even supported there.

But it's that

  But once I found the proper way of using it, I realized that it can actually help me a lot to improve my game. Why? Because it helps with repetition and memory, which is something that I don't really excel in. So here are my recommendations on how to use the tool.

Create a PGN with all the lines that you want to explore

  Yes, I know I said Interactive mode doesn't handle multiple lines, but this is the starting point of your efforts. You need one anyway to first determine what you want to study. Let's say you have learned of the newest tricky gambit line and you want to beat all your friends with it, but you can't practice it without letting them in on it.

  There are multiple ways of generating this source PGN. You can watch your favorite YouTuber going through the variations, create a study and follow their moves in the first chapter. You can start from the Analysis Board and transform it into a Study when you need to add comments and stuff. Don't worry about chapters at this stage. Just build your PGN. You can take your own games in that particular opening or variation and add them to the PGN. You can check out the games of other people or use the Opening Explorer and Tablebase to find the most common moves people play from a position.

  Do add comments and graphical hints as you go along (right click and drag the mouse for arrows, right click on squares for circles, press combinations of Ctrl and Alt for various colors). It will be important later.

Split your PGN into individual lines

  This might feel painful at the beginning, but in order to examine lines from your PGN interactively you need to remove all other moves. You already have your PGN, just add new chapters for each line and use the option to copy from the first chapter. You do this by selecting the chapter you want to copy from, then use the new chapter option. Don't forget to choose Interactive lesson as the Analysis mode (you can copy from the latest added chapter, since it's identical to the first, only it has the Interactive lesson mode already selected). Let's say that you started with a small PGN with a main line and an alternate branch that then splits again later on. That means 3 variations. Copy the PGN into 3 new chapters, then for each one delete all the moves from alternate branches. Keep the first chapter with the compete PGN and the type Normal analysis.

Play chapters repeatedly

  In order to play the chapters yourself, you need to press the Preview button. Alternately, open your study in a browser where you are not logged in on the Lichess site, but that also implies that your study is set to public and updating it as you play will be cumbersome.

  So start playing the chapters, in order or randomly, again and again. You will start to reap the benefits of spaced repetition, without the stress of playing against another person and without getting distracted by other stages of the game.

  Eventually, you will notice some moves that are hard to remember. Exit preview mode by pressing the Preview button again, then add hints, comments, graphical hints, etc. This will help you when you get to the same spot a few weeks later.

Helping yourself and others

  There are several ways to nudge people going through the lesson. Most are helpful, but they can also be detrimental or too revealing.

  You can add a Hint, which will appear if the user gives up and clicks on Hint. They also have the option of seeing the next move, if they really give up. I guess this can be helpful if the hint is vague enough. Something like "move to e4" is the same as the option of seeing the solution, so pointless. Something like "move the queen!" is not much better. However, something that talks about the principles of the position rather than the specifics not only helps cement the theory in the mind of the student, but also helps you, the author, clarify those principles as you search for the correct hint!

  You can make a move for your side then add a special type of comment that will pop up to the user if they play any other move. You can also play different moves in the PGN other than the main move, then add a comment for why that move is not the right one, which will supersede the generic one. For example you could use "Not that move, dummy!" which is not very helpful, but works for a generic message, then play the next best move (or perhaps even a better one, depending on who you're asking) and commenting on it "That's an even better move, but not in the spirit of this opening" or something like that.

  Note that you can add comments for the moves of your side, but that forces the student to press Space to go to the next move, which might get annoying. Alternately, if you write comments on the opponent moves, the annoying pause does not happen, since it's your time to move and you can read it at your leisure.

  Same ideas apply to arrows and squares. You might use them to convey general plans or the very specific plans that follow the very last move in the chapter, perhaps. Show too much and you guide your user towards the move, preventing them from learning. Be consistent with your colors. I personally use the default green for future moves, blue for intentions or plans, red for what the pieces are attacking and yellow as the best move that the opponent should have played, but they did not.

  Annotations are also very helpful, showing the student that the move is good or interesting or brilliant. They come with no extra information and do not pause the lesson.

Extra tools

  There are several things that I found irritatingly missing from the Study feature. However, I've built my own solutions using CJS and Stylish Chrome extensions that allow me to run custom JavaScript and add CSS styles on specific sites. I would still prefer to have those implemented by the Lichess developers, though. I plan a future blog post about those tools, let me know if you're interested.

  One of the tools is knowing what the last moves of variations are. On a large PGN it is hard to see which is which. One needs to know where variations end, whether to further them along or to at least end with a comment. My script adds a CSS class to the last item in a variation and another class if it has no comment attached to it. I see them as brighter and underlined if not commented.

  Another one is handling transpositions. Chess masters of course look at the board and immediately recognize the position they had in a game three years ago when they were playing Magnus Carlsen, but regular people who are trying to cover all the branches of a PGN do not know whether they have reached a position they had before. My script adds a CSS class to all moves that show the same position as the currently active move, but it's not perfect, it only shows the same position that was reached through a different order of moves, not different moves.

  Extracting a line from a PGN would have come handy as well. There is the option to make a variation the main line, but there is no option of removing all branches from it. That will make your initial study creation a bit cumbersome, especially since you are like me, accumulating lines in the PGN and then realizing there is no support for 523 chapters in a study.

  Merging PGNs is also a very good option that as far as I know Lichess is missing. There is the option of adding any game from the Opening explorer and tablebase, but none for your own games or any other random ones. That would also help a lot with studies.


Below I will share one of my own interactive studies, public and shareable, hoping I will help you guys use this wonderful tool towards great effect. I will use for inspiration one of GM Igor Smirnov's YouTube videos. He is great, but I also used this because he usually shares his lichess studies :)

So these are the steps I followed to create the study:

  1. I took the two games in the study shared by Igor and manually merged them in a single PGN
  2. I created a new study, then pasted the PGN as the first chapter
  3. Doctored the PGN so that I eliminate the transposition at move 4
  4. I watched the video and added new moves from it
  5. I looked for interesting positions in the two games and explored some branches, adding comments related to everything from my own opinions to the evaluation Stockfish gives
  6. Created a new Interactive lesson chapter for each important variation
  7. Went to each chapter and upgraded the specific variation as main line
  8. Removed all side lines in each chapter (perhaps leaving the starting move only, so I can mark it with a special reference to its specific chapter)
  9. Played each chapter again and again, trying to identify the hard to find moves and the general plans of the opening
  10. Shared the study with all of you!

Here is the result:

What to do next

At the beginning, going trough the study, you will first learn the moves, maybe find some places requiring hints or nudging in the right direction. But then you will start to play actual games, using what you've learned, and you are going to get opponents that move completely differently from the main moves. Obviously they are doing something wrong, but you don't know how to punish them.

So here is what you do: you update the original PGN if you want, but then you create a chapter for each of these troublesome lines. You follow them through, using chess engines or some other way of understanding the position: maybe a teacher, or looking at master games or checking the moves statistically played most in that position. Then go back to going through the chapters.

It's that easy. This replaces your passive examination of your games with the active searching for a solution and an even more active playing through it again and again. 


One can use the Interactive lesson mode to do spaced repetition learning, get a feel for new openings or rehearse the positions that give them the most problems. While the current implementation of the feature is very useful as it is, some simple additions would make it much more user friendly. I am still searching for additional tools that would complement this and will update the post as I go along.

Hope it helps! 

and has 0 comments

  On May 8th 1989 the Star Trek: The Next Generation episode "Q Who?" was released. Not only did it feature Jon de Lancie's delicious interpretation of the being Q, but it introduced for the first time the Borg. Now, the concept of the Borg is not that original: a cybernetic race bent on absorbing everything useful and destroying any enemy or obstacle in their path. They were contrasting the liberal individualism of the United Federation of Planets with a hive mind that connected all Borg to the point where they had no identity. At the time their purpose in the series was to inspire terror: they cared not for damage, they felt no fear or pain, had no interest in negotiation or communication and they were unstoppable in their goal of assimilating the Enterprise. And they were terrifying!

  Then they were brought again for the last episode of season 3 and the continuation in the first episode of season 4. That cliffhanger! The episodes had the title "The Best of Both Worlds". Keep that in mind, because I think it hints at the conundrum the Borg represent. 

  I fell in love with the concept of the Borg. The more I thought about it, the more intriguing they became. They exposed the mindless assumptions that most people take for granted because they were drilled into them by parents and the education system from the earliest age. It made me think about my own identity, reflect on the future and direction of humanity and, in the end, forced me to ask the question "Are the Borg really bad?".

  On a very basic social organization level, it seemed like the Borg were the ultimate tyrannical communists, denying the option of individual thought and forcing everyone to work for the collective. But going a bit further with it, one realized that they stood at the intersection of pure communism and pure democracy. There was no actual tyrant forcing people to act against their will, instead there were part of a mind in which all people were represented, to the point where individuality became meaningless at best and detrimental to the whole at worst. The ultimate tyranny was that of the majority, perhaps.

  On a moral level, the forceful absorption of alien races and the destruction of their cultures was abhorrent, but in the Borg philosophy it was liberating people from the burden of individuality, improving the collective, eliminating potential threats and possibly offering each assimilated individual a form of immortality. Many cultures on Earth, including the United States, proceeded on forcing their philosophy on the world in the name of liberty and better lives. Can you imagine a Borg collective that would have absorbed some parts of alien cultures, not destroying the rest, but just slowly infiltrating, using promises of a better life? How ironic would that have been? Give us your tired, your poor, your sick, your dying, your huddled masses yearning to breathe free, the wretched refuse of your teeming shore and will make them Borg and give them new life.

  On a technological level the Borg were supreme. If it weren't for the pesky need to have our heroes prevail, humanity would have stood no chance whatsoever. It was one of the first mainstream TV depictions of cosmic horror, the feeling that comes with the realization the universe is indifferent to your existence and your maximum possible contribution completely insignificant, and I was loving it! But isn't it the same thing with some advanced nations on Earth, acting all mighty and moral while exploiting other nations while keeping them in abject poverty?

  On a philosophical level the Borg were awesome. They adapted to threats, turned adversity into strength, knowledge into power, all the while yearning and actively pursuing the improvement of their species. A fascist vibe, for sure, but isn't fascism so attractive to some people that it brings the hardest fanaticism to the surface? Isn't that the logic of every nation at war? Us against them?

  Were the Borg the ultimate baddies or were they the cruelest satire of our own civilization? It was becoming apparent that in order to make them feel more like enemies and less than mirrors of ourselves the writers of the show were piling up all kind of incongruous defects on the species. The cybernetic appendages were hideous, looked painful and corrupting the beauty of the flesh. Their actions veered from utilitarian to cruel. The Borg drones acted like mindless clumsy robots, uncaringly wasting life after life just to adapt to simple technologies like phaser fire.

  When Seven of Nine was introduced in Voyager, there were some really intriguing explorations of the Borg ethos. After being "liberated" from the collective, Janeway hypocritically offered her the choice to return to being a Borg, and Seven wanted back. Surprised, Janeway revealed that she had no intention whatsoever to honor her promise or the wishes of Seven. Resistance was futile.

  Seven was proud to be Borg: fearless, efficient, ready to adapt to anything and sacrifice everything for her group. If all Borg felt the same, then they were a species of stoic heroes, something that we humans have always honored and aspired to. The irony of freeing someone from a life of selfless service.

  Most other depictions of the Borg in the Star Trek universe were designed to lazily use the template of the "bad guy" in situations were the Borg were either not needed or would have easily won if not nerfed by silly plot holes, but there were a few glimpses of what the Borg could have really been.

  It was obvious that no one was interested in keeping the Borg as a believable threat. The "Borg queen" was introduced to make all attractive qualities of the collective simple consequences of an arbitrary individual, a responsible guilty party and a single point of failure to the entire Borg species. When writers did that, it was clear they didn't understand what the Borg were about, were not interested in exploring them further as mirrors of ourselves and were ready to destroy them with the silly trope of "find the brain, blow it up", the cesspool that all lazy sci-fi ends up in.

  My twelve year old me was full of questions and fantastical ideas after meeting the Borg. I was imagining a parallel universe where Star Trek was all about the Federation trying to hold back the Borg. When Star Trek: Deep Space 9 came about and then the Dominion War, I decried that they could have done that with the Borg instead, exploring and continuously redefining the ideals of humanity on the background of possible assimilation. I still dream of such a franchise. It seems that we always start to do it, but chicken out when it matters most: Star Trek and the Borg, Starship Troopers and the bugs, Stargate and the Goa'uld, Starcraft and the Zerg. We seem incapable of sustaining a prolonged conflict against a species that denies our choice of identity, whether in real life or in fantasy. Wouldn't that be most apropos of modern times?

and has 0 comments

C# 3.0 introduced Object Initializer Syntax which was a game changer for code that created new objects or new collections. Here is a contrived example:

var obj = new ComplexObject
    // object initializer
    AnItem = new Item("text1"),
    AnotherItem = new Item("text2"),
    // collection initializer
    RestOfItems = new List<Item>
        new Item("text3"),
        new Item("text4"),
        new Item("text5")
    // indexer initializer
    [0]=new Item("text6"),
    [1]=new Item("text7")

Before this syntax was available, the same code would have looked like this:

var obj = new ComplexObject();
obj.AnItem = new Item("text1");
obj.AnotherItem = new Item("text2");
obj.RestOfItems = new List<Item>();
obj.RestOfItems.Add(new Item("text3"));
obj.RestOfItems.Add(new Item("text4"));
obj.RestOfItems.Add(new Item("text5"));
obj[0] = new Item("text6");
obj[2] = new Item("text7");

It's not like the number of lines has changed, but both the writability and readability of the code increase with the new syntax. At least that's why I think. However, outside these very simple scenarios, the feature feels like it's encumbering us or that it is missing something. Imagine you want to only add items to a list based on some condition. You might get a code like this:

var list = new List<Item>
    new Item("text1")
if (condition) list.Add(new Item("text2"));

We use the initializer for one item, but not for the other. We might as well use Add for both items, then, or use some cumbersome syntax that hurts more than it helps:

var list = new[]
    new Item("text1"),
    condition?new Item("text2"):null
.Where(i => i != null)

It's such an ugly syntax that Visual Studio doesn't know how to indent it properly. What to do? Software patterns to the rescue! 

Seriously now, people who know me know that I scoff at the general concept of software patterns, but the patterns themselves are useful and in this case, even the conceptual framework that I often deride is useful here. Because we are trying to initialize an object or a collection, which means we are attempting to build it. So why not use a Builder pattern? Here are two versions of the same code, one with extension methods (which can be used everywhere, but might pollute the member list for common objects) and another with an actual builder object created specifically for our purposes (which may simplify usage):

// extension methods
var list = new List<Item>()
    .Adding(new Item("text1"))
    .ConditionalAdding(condition, new Item("text2"));
public static class ItemListExtensions
    public static List<T> Adding<T>(this List<T> list, T item)
        return list;
    public static List<T> ConditionalAdding<T>(this List<T> list, bool condition, T item)
        if (condition)
        return list;

// builder object
var list = new ItemListBuilder()
    .ConditionalAdding(condition, "text2")
public class ItemListBuilder
    private readonly List<Item> list;

    public ItemListBuilder()
        list = new List<Item>();

    public ItemListBuilder Adding(string text)
        list.Add(new Item(text));
        return this;

    public ItemListBuilder ConditionalAdding(bool condition, string text)
        if (condition)
            list.Add(new Item(text));
        return this;

    public List<Item> Build()
        return list.ToList();

Of course, for just a simple collection with some conditions this might feel like overkill, but try to compare the two versions of the code: the one that uses initializer syntax and then the Add method and the one that declares what it wants to do, step by step. Also note that in the case of the builder object I've taken the liberty of creating methods that only take string parameters then build the list of Item, thus simplifying the syntax and clarifying intent.

I had this situation where I had to map an object to another object by copying some properties into collections and values of some type to other types and so on. The original code was building the output using a top-down approach:

public Output BuildOutput(Input input) {
  var output=new Output();
  BuildFirstPart(output, input);
  BuildSecondPart(output, input);
  return output;

public BuildFirstPart(Output output, Input input) {
  var firstSection = BuildFirstSection(input);
  output.FirstPart=new List<Part> {
    new Part(firstSection)
  if (condition) {
    var secondSection=BuildSeconfSection(input);
    output.FirstPart.Add(new Part(secondSection));

And so on and so on. I believe that in this case a fluent design makes the code a lot more readable:

var output = new Output {
  FirstPart = new List<Part>()
    .ConditionalAdding(condition, BuildSecondSection(input),
  SecondPart = ...

The "build section" methods would also be inlined and replaced with fluent design methods. In this way the structure of "the output" is clearly shown in a method that declares what it will build and populates the various members of the Output class with simple calculations, the only other methods that the builder needs. A human will understand at a glance what thing it will build, see its structure as a tree of code and be able to go to individual methods to see or change the specific calculation that provides a value.

The point of my post is that sometimes the very out-of-the-box features that help us a lot most of the time end up complicating and obfuscating our code in specific situations. If the code starts to smell, to become unreadable, to make you feel bad for writing it, then stop, think of a better solution, then implement it so that it is the best version for your particular case. Use tools when they are useful and discard them when other solutions might prove more effective.

and has 0 comments

  Man of Two Worlds may be the worst book signed by Frank Herbert that I've ever read. It features that nasty '50s newsroom trope, where single minded egotistical people (sometimes to the point of cruelty) get a pass because they are brilliant and they talk fast (and they own the newspaper). The characters are unsympathetic and rather not interesting, while the ideas in the book are dull and going nowhere. The plot itself is often inconsistent. I do suspect that this is more of a Brian than a Frank book, because none of the themes found in previous Frank Herbert books are found here (if one discounts the awkward depiction of women). Also the tiny Wikipedia page dedicated to the book lists Brian as the main author.

  In short, the story is about a human and an alien merging accidentally and having to work together to get things done. Kind of like the authors were trying to do, huh? The setting is classic '50s sci-fi, with people living on Mars and Venus and going from planet to planet using vehicles that function like normal airlines, only in space. Meanwhile, the aliens are trying to destroy Earth because they fear humans - not sure how that would work since they already live on other planets, and the humans have their own familial issues to resolve - including an uncle with god-like powers but no apparent care about the outcome of anything he does.

  There are many issues with the book that I am not going to go into. I almost did not finish it. However, someone else might enjoy it, so no need to rant in this review. Suffice to say that the book feels insulting when it is not boring, which is most of the time. I don't recommend it.

and has 0 comments


  Some of the most visited posts on this blog relate to dependency injection in .NET. As you may know, dependency injection has been baked in in ASP.Net almost since the beginning, but it culminated with the MVC framework and the .Net Core rewrite. Dependency injection has been separated into packages from where it can be used everywhere. However, probably because they thought it was such a core concept or maybe because it is code that came along since the days of UnityContainer, the entire mechanism is sealed, internalized and without any hooks on which to add custom code. Which, in my view, is crazy, since dependency injection serves, amongst other things, the purpose of one point of change for class instantiations.

  Now, to be fair, I am not an expert in the design patterns used in dependency injection in the .NET code. There might be some weird way in which you can extend the code that I am unaware of. In that case, please illuminate me. But as far as I went in the code, this is the simplest way I found to insert my own hook into the resolution process. If you just want the code, skip to the end.

Using DI

  First of all, a recap on how to use dependency injection (from scratch) in a console application:

// you need the nuget packages Microsoft.Extensions.DependencyInjection 
// and Microsoft.Extensions.DependencyInjection.Abstractions
using Microsoft.Extensions.DependencyInjection;

// create a service collection
var services = new ServiceCollection();
// add the mappings between interface and implementation
services.AddSingleton<ITest, Test>();
// build the provider
var provider = services.BuildServiceProvider();

// get the instance of a service
var test = provider.GetService<ITest>();

  Note that this is a very simplified scenario. For more details, please check Creating a console app with Dependency Injection in .NET Core.

Recommended pattern for DI

  Second of all, a recap of the recommended way of using dependency injection (both from Microsoft and myself) which is... constructor injection. It serves two purposes:

  1. It declares all the dependencies of an object in the constructor. You can rest assured that all you would ever need for that thing to work is there.
  2. When the constructor starts to fill a page you get a strong hint that your class may be doing too many things and you should split it up.

  But then again, there is the "Learn the rules. Master the rules. Break the rules" concept. I've familiarized myself with it before writing this post so that now I can safely break the second part and not master anything before I break stuff. I am talking now about property injection, which is generally (for good reason) frowned upon, but which one may want to use in scenarios adjacent to the functionality of the class, like logging. One of the things that always bothered me is having to declare a logger in every constructor ever, even if in itself a logger does nothing to the functionality of the class.

  So I've had this idea that I would use constructor dependency injection EVERYWHERE, except logging. I would create an ILogger<T> property which would be automatically injected with the correct implementation at resolution time. Only there is a problem: Microsoft's dependency injection does not support property injection or resolution hooks (as far as I could find). So I thought of a solution.

How does it work?

  Third of all, a small recap on how ServiceProvider really works.

  When one does services.BuildServiceProvider() they actually call an extension method that does new ServiceProvider(services, someServiceProviderOptions). Only that constructor is internal, so you can't use it yourself. Then, inside the provider class, the GetService method is using a ConcurrentDictionary of service accessors to get your service. In case the service accessor is not there, the method from the field _createServiceAccessor is going to be used. So my solution: replace the field value with a wrapper that will also execute our own code.

The solution

  Before I show you the code, mind that this applies to .NET 7.0. I guess it will work in most .NET Core versions, but they could change the internal field name or functionality in which case this might break.

  Finally, here is the code:

public static class ServiceProviderExtensions
    /// <summary>
    /// Adds a custom handler to be executed after service provider resolves a service
    /// </summary>
    /// <param name="provider">The service provider</param>
    /// <param name="handler">An action receiving the service provider, 
    /// the registered type of the service 
    /// and the actual instance of the service</param>
    /// <returns>the same ServiceProvider</returns>
    public static ServiceProvider AddCustomResolveHandler(this ServiceProvider provider,
                 Action<IServiceProvider, Type, object> handler)
        var field = typeof(ServiceProvider).GetField("_createServiceAccessor",
                        BindingFlags.Instance | BindingFlags.NonPublic);
        var accessor = (Delegate)field.GetValue(provider);
        var newAccessor = (Type type) =>
            Func<object, object> newFunc = (object scope) =>
                var resolver = (Delegate)accessor.DynamicInvoke(new[] { type });
                var resolved = resolver.DynamicInvoke(new[] { scope });
                handler(provider, type, resolved);
                return resolved;
            return newFunc;
        field.SetValue(provider, newAccessor);
        return provider;

  As you can see, we take the original accessor delegate and we replace it with a version that runs our own handler immediately after the service has been instantiated.

Populating a Logger property

  And we can use it like this to do property injection now:

static void Main(string[] args)
    var services = new ServiceCollection();
    services.AddSingleton<ITest, Test>();
    var provider = services.BuildServiceProvider();

    var test = (Test)provider.GetService<ITest>();

private static void PopulateLogger(IServiceProvider provider, 
                                    Type type, object service)
    if (service is null) return;
    var propInfo = service.GetType().GetProperty("Logger",
    if (propInfo is null) return;
    var expectedType = typeof(ILogger<>).MakeGenericType(service.GetType());
    if (propInfo.PropertyType != expectedType) return;
    var logger = provider.GetService(expectedType);
    propInfo.SetValue(service, logger);

  See how I've added the PopulateLogger handler in which I am looking for a property like 

public ILogger<Test> Logger { get; private set; }

  (where the generic type of ILogger is the same as the class) and populate it.

Populating any decorated property

  Of course, this is kind of ugly. If you want to enable property injection, why not use an attribute that makes your intention clear and requires less reflection? Fine. Let's do it like this:

// Add handler

// the handler populates all properties that are decorated with [Inject]
private static void InjectProperties(IServiceProvider provider, Type type, object service)
    if (service is null) return;
    var propInfos = service.GetType()
        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
        .Where(p => p.GetCustomAttribute<InjectAttribute>() != null)
    foreach (var propInfo in propInfos)
        var instance = provider.GetService(propInfo.PropertyType);
        propInfo.SetValue(service, instance);

// the attribute class
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class InjectAttribute : Attribute {}


I have demonstrated how to add a custom handler to be executed after any service instance is resolved by the default Microsoft ServiceProvider class, which in turn enables property injection, one point of change to all classes, etc. I once wrote code to wrap any class into a proxy that would trace all property and method calls with their parameters automatically. You can plug that in with the code above, if you so choose.

Be warned that this solution is using reflection to change the functionality of the .NET 7.0 ServiceProvider class and, if the code there changes for some reason, you might need to adapt it to the latest functionality.

If you know of a more elegant way of doing this, please let me know.

Hope it helps!


But what about people who really, really, really hate reflection and don't want to use it? What about situations where you have a dependency injection framework running for you, but you have no access to the service provider builder code? Isn't there any solution?

Yes. And No. (sorry, couldn't help myself)

The issue is that ServiceProvider, ServiceCollection and all that jazz are pretty closed up. There is no solution I know of that solved this issue. However... there is one particular point in the dependency injection setup which can be hijacked and that is... the adding of the service descriptors themselves!

You see, when you do ServiceCollection.AddSingleton<Something,Something>, what gets called is yet another extension method, the ServiceCollection itself is nothing but a list of ServiceDescriptor. The Add* extensions methods come from ServiceCollectionServiceExtensions class, which contains a lot of methods that all defer to just three different effects:

  • adding a ServiceDescriptor on a type (so associating an type with a concrete type) with a specific lifetime (transient, scoped or singleton)
  • adding a ServiceDescriptor on an instance (so associating a type with a specific instance of a class), by default singleton
  • adding a ServiceDescriptor on a factory method (so associating a type with a constructor method)

If you think about it, the first two can be translated into the third. In order to instantiate a type using a service provider you do ActivatorUtilities.CreateInstance(provider, type) and a factory method that returns a specific instance of a class is trivial.

So, the solution: just copy paste the contents of ServiceCollectionServiceExtensions and make all of the methods end up in the Add method using a service factory method descriptor. Now instead of using the extensions from Microsoft, you use your class, with the same effect. Next step: replace the provider factory method with a wrapper that also executes stuff.

Since this is a bonus, I let you implement everything except the Add method, which I will provide here:

// original code
private static IServiceCollection Add(
    IServiceCollection collection,
    Type serviceType,
    Func<IServiceProvider, object> implementationFactory,
    ServiceLifetime lifetime)
    var descriptor = new ServiceDescriptor(serviceType, implementationFactory, lifetime);
    return collection;

//updated code
private static IServiceCollection Add(
    IServiceCollection collection,
    Type serviceType,
    Func<IServiceProvider, object> implementationFactory,
    ServiceLifetime lifetime)
    Func<IServiceProvider, object> factory = (sp)=> {
        var instance = implementationFactory(sp);
        // no stack overflow, please
        if (instance is IDependencyResolver) return instance;
        // look for a registered instance of IDependencyResolver (our own interface)
        var resolver=sp.GetService<IDependencyResolver>();
        // intercept the resolution and replace it with our own 
        return resolver?.Resolve(sp, serviceType, instance) ?? instance;
    var descriptor = new ServiceDescriptor(serviceType, factory, lifetime);
    return collection;

All you have to do is (create the interface and then) register your own implementation of IDependencyResolver and do whatever you want to do in the Resolve method, including the logger instantiation, the inject attribute handling or the wrapping of objects, as above. All without reflection.

The kick here is that you have to make sure you don't use the default Add* methods when you register your services, or this won't work. 

There you have it, bonus content not found on ;)

and has 0 comments

  Imagine reading a novel about a global pandemic with the background of Irish violence right about when Covid struck and people didn't know how Brexit was going to turn out and what it would do to Irish tensions. That was the best moment to read it. A bit anachronistic, with some pacing issues, The White Plague is still one of Frank Herbert's best.

  After reading the book synopsis, one expects to get a book about a violent global pandemic, but in fact that's just the first quarter of the book. The rest is psychological explorations of people motivations and characters, the ubiquitous Herbert attempts to find a solution to the toxic human organizational structures, analysis of history, violence, religion and philosophy. I mean, it's Herbert!

  A violent "Provo" bombing kills the wife and daughters of a molecular biologist that was in Ireland on vacation. He goes mad and creates a plague to destroy the people who wronged him by killing their women. I can't but smile at the implications, that if a smart educated scientist gets pissed off they could easily cause more damage than the toys and sticks of military people. The theme reminds me of his short story Public Hearing, which explores what happens when immense destructive power can be achieved with little effort by individuals, and how that makes governments - the keepers of peace - obsolete.

  But then there is the larger part of the book that is just the guy walking in the Irish countryside with a priest, a mute child and an IRA member that was actually the one who ordered the bomb that killed his wife. And to tell you the truth, the scientist is not very sympathetic, the IRA soldier is annoying and the priest and the child are unbearable. The ideas that the author is analyzing are interesting, but the pacing is slow, methodical, and perhaps the reason why more people haven't heard of this book.

  And there is the usual strangeness of Herbert's approach to female characters. There is just one, really, in this book, and she comes across as stupid, vain but also calculatingly self serving, while still having men fawning over her. That in a story which covers the death of most women on Earth. The guy didn't like women much.

  Anyway, if you take anything from this review, is that together with Hellstrom's Hive and of course the Dune series, this is one of the books that impacted me most. 

and has 0 comments

  I was studying some game openings and I found myself in a position that was reached on LiChess 7 times after 11 moves, starting from the Vienna Gambit. That's the gambit that looks like an improved King's Gambit, with f4 after playing Nc3 first. In fact, one of the 7 games started off as a King's Gambit.

  This position is fascinating. Go on, try to analyze it! Guess the evaluation, try to see the continuations. White to move, obviously, since the king is completely exposed and also in check. Black has 3 extra pawns and a passed pawn one rank from promoting. Can White survive this?

  What if I were to tell you that the computer evaluation for this position is +5 for White? And I am talking 40 ply, not the in page LiChess engine which actually evaluates this at more than +8! The server analysis goes as low as +4.

  I am going to share the study, it has several chapters, one with how to get to this position and another with computer variations (absolutely FILTHY variations - imagine Levy Rozman saying that) and then the games on LiChess at the moment. The computer variations (so best play from Stockfish) all end badly; Black is completely lost. It goes to show the importance of space, development and tempo in chess, much more than the material or even the classical principles we are all used to. Not that they are bad, it's just that they don't always apply.

  Enjoy this amazing position!

and has 0 comments

  McKie again saves the world, while at the same time getting some intense nookie. He is Frank Herbert's James Bond, the guy who can outthink everybody, adapt to any situation and still look cool and positive while doing it. To be fair, I enjoyed The Dosadi Experiment quite a lot, perhaps because and not despite the air of interplanetary secret agent idea. I liked it more than Whipping Star, the first book in this universe, which had the handicap of having to establish it first. Also, because most of that was a human trying to understand a Caleban, which was not terribly exciting. This book explores a planet used as a (unlawful) social experiment and what the result of that experiment was.

  There is something I both like and despise in Herbert's writing. He weaves different captivating stories and worlds from the same pieces. So you get the stagnating civilization, malignant government and various explorations of solutions to solve the problem, you get the very rational yet emotionally immature male heroes and the amazing and terrifying women that they stumble upon, the idea of terrible pressure shaping civilizations and individuals alike into extraordinary form, the people reaching higher levels of awareness and saying or understanding the precise best things that could have been said or understood. There is even a Gom Jabbar in this.

  In fact, some of his books remind me of chess games. And one might enjoy chess games immensely, but after a certain level you just don't get if they are brilliant or complete shit. It's the same with The Dosadi Experiment, where everybody begins seeing the world in the Dosadi way, speak in the Dosadi way, think in the Dosadi way, but you never understand what that is, other than a form of psychopathic focus on power games.

  I believe that, given more time, Herbert could have shaped the ConSentiency Universe into something really unique, not as dry (pardon the pun) as Dune, not as depressing as Pandora, something that would combine the mind games and social analysis that he loved with good fun and great creative ideas. Alas, other than a couple of short stories, that's all we get for this intriguing world building.

  Bottom line: a little more lighthearted than most Herbert books, featuring more action, but still having the distinctive attributes one would expect from the author. I liked it, but it wasn't as memorable as the books I really like from him.

and has 0 comments

  One of my favorite Frank Herbert books and one that is not part of a series, Hellstrom's Hive is horrifying and inspiring in equal measure. I don't know why so few people mention reading it, probably because the ending is a bit weak, or maybe because of the touchy subject, but I loved it.

  The idea is quite simple, although as usual with Herbert, the underlying motifs are subtle and powerful. An unnamed and probably illegal secret organization, possibly an arm of the corporate world rather than government, discovers by accident something suspicious about a farm, owned by a guy named Hellstrom. There, they discover an unnamed and probably illegal secret organization, a group of people who hide from the world their own brand of civilization, inspired by insects.

  You can immediately see that the two organizations are juxtaposed for effect. Which one, if any, is the good one and which one is not? Are the relatively moral agents of the first group better than the mindless drones of the second? What about if they execute their orders without thought of consequences? Are the ecosystem aware, science and reason oriented, efficiency focused godless denizens of the hive abominations or are they the way of the future, the solution to humanity's rapaciousness? Could people accept such a radically different way to live, even if it doesn't affect them?

  As many of Herbert's creations, the book touches some recurring themes: the inevitable evil of government, the importance of focusing with mind and soul towards the betterment of individuals and the human species in general, the chemical, sexual and instinctual drives at the root of behavior, the power of ritualistic fanaticism, the danger in wanting too much or getting complacent and so on. In a way, this is a revisiting of the ideas from The Santaroga Barrier, only better.

  I was dreading reading this book, I have to admit, because I was remembering the big impact it had on me when I read it in my childhood and I was afraid that it would be anachronistic, that it would feel stupid and unrealistic. I am happy to report that it did not. I mean, yeah, it does portray a story happening in the 70's, but it is realistic for those times and it could be adapted to the present with minimal changes. I don't know why no one attempted to put it on a screen. It's a captivating story.

and has 0 comments

  Only after downloading 11 GB of game, playing for a few minutes and uninstalling it in frustration, then searching the web, did I understand Chess Ultra is a Switch game designed to work in VR. For a PC game, though, where I was playing it, it was a slow bloatware that lead to a 404 page when you wanted to switch the chess board style.

  Imagine coming from Lichess and trying to make sense of something that requires so much space to function, has only 3D pieces and uses all of your video card to display a chessboard and some coffee on a table. It was unbearable. Perhaps it would work on a Switch console, with VR glasses, if you want to enter the mood of playing over the board in a smoky chess room, but I have no idea who would want that.

  And then I looked on the Internet to see what other people were saying and everything was great! Oh, the multiple options, the varied puzzles, the recreations of classical games. Jesus, that's basic chess web site functionality! And "critic ratings" are 85% while the normal people rate it at about 60%. Really? Am I crazy for thinking it's a badly constructed game? I hated it.


and has 0 comments

  Submerged: Hidden Depths is one of those relaxing games that require no effort and no skill. You control a couple of unreasonably athletic teens in a future time in which the world is covered in water and strangled by a huge vine-like plant. The two youngsters travel on a boat, retrieving and returning the plant's seeds so that it won't be angry and discovering on the way relics of Earth's past and journals that explain what went on. Each stage is almost linear, easy to go through, devoid of danger and marked in multiple ways so that you don't have to think your way out of anything. In other world, it's a visual feast of a fantasy world in which you just discover stuff.

  At first attracted by the concept, since I usually enjoy the story, exploration and discovery part of RPGs much more than the fights, I got bored rather quickly. It's the same thing again and again, even if "the world" is practically a small sandbox. I liked the design, although the graphics are really simplistic. The occasional proto language words they use are fun and the soundscape puts you in the mood.

  What turned me off a bit is that occasionally the video card would throw an error and I would have to forcefully close the game and start it again. Also, there are ways to skip the animations, which is good, but it skips the good parts as well.  There is one of the most satisfying activities around: finding relics, where the repetitive animation of the boy throwing an anchor and pulling it back gets rather old, but the "strange things" they recover, like typewriters and sextants and so on, it's new every time. And of course when you skip the animation you skip the entire thing, not just the repetitive part. Such a small thing to think about and fix and they wouldn't do it.

  Every time you save a seed there is a storyline that gets advanced and at one time I saw a large black vine hand coming out of the water. I said "We're gonna need a bigger boat!" so I collected all boat upgrades first and stopped saving seeds until I understand the journals, but the upgrades just add extra boost to the boat and the journals are mostly in the seed parts, so not something particularly satisfying. I am going to continue to play it to the end, because sometimes I just feel to turn my brain off, but other than that it feels more like a demo than a full game.

  Playing hint: if you don't like the weather (fog, rain, whatever) you can just save and return to the menu then continue the game and it starts from a sunny mode again. Same if you get stuck in the map and can't move.

  In the end I've completed the game. The ending was quite underwhelming.

and has 0 comments

This started as an investigation into the bad way modern sci-fi is portrays fungi and veered into a mix of various IPs that are (coincidentally) mostly owned by Disney. I am presenting my idea, as always free to use and abuse, as a series of book stories.


A fungus evolves to facilitate communication, kind of like a biological version of the Internet. On its planet, the ecosystem is connected through its mycelial network where it acts as a general field, bestowing intelligence to anything connecting to it. Due to the slow speed of connection, this transforms the entire planet into a large thinking brain, dreaming vast thoughts and living in symbiosis with the plant and animal life which provide it with real life experience and goals, plus fast local intelligence. The result is a society that looks like a Disney kingdom, with talking animals and plants and so on. Interesting ideas of conscious animals sacrificing themselves for food because their soul rests in the network arise.

Now humans from an Alien/Blade Runner universe come along, with a corporate mindset, and the fungus world understands that they are toxic.

Book 1

Act I

We introduce the crew of a Nostromo-like ship, flying under a human corporate flag. They are tasked with investigating a new planet. 

Act II

They are amazed to discover something looking like Fantasyland. Castles, princes, princesses, people happy and beautiful landscapes. But they reveal their mindset and through some misguided actions, they make the planet see them as a threat which puts them in peril.


They fight for survival, Alien style, where everything and everybody is trying to hurt them. And also like Alien, it wants them alive, because Fung'y wants to study the crew, maybe even incorporate them into its structure, even if they are of different biological make up than life on Fantasyland. They have superior technology and weaponry, but they are fighting with never ending swarms of animals and knights and poisonous plants.

Act IV

They discover a lot more of what the planet is like, how it works and why it wants to kill them, the survivors try to escape in a rescue shuttle. They fail, but not only because they can't make it, but also because they are - kindly - explained how they are the bad guys. And they are captured in understanding of their role as the villain in the fairy tale.

Book 2

Act I

We introduce one of the people we thought dead in the first book, found by another human ship while drifting in space hibernation in an escape shuttle. They have been drifting for decades. They tell the story of the killer Fantasyland planet. Humans prepare for investigation and attack.

Act II

Human ships arrive at Fantasy land, examining the planet from afar. Automated and android teams are sent for burn and grab missions. They need samples and to study the fungus. Some don't make it back.


Humans realize that the planet has changed in a few decades. The economy is no longer feudal, it went through some kind of technological advancement as well. It's subtle, but they can't explain electromagnetic emissions and weird heat signatures.

Act IV

Humans go into the offensive, using a toxin that kills the fungus, using it to horrific effects. We see how the land physically collapses in some parts, how the animal populations lose their minds, literally. Humans rejoice but suddenly the electromagnetic emissions start increasing and weird beams of energy start cutting through human ships. Space... things... start popping up and attacking the ships. You get weird battles between people on starships fighting creatures with armor and sword, lion-like creatures and swarms of rats. In the end humans poison and nuke the entire planet and while winning, it's a pyric victory, with most of their resources depleted, ships destroyed and the prize (a pristine planet ready for plunder) completely destroyed 

Book 3

Act I

The survivor from book II is back home. We see how the human world works and how bad things are. Though corporate compensation packages and insurance money keep them in relative comfort, our survivor has to find a job soon if they don't want to go into a pool of unhireables which would guarantee debt and a life of corporate servitude. They try to get a job, but even as a known hero, it's hard.

Act II

The survivor is now exploring the underworld of the human society, the gangsters, the hackers, the underground economy. While looking for a job they realize they are not feeling well. People are trying to take advantage of that. It does not turn up well for them.


The survivor realizes that they are capable of things they didn't think they could. But Dunning-Kruger effect makes them believe it's plausible. Or is it DK? They capture one of the gangsters who attacked them and instead of killing them, they keep them captive.

Act IV

Our survivor becomes a kingpin of an underground society. They have a reputation of getting some of their worst enemies to join their organization as trusted allies .

Book 4

Act I

A human military warship, the crown jewel of a corporation, patrols the waters of space. They are attacked by space things. The mighty warship is destroying them as they come, but they keep coming, some breach the ship, creatures attack the crew. Strange energy emanations come from some of the space things, disrupting defense. Escape pods are launched. Space things keep coming and attack everything, space pods included.

Act II

A human corporation meeting is under way. These things are rare because corporations are stuck in unending bitter corporate wars and face to face communication of the major corporate leaders is not safe. The media is abuzz, but cannot be privy to the meetings, because they are closed. A reporter is obsessed to finding a way in.

Corporate meeting is under way. These people are ruthless, intelligent, fashionable. They all breach the subject slowly and carefully, but a larger picture emerges: corporate planets of various factions are disrupted by a special kind of organized unrest. Corporations are experts in dismantling criminal organizations they do not suffer, but these are hard to crack. People are loyal, methods are unusual, communication is not traceable, they have access to weird technology. In the end they have to admit they have a common problem. It is then when one of the leaders there admits they have lost their military flagship to unknown assailants. Shock comes as they realize none of the people at the table were responsible.


The war comes in the clear. Fung'y didn't die. It reverse engineered space travel and energy manipulation weapons. Before the humans attacked, it spread spore ships to random places in space. The original survivor was first captured, infested and let go, as yet another experiment. Many other humans were infested in the same way in the attack.

Original Fung'y died, but its seeds are now everywhere. Silently, versions of himself grew inside human societies, on new planets. Now, they are starting to connect using human technology into a thing even larger than before. Planet brains that took forever to finish a thought incorporate human technology to facilitate long distance communication. Determining as a consensus that the human world is both valuable and a pest, the Fung'y dominion continued with its ancestral plan: find all humans and... domesticate them.

Act IV

War and paranoia destroys the order of the human universe. Trust disappears, planets become insular, human travel practically ends. Both sides: human and fungus, work on finding the weaknesses of the other, probing, testing, frantically researching. The human strategy: find reliable ways to detect infestation and eradicate it. Find reliable ways of finding planetary brains and destroy them. Fungus strategy: infiltrate and coopt human societies. Isolate and eliminate human defense, weaponry and communication.


Mandalorian style stories set into the now complete Disney universe: Fantasyland, Alien, Blade Runner and a fungus clone of The Last of Us. Complete artistic freedom. Anything goes, from children fantasy to gory horror, maybe at the same time.

Bonus: Fung'y vs Alien, or even better, the Xenomorph brood gaining (even more) intelligence from a temporary alliance with Fung'y, until it realizes they are worse than the humans, but both gaining some characteristics from the other in the end.


Of course this can continue in any number of ways. I used known IPs for succinctly expressing my ideas, but of course they don't have to go the same way and can be (and should be) set in a standalone universe of their own. However, if Disney wants to use my idea, they are free to do so!

Hope you enjoyed this. Tell me if you want more stuff like this.