and

Ken and Robin Talk About Stuff: Not Quite Doctor Cowboy

In the latest episode of their pageant-like podcast, Ken and Robin talk where to start with Earth, your conspiracy bookshelf, Moina and Samuel Mathers, and The Rise of Skywalker.



  • Ken and Robin Talk About Stuff

and

Ken and Robin Talk About Stuff: Number One Nightmare

In the latest episode of their starry starry podcast, Ken and Robin talk alternate reality tech levels, Sarah Saltiel, emergent continuity and Belle Epoque astrologer Ely Star.




and

Ken and Robin Talk About Stuff: Shill for the Macedonians

In the latest episode of their multi-layered podcast, Ken and Robin talk narrative voices in RPG play, Whitey Bulger & MK-ULTRA, curse tablets, and Oswald Wirth & Stanislas de Guaita.



  • Ken and Robin Talk About Stuff

and

Ken and Robin Talk About Stuff: The Apache Helicopter of Toaster Ovens

In the latest episode of their crispy-in-a-good-way podcast, Ken and Robin talk agency in the sandbox, air frying, Alphonse Bertillon, and numbers stations.



  • Ken and Robin Talk About Stuff

and

Ken and Robin Talk About Stuff: Yell Down Into the Hollers

In the latest episode of their unswervingly loyal podcast, Ken and Robin talk Night's Black Agents vampire concealment, Gideon & Longknife, Robin's Yellow King novel, and Time Inc vs the Iowa caucuses.



  • Ken and Robin Talk About Stuff

and

Ken and Robin Talk About Stuff: The Toppling is the Point

In the latest episode of their feathery but unruffled podcast, Ken and Robin talk history spoilers, political pigeons, Sarah Bernhardt, and the Dark Watchers.



  • Ken and Robin Talk About Stuff

and

Ken and Robin Talk About Stuff: The Owl Costume Never Pulled

In the latest episode of their swelegant podcast, Ken and Robin talk GUMSHOE One-2-Ones you should writer, an Esperanto commune, screwball comedies, and the Takenouchi Documents.




and

Ken and Robin Talk About Stuff: Vigorous Deaccessioning Policy

In the latest episode of their high-flying double-decker podcast, Ken and Robin talk making mind control fun to play, Nadar, the occult adventures of Bruce Lee & Jimi Hendrix, and the Rotodyne.




and

Ken and Robin Talk About Stuff: Existence Does Exist

In the latest episode of their safely sheltering podcast, Ken and Robin talk remote play tips, secret museum scans,  war movies you can nerdtrope into Yellow King RPG: The Wars scenarios, and USAF involvement in UFO patents.



  • Ken and Robin Talk About Stuff

and

Ken and Robin Talk About Stuff: Sonia Plus Melted Cheese

In the latest episode of their thoroughly vetted podcast, Ken and Robin talk converting standard GUMSHOE scenarios to QuickShock, a Ukraine mole, QuestWorlds with Ian Cooper, and moving Lovecraft to Chicago.



  • Ken and Robin Talk About Stuff

and

Ken and Robin Talk About Stuff: Fruit Cutting Policies

In the latest episode of their correctly advertised podcast, Ken and Robin talk intelligent maps, Guelphs vs Ghibellines, bad place psychology, and a terrible novel and/or occult tome.




and

"solidarity, equity and social justice"

Смешно
https://www.forbes.com/2010/02/05/world-health-organization-swine-flu-pandemic-opinions-contributors-michael-fumento.html
оказывается, в 2010-м WHO (это те самые люди, которые
придумали карантин против ковида и везде его пропагандируют)
замечательно сели в лужу, объявив свиной грипп пандемией
и проебав на том 18 миллиардов баксов. Но делали это
они не просто так, а под знакомыми лозунгами
"solidarity, equity and social justice". То бишь WHO
это такая коллективная Оказия Кортез, банда ебанутых
SJW, возглавляющая атаку международного капитала на
общественные и личные свободы.

В 2010-м со свиным гриппом у них не
получилось, теперь они пытаются с короной,
и у них все пока получается.

Многие спрашивают, кому нужно это адское
говно, "карантины" и все прочее, и зачем
либеральная общественность так за них цепляется.
А вот за этим, очевидно. Коррупционеры из WHO рвутся
к власти, а пропагандисты за "solidarity, equity
and social justice" (CNN, NYT, Guardian и иже с
ними) им помогают, ибо надеются урвать свой кусок.

Интересно, что в 2010-м в каждом магазине
(я как раз жил в Бразилии) на входе был специальный
рекомендованный WHO против свиного гриппа диспенсер
антисептического геля для рук, а сейчас их нет.
Специально ходил сегодня в аптеку, искал,
но нет антисептического геля и там.

В принципе, если бы кому-то хотелось
бороться с коронавирусом, они бы этим в первую очередь
озаботились, но никак. Очевидно, WHO, под впечатлением прошлого
раза, сама убедила себя, что корона это фейк, и никаких реальных
мер больше не предлагает. С другой стороны, реальных мер WHO
и не надо, пусть эта музыка будет вечной, им так выгоднее.

В общем, чиновник WHO это адский гад,
похуже любого коронавируса.

Привет




and

2020 coronavirus pandemic in New York City

Странные данные по NYC
https://commons.wikimedia.org/wiki/Data:COVID-19_cases_in_New_York_City.tab
трупов, оказывается, не 300-400 в день, как
объявлялось, а всего 200 в день, то есть около половины
мертвецов в NYC болели короной (или меньше; нормальная
смертность в NYC 400-500 человек в день).

Похоже, оно не растет даже, ну типа - ковид
выкашивает тех, кто и так на пороге смерти,
а остальные могут особо не беспокоиться.

Привет




and

Running on empty: Coronavirus has changed the course for races big and small

Don't expect a pack of running fanatics swarming to the finish line at road races this year. But that doesn't mean that participants don't have options.




and

Lance Armstrong and Bruce Lee 30 For 30 documentaries coming to ESPN Africa

ESPN will be releasing two brand new 30 For 30 documentaries in Africa in May and early June, telling the stories of cyclist Lance Armstrong and martial artist Bruce Lee.




and

Let's try and bring this back - Fanart Thursday

Posted by: icon_uk

It used to be the tradition around these here parts to post fan art on Thursday, comic themed, but not comic published, art by fans or professionals.

So share your commissions or interesting art you've seen. (If in doubt, check with the artist it's okay to post it and if they say no, then it's a no!)

Just for fun )



comments



  • char: warlock
  • char: cypher/doug ramsey
  • medium: fanart
  • char: poison ivy/pamela isley
  • creator: george perez
  • char: nico minoru
  • title: saint seiya
  • creator: todd nauck
  • char: robin/nightwing/dick grayson
  • title: legion of super-heroes
  • char: jimmy olsen
  • char: she hulk/jennifer walters
  • creator: luciano vecchio
  • creator: dustin nguyen
  • char: harley quinn/harleen quinzel
  • char: catwoman/selina kyle

and

New Mutants D&D: Chapter 1- Road of Bandits

Posted by: iamrman

People seemed interested in my New Mutants Dungeons and Dragons story, so here is the first chapter.

Read more... )



comments



  • char: magik/illyana rasputin
  • medium: fanart
  • char: black cat/felicia hardy
  • char: mirage/danielle moonstar
  • char: wolfsbane/rahne sinclair
  • char: phoenix/marvel girl/rachel summers
  • char: cypher/doug ramsey
  • group: new mutants
  • char: sunspot/roberto da costa
  • char: magma/amara aquilla

and

Pandemie srazila hypoteční trh o čtvrtinu. Úrokové sazby stále rostou

Pandemie koronaviru dolehla v březnu i na hypoteční trh. Objemy poskytnutých hypoték se propadly o čtvrtinu. Průměrná úroková sazba hypoték však roste již třetí měsíc v řadě, v březnu vzrostla na 2,45 procenta.



  • Finance - Hypotéky a půjčky

and

Home office v časech pandemie. Na co je nárok a co byste si měli ohlídat

Kvůli koronavirové pandemii pracují z domova tisíce lidí. Home office má však určitý pracovně-právní rámec, což tuší málokdo. Jaká jsou práva a povinnosti zaměstnanců a co musí zaměstnavatel udělat, aby neporušil zákoník práce? Ve spolupráci s právníky Bořivojem Líbalem a Markem Poloni přinášíme praktický servis rad pro zaměstnance a zaměstnavatele.



  • Finance - Finanční rádce

and

A New Name and Direction for Raw on $10 a Day (or Less!)





Ch-ch-ch-changes. 

Raw on $10 a Day (or Less!) began at the end of 2009. I’d just become vegan and was interested in raw foods. I was struggling in quite possibly the worst situation I’d ever been in. I was drowning and, you probably didn’t know it, but this blog and its readers became something of a lifeline. 

It all started as a simple question: “How much does it cost to eat raw?” but led to so much more. I’ve learned so much about food, and living, about loving myself and others, about the value of good food, and emotional and physical health. I've experienced heartbreaking loss, and deep happiness and joy, and I’ve grown and bloomed into the person I was always meant to be. I even wrote a real book, Easy Affordable Raw.

Today is my 54th birthday. It's said one's life goes in cycles and the 54th year is one of renewal, change, and rebirth. I feel fantastic and optimistic and am looking forward to many more happy, healthy years of vegan life, love, and adventure.

Because of all that, it makes me incredibly sad to say goodbye to Raw on $10. It’s something that I put a lot of work into. More than anything else, though, it’s something I’ve gotten a great deal from. I’ve deeply appreciated every reader, every encouragement, and every friendship and connection, online and off, that has come about directly and indirectly from Raw on $10.

I’ve never been good at ending relationships, either. I hang on. Drag my feet. Procrastinate. Second guess my decision. But there is only so much room in a life and sometimes one relationship must end for another to begin. It’s incredibly bittersweet. I’m sad for the ending but excited and so happy for what’s to come. 


And so …

Raw on $10 a Day is 

changing, 

growing, 

becoming … 

Planted 365



Changing the name of a blog while also changing the platform from Blogger to Wordpress has been brain explodingly complicated and I’d much rather be creating content. I’ve got some help and the process of changing and updating and linking and all that will be an ongoing process. Surely there will be some snags. Please be patient with the transition. 

All recipes will still be available, although I'll be updating and improving a lot of them.

I'll be migrating the RSS feed, email list, and all that, so you might see unfamiliar notifications.

Raw on $10 will continue to exist for the next week. Next Monday, everything will be redirected to the new name and new platform.

Planted 365 will be official then. If you want to go over now, though, it's up and running with a few new things. Sign up by email and you won't miss any posts.

I sincerely hope you will come along and see what else we can discover together. There will be lots of raw food still, because it’s awesome, delicious, and beautifully photogenic. And a new full day menu every week, starting next Monday. There will also be healthy cooked vegan recipes, soul healing art, mindful movement, and conscious connection and relationships. Because how much things cost seems to be interesting to so many, I'll note that information when I can. 

I’ve learned so much in the past nearly nine years. There’s ... so ... much … I can’t wait to show it all to you. 

I'll leave you with a very short video of where I'm headed with Planted 365. 









With sincerest gratitude ...
Lisa 

xoxo











and

Pronouns and terms of address

Seen several variations of this floating around. This particular version I got from ghoti_mhic_uait who pointed out that whether and how some of them are gendered can be really regional.

It/its - Basically nobody ever uses 'it' spontaneously unless they are trying to insult people for being GNC or perceived as trans. Most people perceive me as a not particularly feminine woman, so 'it' pretty much doesn't happen. I don't have any wish to be insulted by people who hate non-binary folk, but in the abstract I somewhat prefer 'it' to 'they'.

She/her - Most usual pronouns for me, and what I'll pick if people ask for pronouns and I don't want to be that annoying cis person who says 'I don't mind'. But actually I kind of don't mind.

He/him - I about equally don't mind 'he' as 'she', but in practice nobody ever reads me as male. I'll correct it if we're in an online discussion where people assume that articulate and sensible = male, but otherwise, emotionally it would be fine, realistically not very likely.

They/them - I feel guilty for saying this but I somewhat dislike being referred to as 'they'. I think it's the same objection I used to have when 'Ms' became common. It ought to mean that my gender (marital status) is irrelevant to what people are saying about me, which is correct, but actually it seems to mark me as one of those people for whom non-binary gender (or non-determinate marital status) is really important. So I don't like 'they' because I feel like I'm being gendered as a gender rebel, which I'm really not, I have no spare energy for activism around not fitting into the female box. I am entirely happy to refer to other people as they and hopefully wouldn't make too many assumptions about anybody else's gender politics, but I dislike it for myself.

Neo-pronouns - If it were a politically uncomplicated choice, and didn't have the same problem as 'they' that neo-pronouns mark you as a gender rebel, this would probably be my preference. I particularly relate to zie / hir ; some people object to this set because it sounds like German 'sie' meaning 'she' and therefore isn't truly gender neutral. But actually that matches pretty well how I feel about myself. I'm sort of female-ish, if people think of me as somewhere on the female side of neutral, that's about right. Also, as you can see from my icon, my preferred pronoun in Swedish is definitely 'hen'; yes, it does sound like the feminine gendered English word 'hen', which is a problem for many bilingual people, but for me personally it works really well.

Mr. - Can't really imagine this happening to me. Sometimes I choose it in a fit of pique if I'm choosing from a fixed list with only inappropriate title options. But just like I'm never going to be called 'he' spontaneously, nobody ever calls me Mr.

Mx - Don't love Mx but I'm ok with it. If social norms shift to the point that Mx is the default that people start out with rather than assuming Mr or Ms, that would be ok with me. But I don't love it anywhere near enough to insist on it if people are using a different title. (I don't like to spell it with a dot as it was in the list I copied from, 'Mx.' just looks wrong to me because it isn't an abbreviation for anything.)

Miss - My preferred title if Dr. isn't available. I dislike when people who don't know my name just call me 'Miss', but in a formal context where we're using titles, I will opt for 'Miss Surname'.

Ms - I guess, if I can't have Dr or Miss, then Ms is probably better that the other options. I am less prickly about being identified as a feminist than I was years ago, but it kind of doesn't really feel like me and I'd rather have Mx.

Mrs. - Don't like this because there is no sensible combination of 'Mrs.' with a surname. I don't have the same surname as my husband, so calling me 'Mrs. Hisname' is incorrect, but calling me 'Mrs. Myname' doesn't work either because it's not a married name, it's the same surname I was assigned at birth. A few distant relatives on both sides do default to 'Mrs. Hisname', and I don't really take offence at it, it's just a slightly incorrect formalism, not an insult. It just feels completely irrelevant to how I think of myself.

Dr. - This is my correct and earned title, which is incidentally gender neutral. I don't like being pretentious enough to insist on it always, but if I have to give a formal title to a random customer service bod, then Dr. is more correct than any of the other options. I'm happy to be addressed as 'Dr. Surname' if we are being formal. I'm not a fan of being addressed as just 'Dr.' or 'Doc', but I suppose it's better than plain 'Miss'.

Sir - I can't imagine a situation where someone would call me Sir outside a kink scene. And even then I'm almost exclusively submissive so it's not very likely. If I hypothetically did get read as male, and hypothetically it was the kind of context where 'Sir' is polite, I would be ok with it, but I'm not willing to go to the effort to be read as male, so it's not going to happen.

Ma'am - The cross-section of class and region I'm most familiar with doesn't use this. I have occasionally been called 'Madam' and I'm ok with that if it's a mark of genuine respect from someone who doesn't have a clue what my name or title are, not if it's sarcastic.

Dude - Relatively gender neutral in my dialect, but mostly used as an expression of surprise. So I wouldn't expect to be called 'dude' for real, but if it happened it would be ok.

Bro/bruh - I don't think anyone has ever called me either of these. If I heard it from someone from a similar sort of race and class background to me, I would assume they were taking the mick, either mocking me, or mocking what they perceive as a working class or ethnic minority dialect. If I were called 'bro' by someone who regularly calls people 'bro' that would be ok but again, unlikely because it's too male-gendered.

Sis - Fine from my actual siblings, and one particular friend with whom I have a negotiated fraternal relationship. Fine from people who are expressing feminist solidarity; I think I broadly prefer 'sister' over 'sis' but either is fine.

I'm also totally fine with Muslim women calling me 'sister' if they come from a culture where that's the general term of respect for anyone perceived as a woman. And if they normally only call fellow-Muslims 'sister' then it's a compliment to include a Jewish woman in the sisterhood. I don't expect it from Christians because I'm not a nun and not likely to be mistaken for one.

I wouldn't like to be called 'sis' by a stranger trying to get my attention though, it's one of the words that assumes intimacy.

Sib - Nobody really calls me 'sib' (or 'fam' for that matter). I like them, but they don't really belong in my culture and dialect.

Woman - I'm totally fine with being described as a woman. I strongly dislike being addressed as 'woman'; I can't think of a context where that would be anything other than deliberately rude.

Man - I don't think people call me 'man' directly. People use 'man' as an expression of emphasis, like, man, you're fast!. But I don't perceive that as being addressed as 'man'.

I have a few friends who will refer to me as a man if I happen to be wearing more masc attire than I usually do, and I am somewhat uncomfortable with that, because I'm not more male in trousers than a skirt, though I appreciate the underlying thought process which is to acknowledge gender-fluidity.

Boy - Implausible.

Girl - In a feminist-disapproved way, I do to some extent think of myself as a 'girl'. I am ok with other people calling me 'girl' in a context where it's obviously positive, like you go, girl!, but I wouldn't respond to someone calling me 'hey girl!' in the street. I might slightly ironically say 'because I'm a girl' when discussing some gender unfairness. I don't like people referring to me as a girl, because that can be patronizing. I particularly don't like 'girl' as a modifier; I'm not a 'girl scientist' or a 'girl manager' or a 'girl blogger', I'm a woman or female scientist.

King - I don't move in the kind of circles where this would ever be a term of address.

Queen - I think you have to be a certain kind of gay man or African American to call someone 'Queen' so this doesn't seem to fit me.

Prince - Implausible.

Princess - I kind of dislike this even as a term of endearment. It feels like a name for either a young child, or someone you don't really respect as a person but think of as basically an ornament or toy.

Captain - Completely irrelevant. The only time I'm ever even slightly likely to be addressed as 'Captain' is if someone is gently ribbing me for being bossy, which I suppose is ok if we have the kind of relationship where that sort of teasing is accepted.

Lady - As a term of address where this is culturally normal, fine. I don't feel personally excluded or hurt if someone addresses a speech to 'Ladies and Gentlemen'. If a complete stranger is trying to get my attention, I probably prefer 'lady' over 'girl', though neither is great. I don't mind when parents tell their children, say thankyou to the nice lady or similar. I would not expect anyone who knows my name to call me 'lady' instead. If someone is describing me rather than addressing me, I think 'woman' is a better word than 'lady', and 'person' is a better word still.

Feminine compliments - I don't entirely agree with the various examples from different versions of the meme of what constitutes a feminine, masculine or gender-neutral compliment. I broadly dislike 'feminine' compliments from people who don't know me well, because they are almost all about appearance, and because they are often belittling. If I'm in a close relationship with someone and feel comfortable with them complimenting my appearance, I prefer the gender-neutral 'gorgeous' over the more feminine-ish 'beautiful' as terms of address, but if it's a description rather than a name then it depends on the person giving the compliment.

Masculine compliments - I would love to be described as 'handsome', but it's never going to happen, because I'm really not. Also I don't like being addressed as 'handsome' in place of a name or title. What other masculine compliments even exist? I can't think of any of the top of my head.

Neutral compliments - In place of a name, supposedly neutral compliments are often feminized. Like, if a stranger calls me 'cute' or 'hot' or 'sexy' because they don't know my name, they're quite likely to be asserting gendered power over me and I don't like that. If someone wants to describe me in a sentence using complimentary language, I usually prefer neutral over explicitly feminine.

Honey, sweetie etc - If it's normal in someone's dialect to call random strangers by terms of endearment, that's fine. I think doing so can be gendered slightly female, but it doesn't bother me if someone calls me 'darling' or 'sweetheart' because they perceive me as female. I dislike endearments once I'm having an ongoing interaction with someone, in that case I want them to ask my name (or title, in a more professional context) and use it.

comments




and

Summer Horrification — Day Five — Englishman River and Rathtrevor

Continued from Day Four. (From the beginning.) On Friday we packed all of our stuff back up and headed out.  We were barely out of the resort when: This tire is flat. Apparently all that gravel out to Horne Lake Caves the day before also included a small screw.  We limped around the corner to … Continue reading Summer Horrification — Day Five — Englishman River and Rathtrevor




and

NaN Gates and Flip FLOPS

I was hoping to have a few things to write about in this month, but the only thing I finished was this video for SIGBOVIK, right at the beginning:


NaN Gates and Flip FLOPS


There is also the paper which has some merits but I submitted that before actually finishing the project, so I think the video is the definitive version. Either way this one is really aimed at trolling computer scientists, and so may be impenetrable if you don't have the background; sorry about that!

Allergies and various things have got me down recently but it's also getting nice out, which should provide a burst of energy!! This weekend is the Marathon in Pittsburgh, which I intend to run. No costume plans but sometimes I get last minute inspiration / compulsion. Feel free to taunt me with your ideas.




and

I still always confuse June and July

Ugh, well, I still didn't finish the video I mentioned last post (it is just a video version of some of my chess papers from this last SIGBOVIK; don't get too excited), but I made a lot of progress on it this weekend. This one has a lot of custom software, some of which is hours of work for like 10 seconds on-screen. This approach is "fun" but not efficient. At least I have a good approach to the video so it's just a matter of turning the crank now.

I finished The Messenger. My verdict is that it is good. Some aspects of it are fantastic (8-bit graphics and writing) and most are very good, but the game was not very hard and the "metroidvania" aspects of it were mostly about retreading ground between distant teleports. I managed to get all the achievements, which I don't usually do, but there was just like one hard one left.

Speaking of hard ones, next up is/was Dead Cells, whose verdict is great. This is a grindy (lots of unlockables/upgrades) roguelike platformer with really excellent controls and "flow", almost feeling like a twitchy fighting game at times. It's no "Spelunky" or even "Crypt of the Necrodancer"; what set those apart for me is how the design of the random level generation really tended to create these interesting situations and puzzles. But this game has an impressive amount of content (the graphics and the sheer variety of weapons/powerups both stand out to me) and is just really fun to play, except when you die (which is always). Just now I finally beat the game on "Hard" (second boss cell) so it may be time to retire. I bought like 9 more games on the Steam summer sale, after all!




and

Welcome to the quicksand.

I’m not sure if it’s depression or just life catching up but I’ve been having a lot of quicksand days.  Those times when you feel like you’re moving in slow-motion and things that should take 10 minutes for a normal … Continue reading




and

Get up, get up and get down

I work from home, and the marvelous company for which I work gave me a VariDesk standing desk. I can adjust it to either a standing position or a sitting position, and I do so multiple times per day. Sitting now being the thing that’s going to kill us, I try to make sure I […]




and

DATE and Switch




and

Leo Zovic: Places, Peeps And Plagues

(in-package #:cl-pestilence)

;;   This is _not_ a simulation. It's just a game. And any resemblance
;; to any world, real or imaginary, is entirely coincidental.

;;   You can copy/paste this post in its entirety into a Common Lisp
;; REPL and play around with it if you like. I'm documenting it where
;; possible, but it's just a small toy to poke at for the moment.

;;   I've been thinking a lot about asymmetric multiplayer games and
;; <gestures wildly to world at large> all this.
;; I'm not actively _trying_ to model it accurately, but it's probably
;; obvious what's been consuming my thoughts lately.

;;   Let's get right into this. I'll explain as I go, and tie a few things
;; together neatly at the end. I hope. Regardless, there will absolutely
;; be a repo sometime fairly soon.

;; A place can be tagged arbitrarily, and can contain occupants.
;; They also collect points.

(defclass place ()
  ((tags :initarg :tags :initform nil :accessor tags)
   (occupants :initarg :occupants :initform nil :accessor occupants)
   (points :initform 0 :accessor points)))

(defun place? (thing)
  (eq (find-class 'place) (class-of thing)))

(defun place (&key tags occupants)
  (make-instance 'place :tags tags :occupants occupants))

(defun gen-place ()
  (let ((tag (pick '(:apartment-building :house :cottage
		     :office-building :factory :store
		     :cafe :lounge :theater))))
    (place :tags (list tag))))

(defmethod details ((place place))
  (format nil "====================~%~a {~{~a~}}~%~{  ~a~^~%~}~%"
	  (first (tags place))
	  (rest (tags place))
	  (mapcar #'details (occupants place))))

(defmethod show ((place place))
  (format nil "~20@a ~5a [~{~a~}]~%"
	  (first (tags place)) (points place)
	  (mapcar #'show (occupants place))))

;; A peep goes places.
;; They have
;;  - their daily routine (a list of places to visit)
;;  - their todo (the part of their routine they still need to do;
;;                they are currently at the first place in this list)
;;  - their health (a number from 0 to 100)
;;  - a list of plagues
;; Finally, they _also_ collect points.

(defclass peep ()
  ((routine :initarg :routine :initform (list) :accessor routine)
   (todo :initarg :todo :initform nil :accessor todo)
   (health :initarg :health :initform 100 :accessor health)
   (plagues :initform nil :accessor plagues)
   (points :initform 0 :accessor points)))

(defun peep? (thing)
  (eq (find-class 'peep) (class-of thing)))

(defun peep (&key places)
  (make-instance 'peep :routine places :todo places))

(defun health->string (health)
  (cond ((>= health 90) "@")
	((>= health 80) "0")
	((>= health 70) "O")
	((>= health 50) "o")
	((>= health 30) ":")
	((>= health 1)  ".")
	(t "☠")))

(defmethod details ((peep peep))
  (format nil "[~a ~3d [~{ ~a~^ ->~}]]"
	  (health->string (health peep)) (health peep)
	  (mapcar
	   (lambda (place) (first (tags place)))
	   (routine peep))))

(defmethod show ((peep peep)) (health->string (health peep)))

;; A world is a list of places, occupied by peeps. The world we start
;; peeps in also determines their routine.

(defun gen-world (&key (num-places 20) (num-peeps 100))
  (let ((places (loop repeat num-places collect (gen-place))))
    (loop repeat num-peeps
       do (let* ((routine (loop repeat 5 collect (pick places)))
		 (peep (peep :places routine)))
	    (push peep (occupants (first routine)))))
    places))

(defmethod details ((world list))
  (format nil "~%~{~a~}~%" (mapcar #'details world)))

(defmethod show ((world list))
  (format nil "~%~{~a~}~%" (mapcar #'show world)))

(defmethod all-peeps ((world list))
  (loop for place in world append (all-peeps place)))

(defmethod all-peeps ((place place))
  (loop for o in (occupants place) if (peep? o) collect o))

;; `tick!`ing a world means moving every peep through their routine once.
;;   We `tick!` each peep, then `tick!` each place until all the peeps are
;; done. Then we reset their routines.
;; You can think of this as a turn in the game.

(defmethod tick! ((world list))
  (let ((peeps (all-peeps world)))
    (loop while peeps
       do (setf peeps
		(loop for p = (pop peeps) while p
		   for res = (tick! p)
		   if res collect res))
       do (mapc #'tick! world)
       do (format t "~a" (show world)))
    (loop for p in (all-peeps world)
       do (setf (todo p) (routine p))))
  world)

;; Don't worry about the details of how to `tick!` peeps or places yet.

;;   Ok, here's where it gets a bit darker. Although we _did_
;; foreshadow this in the definition of `peep`. And also in the title
;; of the accompanying blog post.

;; A plague is another living thing.
;; It has
;;  - a host (a peep that it's infecting)
;;  - a signature (a token representing its lineage and strain)
;;  - health (how well it's doing inside its host)
;;  - virulence (how likely it is to spread to another host)
;;  - efficiency (how efficient they are at feeding)
;;  - reproduce (a function that returns a new instance to push into a new host)
;;  - and a strategy (a function, possibly closed, that takes
;;    itself and its host peep and mutates)

;; Plagues do not collect points; they score differently.

(defclass plague ()
  ((host :initarg :host :initform nil :accessor host)
   (signature :initarg :host :initform "SIG" :accessor signature)
   (health :initarg :health :initform 10 :accessor health)
   (virulence :initarg :virulence :initform 10 :accessor virulence)
   (efficiency :initarg :efficiency :initform 0.2 :accessor efficiency)
   (reproduce
    :initarg :reproduce
    :initform
    #'plague
    :reader reproduce)
   (strategy
    :initarg :strategy
    :initform
    (lambda (plague peep)
      (feed! plague peep 30))
    :reader strategy)))

(defun plague ()
  (make-instance 'plague))

;; Plagues can `feed!` on peeps or plagues. To feed means to
;; take away some of the targets' health and add some to your own.

(defmethod feed! ((self plague) (peep peep) (amount integer))
  (decf (health peep) amount)
  (incf (health self) (* (efficiency self) amount)))

(defmethod feed! ((self plague) (plague plague) (amount integer))
  (decf (health plague) amount)
  (incf (health self) (* (efficiency self) amount)))

;; Plagues can also `infect!` peeps by `reproduce`ing into them.

(defmethod infect! ((self plague) (peep peep))
  (unless (infected-by? self peep)
    (let ((child (funcall (reproduce self))))
      (setf (host child) peep)
      (push child (plagues peep)))))

(defmethod infected-by? ((self plague) (peep peep))
  (member (signature self) (mapcar #'signature (plagues peep))
	  :test #'string=))

;;  `tick!`ing a plague causes it to weaken and also carry out its strategy.
;; This models the background effect of the immune system of its host.

(defmethod tick! ((plague plague))
  (decf (health plague) 1)
  (funcall (strategy plague) plague (host plague))
  plague)

;;  `tick!`ing a peep means moving them to their next place, and also
;; `tick!`ing any plagues they may have contracted. Also, peeps are
;; resilient; they heal a small amount each time they tick (to a
;; maximum of 100).
;;  If a peep dies, they no longer move. And their plagues probably
;; won't do well. Peeps like to go places. They score points for each
;; place they go to.

(defun dead? (thing) (>= 0 (health thing)))

(defmethod tick! ((peep peep))
  (unless (dead? peep)
    (let ((location (pop (todo peep))))
      (incf (points peep))
      (setf (occupants location) (remove peep (occupants location)))
      (push peep (occupants (or (first (todo peep)) (first (routine peep)))))
      (setf (health peep) (min 100 (+ 5 (health peep))))
      (mapc #'tick! (plagues peep))
      (unless (empty? (todo peep))
	peep))))

;; `tick!`ing a place causes it to score for each `peep` present. And it causes
;; any `plague`s on present `peep`s to try to `infect!` other nearby peeps.
;; Places also lose points for each dead peep they contain.

(defmethod tick! ((place place))
  (incf (points place) (length (occupants place)))
  (loop for peep in (all-peeps place)
     if (dead? peep)
     do (decf (points place) 2)
     else do (loop for plague in (plagues peep)
		do (loop for victim in (remove peep (all-peeps place))
		      if (>= (virulence plague) (random 100))
		      do (infect! plague victim))))
  place)

;;  So, now we've got the basic framework of the game in place. There are three
;; players in this game: places, peeps and plagues.
;;   A plague player automatically loses if they are completely cured, and
;; automatically wins if they manage to kill everyone. That's fairly simple.
;;   A place player wins if they manage to cure the plague. They automatically
;; lose if all the peeps die. Also, fairly simple.
;;   A peep player is trying to survive. If they manage to make it some numer
;; of turns before dying, then we have to score the game instead of declaring
;; an outright winner regardless of game state.

;;   A peep player's score is the total number of points plus remaining health
;; on all of their peeps, minus the number of active plagues on said peeps.
;;   A plague player's score is the total number of health of their plagues,
;; with a multiplier equal to the number of places fully infected by
;; their plague.
;;   A place player's score is the total number of points in their places.

(defun score (world)
  (list :peep (let ((score 0))
		(loop for p in (all-peeps world)
		   unless (dead? p)
		     do (incf score (+ (health p) (points p)))
		   do (decf score (length (plagues p))))
		score)
	:place (let ((score 0))
		 (loop for p in world
		    do (incf score (points p)))
		 score)
	:plague (let ((score 0))
		  (loop for victim in (all-peeps world)
		     do (loop for p in (plaguesvictim)
			   do (incf score (max 0 (health p)))))
		  (loop for target in world
		     if (every
			 (lambda (victim)
			   (not (empty? (plagues victim))))
			 (all-peeps target))
		     do (setf score (* 2  score)))
		  score)))

;;   I think that's all I've got for now. This is definitely an idea I want
;; to run with. At the moment, it's just a tiny, in-repl proof-of-concept,
;; and not particularly fun, but I'm going to try developing it further with an
;; eye towards turning it into an actual web game playable from this site.

;; As always, I'll let you know how it goes.

(defun pick (lst)
  (nth (random (length lst)) lst))

(defun empty? (lst)
  (null lst))




and

Timofei Shatrov: Previewing images in and out of SLIME REPL

As any Common Lisp coder knows, a REPL is an incredibly useful tool. It can be used not just for development, but for running all sorts of tasks. Personally, I don't bother making my Lisp tools into executable scripts and just run them directly from SLIME. As such, any operation that requires leaving the REPL is quite inconvenient. For me, one such operation was viewing image files, for example in conjunction with my match-client:match tool. So lately I've been researching various methods to incorporate this functionality into the normal REPL workflow. Below, I present 3 methods that can be used to achieve this.

Open in external program

This one's easy. When you want to view a file, launch an external process with your favorite image viewer. On Windows a shell command consisting of the image filename would launch the associated application, on Linux it's necessary to provide the name of the image viewer.

(defvar *image-app* nil) ;; set it to '("eog") or something

(defun view-file-native (file)
  (let ((ns (uiop:native-namestring file)))
    (uiop:launch-program (if *image-app*
                             (append *image-app* (list ns))
                             (uiop:escape-shell-token ns)))))

Note that uiop:launch-program is used instead of uiop:run-program. The difference is that launch- is non-blocking - you can continue to work in your REPL while the image is displayed, whereas run- will not return until you close the image viewer.

Also note that when the first argument to run/launch-program is a string, it is not escaped, so I have to do it manually. And if the first argument is a list, it must be a program and a list of its arguments, so merely using (list ns) wouldn’t work on Windows.

Inline image in REPL

The disadvantage of the previous method is that the external program might steal focus, appear on top of your REPL and disrupt your workflow. And it's well known that Emacs can do everything, including viewing images, so why not use that?

In fact, SLIME has a plugin specifically for displaying images in REPL, slime-media. However it’s difficult to find any information on how to use it. Eventually I figured out that SWANK (SLIME’s CL backend) needs to send an event :write-image with appropriate arguments and slime-media's handler will display it right in the REPL. The easiest way is to just send the file path. The second argument is the resulting image's string value. If you copy-paste (sorry, "kill-yank") it in the repl, it would act just like if you typed this string.

(swank::send-to-emacs '(:write-image "/path/to/test.png" "test"))

You can even send raw image data using this method. I don't have anything on hand to generate raw image data so here's some code that reads from a file, converts it to a base64 string and sends it over SWANK.

(with-open-file (in "/path/to/test.png" :direction :input  :element-type '(unsigned-byte 8))
                (let* ((arr (make-array (file-length in) :element-type '(unsigned-byte 8)))
                       (b64 (progn (read-sequence arr in) (cl-base64:usb8-array-to-base64-string arr))))
                  (swank::send-to-emacs `(:write-image ((:data ,b64 :type swank-io-package::png)) "12345"))))

Note that the first argument to :write-image must be a list with a single element, which is itself a plist containing :data and :type keys. :data must be a base64-encoded raw image data. :type must be a symbol in swank-io-package. It’s not exactly convenient, so if you’re going to use this functionality a helper function/macro might be necessary.

Image in a SLIME popup buffer

Inline images are not always convenient. They can’t be resized, and will take up as much space as is necessary to display them. Meanwhile EMACS itself has a built-in image viewer (image-mode) which can fit images to width or height of a buffer. And SLIME has a concept of a “popup buffer” which is for example used by macroexpander (C-c C-m) to display the result of a macro expansion in a separate window.

Interestingly, slime-media.el defines an event :popup-buffer but it seems impossible to trigger it from SWANK. It is however a useful code reference for how to create the popup buffer in ELisp. This time we won’t bother with “events” and just straight up execute some ELisp code using swank::eval-in-emacs. However by default, this feature is disabled on Emacs-side, so you’ll have to set Emacs variable slime-enable-evaluate-in-emacs to t in order for this method to work.

Also Emacs must be compiled with ImageMagick for the resizing functionality to work.

Anyway, the code to view file in the popup buffer looks like this:

(defun view-file-slime (file &key (bufname "*image-viewer*"))
  (let ((ns (namestring file)))
    (swank::eval-in-emacs
     `(progn
        (slime-with-popup-buffer (,bufname :connection t :package t)
          (insert-image (create-image ,ns))
          (image-mode)
          (setf buffer-file-name ,ns)
          (not-modified)
          (image-toggle-display-image))
        ;; try to resize the image after the buffer is displayed
        (with-current-buffer ,bufname (image-toggle-display-image))))))
    ))

Arriving to this solution has required reading image-mode’s source code to understand what exactly makes image-mode behave just like if the image file was opened in Emacs via C-x C-f. First off, image-mode can be a major and a minor mode - and the minor mode is not nearly as useful. slime-with-popup-buffer has a :mode keyword argument but it would cause image-mode to be set before the image is inserted, and it will be a minor mode in this case! Therefore (image-mode) must be called after insert-image.

Next, the buffer must satisfy several conditions in order to get image data from the filename and not from the buffer itself. Technically it shouldn’t be necessary, but I couldn’t get auto resizing to work when data-p is true. So I set buffer-file-name to image’s filename and set not-modified flag on.

Next, image-toggle-display-image is called to possibly resize the image according to image-mode settings. It's called outside of slime-with-popup-buffer for the following reason: the buffer might not yet be visible and have any specific dimensions assigned to it, and therefore resizing will do nothing.

Here’s an example of how calling this function looks in Emacs.

The position of the popup buffer depends on whether the original Emacs window is wide enough or not. I think it looks better when it’s divided vertically. Use M-x image-transform-fit-to-height or M-x image-transform-fit-to-width to set up the auto-resizing method (it gets remembered for future images). Unfortunately there’s no way to fit both height and width, at least with vanilla Emacs. I prefer fit-to-width because in case the image is too tall, it is possible to scroll the image vertically with M-PgDn and M-PgUp from the other buffer. Unlike other image-mode buffers, this buffer supports a shortcut q to close itself, as well as various SLIME shortcuts, for example C-c C-z to return to the REPL.

That's it for now, hope you enjoyed this overview and if you happen to know a better way to display images in Emacs, I would be interested to hear about it.




and

Nicolas Hafner: Creative Block - May Kandria Update


It's a new month, and that usually means I'm supposed to write a monthly update on the progress with Kandria. Thinking about that though made me feel very depressed because I realised that I hadn't really done anything at all for the game, all of April.

I can blame however much I want of that on the quarantine and university stress, or whatever else, but it won't change the fact that there has not been much progress on any front. While I have been slacking a lot, it's not like I haven't been working at all - plenty of time has gone into Courier, after all.

When I had this realisation yesterday, I tried my best to push myself to work on the game any way I could, but I failed to find anything that I could actually convince myself to do. That isn't to say that there aren't things to do; god forbid there's a tonne of things! Tuning combat, drawing animations, writing the UI, fixing dialogue, starting on enemy AI, optimising performance - just to name a few. And yet, despite the breadth and depth of things to do, there was absolutely nothing that looked appealing to me.

This kind of feeling is nothing new to me. It's a creative block, and happens more often that I'd like to admit. It's also why I often don't like to start long running projects, because I'm afraid of a creative block that would ruin it. The worst part about the creative block is that there's no remedy for it. You just get stuck in a rut, and it sucks a whole lot for a completely unpredictable amount of time. Often what I end up doing, whether consciously so or not, is switching to another project and just working on that.

So far that project has been Courier, but that's at its end and I'm also starting to feel burnt out on it, too. I don't have any other projects queued up that I'd like to tackle, or new ideas on what to do at the moment, so I'm just... stuck.

I suppose the right thing to do in this situation is to take it easy and not fret too much over it, since that's often one of the many factors causing the block. I've never been good at actually doing that, though. Maybe I should try to take a break from programming in general? I don't know.

You may be wondering why I'm writing this all to begin with. Well, partly I feel like I promised to do monthly and weekly updates, and I really hate to break that promise without notice. Another part is that I just feel like I owe you the discretion to tell you what's going on with me. I'm very thankful for the email replies and general responses I've gotten for Kandria so far, I really am! Because of that genuine interest, I feel all the more pressured not to disappoint. Since I have nothing to show though, I thought the only proper course of action is to just be open and direct about it. So I'll just say it again: aside from updating the public demo, no progress has been made at all.

Maybe it would help me to have a more open discussion about this topic in general, instead of just it being me telling you that I'm in a bad place. So please, let me know: have you been in similar situations before? What helped you deal with them? Is there something in Kandria I could try to focus on that you, personally, would like to see?

You can reach me at shinmera@tymoon.eu.




and

Leo Zovic: Zippers And Clj

So recently, I had to use zippers at work. Specifically, the Clojure implementation. There were some close-to-arbitrary transformations I needed to do with some close-to-arbitrary trees and it turned out that zippers were more efficient than the alternatives1.

Using them this way, combined with the general state of the world and my free time, finally tipped me into doing some more Common Lisp development. Before, I go any further, let me be clear about something.

I Like Clojure

Seriously.

Its logo is up top in the language bar, I was one of the inaugural members of the Toronto Clojure User Group, I recommend it as a first lisp you should learn, and have for about six years now. I'm also painfully aware of the shortcomings of Common Lisp, and make no excuses for them.

However.

  • I don't like the JVM. It's slow as balls, its' deployment options are less than ideal for my purposes, its' error system is at best useless, and Clojure without it is unlikely.
  • Clojurescript build incompatiblities are, if anything, worse2.
  • I don't like the underlying licensing decisions.

These are deep reasons to stay away. They're not the sort of thing I can paper over with a library or two. Fixing them would mean a superhuman amount of work poured into the underlying technical and social infrastructure, and I'm not into it. I wouldn't be into it even if the community was interested in heading that way, and near as I can tell, they're not particularly.

Whether or not I think you should learn Clojure as your first3 lisp, it definitely wasn't my first lisp. The more uniform, mostly-better-thought-out interface, lack of historical baggage and functional data structures are not enough to pull me all the way over.

It is enough for me to start plotting a smash-and-grab of as much of the stuff I like as I can carry. Which is exactly what clj represents. As of this writing, it defines and exports exactly four symbols: if-let, when-let, -> and ->>. This is a tiny beginning of the list, and I fully plan to put something more substantial together using cl-hamt, named-readtables, test-utils and possibly optima. Stay tuned to that repo if you're interested, but it's not the focus today.

cl-zipper

The thing that percipitated this thought was having used the Clojure Zipper implementation. So, obviously, this is something I want next time I need to manipulate trees in Common Lisp. The paper is here, and unless you have a terminal phobia of datastructures4, you should go read it. It's six pages, they're light, and one of them taken up by the intro and references.

The operations defined in the paper are left, right, up, down, insert_right, insert_left, insert_down and delete. There's a few conveniences defined for the Clojure version, and I've implemented some of my own stuff too. Lets go through the main file in almost-literate style.

First up, we have constructors.

(defstruct path
  (left) (path) (right))

(defstruct loc
  (node)
  (path)

  (fn-branch?)
  (fn-children)
  (fn-make-node))

;;;;;;;;;; Constructors
(defun zipper (branch? children make-node root)
  (make-loc
   :node root
   :fn-branch? branch? :fn-children children :fn-make-node make-node))

(defmethod make-zipper ((thing list))
  (zipper #'listp #'identity (lambda (node children) (declare (ignore node)) children) thing))

(defun make-node (zipper children)
  (funcall (loc-fn-make-node zipper) zipper children))

You can see influence from both clojure.zip and the paper here. I'm taking the lead from the paper by explicitly separating the path triple our from the loc definition. However, I'm not explicitly defining my own type tree the way that Huet does. Instead, I'm going to be dealing with assorted lisp trees. These could be implemented as lists, vectors, hashes, or any number of other formats. I'm going to implement a few type-distpatching built-ins, including the make-zipper list method above, but the basic zipper function just needs to take an interface as input in the form of branch?, children and make-node arguments. This is the same solution that the Clojure implementation went with, and I see no reason to go a different way. The only material difference is that theirs uses the Clojure metadata system, while I explicitly define slots in the loc structure.

Now that we can construct, we need to be able to select.

;;;;;;;;;; Selectors
(defun branch? (zipper) (funcall (loc-fn-branch? zipper) (loc-node zipper)))
(defun children (zipper)
  (funcall
   (loc-fn-children zipper)
   (loc-node zipper)))
(defun node (zipper) (loc-node zipper))
(defun path (zipper) (loc-path zipper))

(defun lefts (zipper)
  (when (loc-path zipper)
    (reverse (path-left (loc-path zipper)))))

(defun rights (zipper)
  (when (loc-path zipper)
    (path-right (loc-path zipper))))

The basic navigation is four functions; down, up, left and right

;;;;;;;;;; Navigation
;;;;;;;;;;;;;;; Basic navigation
(defun down (zipper)
  (when (children zipper)
    (let ((fresh (copy-loc zipper)))
      (setf (loc-node fresh) (first (children zipper))
	    (loc-path fresh)
	    (make-path
	     :left nil
	     :path (loc-path zipper)
	     :right (rest (children zipper))))
      fresh)))

(defun up (zipper)
  (when (path zipper)
    (let ((fresh (copy-loc zipper)))
      (setf (loc-node fresh)
	    (make-node
	     zipper (append
		     (reverse (path-left (path zipper)))
		     (cons (loc-node zipper)
			   (path-right (path zipper)))))
	    (loc-path fresh) (path-path (path zipper)))
      fresh)))

(defun left (zipper)
  (when (and (path zipper) (path-left (path zipper)))
    (let ((fresh (copy-loc zipper)))
      (setf (loc-node fresh) (first (path-left (path zipper)))
	    (loc-path fresh)
	    (make-path
	     :left (rest (path-left (path zipper)))
	     :path (path-path (path zipper))
	     :right (cons (loc-node zipper) (path-right (path zipper)))))
      fresh)))

(defun right (zipper)
  (when (and (path zipper) (path-right (path zipper)))
    (let ((fresh (copy-loc zipper)))
      (setf (loc-node fresh) (first (path-right (path zipper)))
	    (loc-path fresh)
	    (make-path
	     :left (cons (loc-node zipper) (path-left (path zipper)))
	     :path (path-path (path zipper))
	     :right (rest (path-right (path zipper)))))
      fresh)))

The main difference between this and the paper is that I've chosen nil as my Top representation, which lets me pull the trick of using when to check for the presence of a path, and its' non-Top-ness at the same time.

The bad news is that since Common Lisp doesn't have pervasive functional data structures, I have to explicitly copy locs while moving through a tree. The good news is that the copy is fairly light weight. Effectively, I'm copying out a set of 5 pointers, and could get that down to 3 by defining an intermediate struct.

Hm.

Which I probably should do. Note to self.

Out of those, we get three compound navigation functions. With more probably coming soon. Specifically, I found find useful for the work I did. It's easily externally definable, but would be even easier to bundle along. The ones I've already implemented are root, leftmost and rightmost.

;;;;;;;;;;;;;;; Compound navigation
(defun root (zipper)
  (if-let (z (while zipper #'up))
    (node z)))

(defun leftmost (zipper) (while zipper #'left))

(defun rightmost (zipper) (while zipper #'right))
Each of these involve an intermediate call to while. Which isn't a generic macro; it's a function defined in util.lisp
...
(defun until (zipper f)
  (let ((z zipper))
    (loop for next = (funcall f z) while next
       when next do (setf z next))
    z))
...
As you can see, all it does is repeatedly call a given function on a zipper and return the last non-nil loc result. That's loc, not node, so this doesn't run into the usual Common Lisp conflict of "Did you fail to find a thing, or find the element nil?".

That's the traversals done. Next up, we've got modification, without which this library is fairly useless. The basics are replace, delete and the insert/child twins.

;;;;;;;;;; Modification
(defun replace (zipper node)
  (let ((fresh (copy-loc zipper)))
    (setf (loc-node fresh) node)
    fresh))

(defun delete (zipper)
  (when (path zipper)
    (let ((fresh (copy-loc zipper))
	  (fresh-path (copy-path (loc-path zipper))))
      (cond ((rights zipper)
	     (setf (loc-node fresh) (pop (path-right fresh-path))
		   (loc-path fresh) fresh-path))
	    ((lefts zipper)
	     (setf (loc-node fresh) (pop (path-left fresh-path))
		   (loc-path fresh) fresh-path))
	    (t (setf (loc-path fresh) (path-path fresh-path))))
      fresh)))

(defun insert-child (zipper node)
  (replace
   zipper
   (make-node
    zipper
    (cond ((not (branch? zipper))
	   (list node (node zipper)))
	  ((children zipper)
	   (cons node (children zipper)))
	  (t (list node))))))

(defun append-child (zipper node)
  (replace
   zipper
   (make-node
    zipper
    (cond ((not (branch? zipper))
	   (list (node zipper) node))
	  ((children zipper)
	   (append (children zipper) (list node)))
	  (t (list node))))))

(defun insert-left (zipper node)
  (let ((fresh (copy-loc zipper))
	(fresh-path (copy-path (loc-path zipper))))
    (push node (path-left fresh-path))
    (setf (loc-path fresh) fresh-path)
    fresh))

(defun insert-right (zipper node)
  (let ((fresh (copy-loc zipper))
	(fresh-path (copy-path (loc-path zipper))))
    (push node (path-right fresh-path))
    (setf (loc-path fresh) fresh-path)
    fresh))

The paper defines an insert_down function. It fails on a Leaf node, and otherwise inserts a singleton branch at the given location. The insert/append child functions above also insert nodes at a lower level at the current loc. They give you a choice about whether to insert the new node as the leftmost or rightmost child, and additionally succeed on Leaf nodes by including the leaf value as a child of the new branch.

There are, thus far, three compound modification functions; edit, splice-left and splice-right.

(defun edit (zipper f &rest args)
  (replace zipper (apply f (node zipper) args)))

(defun splice-left (zipper node-list)
  (reduce #'insert-left node-list :initial-value zipper))

(defun splice-right (zipper node-list)
  (reduce #'insert-right (reverse node-list) :initial-value zipper))

edit takes a function instead of a new node, and replaces the node at loc with the result of running that function on the existing node. The splice-* twins are fairly self-explanatory; they're like insert-left/insert-right, but work on multiple nodes rather than single ones.

I haven't yet implemented next, prev and remove because these might relate to the different representation of the traversal end? state. The reason for this seems to be that next/prev/remove assume a depth-first traversal. The reason I'm being weasely here is that I haven't thought about it hard enough to be sure that the end? marker is really necessary. It also seems odd to privilege depth-first over breadth-first traversals; ideally, I think you'd want to be able to support either. Possibly interchangeably.

Minor Housekeeping

That wraps it up for this edition. My immediate intention is to do more work on the cl-zipper and clj libraries, as well as that game I mentioned last time. Ideally, I'd like to up my blogging output too. Probably not to the same volume as I had at my peak, but it was definitely helpful to keep some sort of written journal around for a while. The current state of the world is, hopefully, going to make it easy for me to get more programming time in. All things considered, I'd count that as a win.

  1. Although admittedly, it does require me to explain the concept of zippers to a few other people for maintenance purposes. So ironically, this adds complexity despite being much more technically elegant than other options.
  2. There's a reason that langnostic.js is a raw JS file, rather than compiled from clojurescript source, and that reason is like 90% that the compilation process is nontrivial to set up.
  3. "First", not "only". You can probably make educated guesses about which other ones I think you should learn.
  4. In which case, why are you here? This blog could kill you accidentally with an errant click or two. You should probably just go do something else.




and

my year in cities and towns, 2019

Really serious about staying out of airplanes now. Two airplane trips this year. A low key summer not feeling terrific. Lots of time doing more local stuff and not regretting it at all. Here is the short list of places. Four states. Stars indicate multiple visits to the exact same place. Past years: 2018, 2017, […]




and

Assembly Coffee Roasters Rwanda Bumbogo Coffee




and

Support your local body during the COVID-19 pandemic

Event cancellations at local bodies due to COVID-19 will reduce revenue, but not rent and other fixed expenses. Many local bodies already operate on extremely tight margins and struggle to pay their bills even during normal times. All members are encouraged to continue to financially support their local bodies, even if there are no events …

Continue reading




and

A message from the Grand Master on pandemic response

The Grand Master Sabazius has provided some useful information and advice to O.T.O. members about how to respond to the COVID-19 pandemic.









and

The Grand Mask

Some say we must mask ourselves to save ourselves and others Others say we must unmask to save America and as for the world beyond America it can kiss  our collective unmasked ass Then again  the face we know of  America itself has always been a mask covering hypocrisy with good intentions Contradiction is how it stays […]






and

A snail in the hand is better than 10 on the roof

A snail in the hand is better than 10 on the roof



View Comic!







and

[tasty review] United Tastes of America by Gabrielle Langholtz, Jenny Bowers, and DL Acken

  Feeling a little peckish? What’s your pleasure? If you’re craving something savory, perhaps we should zip on over to Illinois for some deep dish pizza and pierogies. Something a little more substantial? Well, we could feast on chicken fried steak in Oklahoma and bison burgers in Wyoming, before topping everything off with a platter … Continue reading [tasty review] United Tastes of America by Gabrielle Langholtz, Jenny Bowers, and DL Acken




and

new art crush: jane newland

  I recently “discovered” UK illustrator Jane Newland while browsing images online. Safe to say that 80% of the time, when something different/exceptional/beautiful stops me in my tracks, the artist turns out to be British. ????         Jane lives and works in Norwich (the most complete Medieval city in the UK), which … Continue reading new art crush: jane newland




and

[review + recipe] On Wings of Words by Jennifer Berne and Becca Stadtlander

  Each bird, bee, blossom, butterfly — was a source of joy and wonder for young Emily Dickinson. In this beautiful new picture book biography, aptly illustrated with a butterfly motif, we witness her singular metamorphosis from a keenly observant child into one of the most original and innovative poets in American literature. On Wings … Continue reading [review + recipe] On Wings of Words by Jennifer Berne and Becca Stadtlander




and

Rubbish in the sea and in the streets

Pieta Creek i March
One can wonder why a country like Malta, depending totally on its tourists, does not care more for the impression it gives its visitors.

Pieta Creek in February
The creeks, for instance, in S:t Julians, Sliema, Msida and Pieta are very often full of floating rubbish that could be taken out of the water easily; the rubbish gathers very often in the end of the creek and could be taken out of the water with landing nets. When going with Captain Morgan’s underwater safari you can see where the garbage ends up, something I several times have heard tourists complain about.
Pieta Creek in February
The system for collecting garbage, put out on the pavements, about every other day is very old fashioned and unhygienic. Very often people seem not to be aware of when to put out garbage in accordance with the timetable every household has received from the government; that is why one often can see plastic bags full of garbage standing on the pavement for almost 24 hours. There are high fines if you put out garbage on unauthorized time, but I have never heard of anybody that has been forced to pay such fines. Very few countries in EU have a system like this. The normal way to handle garbage is to use closed bins. Surprisingly, I have never seen rats eating from the garbage.
It seems like people think it is ok to throw papers, plastic bottles and a lot of leftover from quick lunches and many more things everywhere. Sometimes people even hide them under the few bushes although there are trash cans almost everywhere. The government has done what it can do to stop this but it is up to all of us to ensure we get cleaner streets, because, as it is now, it is disgusting.




and

The Government, The Catholic Church and the prostitution in Malta

In today's The Times, you can read in an article by David Pace O’Shea, that, in general, Maltese are a helpful people, generous, hardworking, humble, careful with their money, welcoming, peaceful and unaggressive and that they love their families and, especially, their children. In the Observer’s opinion, anyone who states that he or she has all those qualities also might add the words conceited and boastful. The word humble is not the first that comes to one’s mind when reading all the other characteristics Mr. O’Shea states that Maltese in general possess. Thank God (just an expression!) that most Maltese do not consider themselves to have all those qualities (and I do not know of any other country’s citizens that would claim all these good characteristics). Since the article is written by a convinced catholic believer it might be interesting to hear his humble view, from a moral and Christian standpoint, on prostitution in Malta. Every time one passes the area around the closed Empire Stadium one can see prostitutes hanging out from windows or standing on the street offering men their services. In Malta it is allowed to buy and sell sexual services; such services are forbidden in many other EU states. One can ask how this complies with the Maltese character as described in today’s Times. The Maltese government and the Church might not officially be in favor of prostitution but they certainly do not try hard to solve the problem. Prostitution is closely connected with criminality such as trafficking and drug related crimes. There is no reason whatsoever to let young women be treated like slaves in any country and especially not in a country like Malta, which is said to be one of the most Christian in the world. It is a shame for Malta!




and

Malta - a Lilliput state with potentates separated from and above the people?


Memorial plaque
Memorial plaque
Malta is the smallest country among EU member states. It has only about 400000 inhabitants and the area is only 312 square kilometers. The Maltese people are very proud of their country and are very right to be so. During WW II the Maltese people were very courageous and it was then the Maltese people was rewarded S: t George’s cross 1942 by the king of England, which cross since 1943 is a symbol on the Maltese flag. The president of the United States of America, Franklin D. Roosevelt, has expressed his gratitude to the Maltese people, which can be seen on a memorial plaque on the wall of the predidential palace in Valletta. 
However, the majority of Maltese do not seem to travel a lot and therefore are rather ignorant about other countries. Malta is just a rock in the Mediterranean, but, of course, historically an important rock. Yet, you can hear Maltese people quite seriously say that Malta is the most beautiful country in the world. Of course, what is beautiful is a very subjective. Still, very few people, but the Maltese, would say that Malta is the most beautiful country in the world. I have also heard that the Maltese wines as well as its vegetables are the best in the world! There might be a few countries which would like to contest that. Maybe it is beacuse of this ignorance that the Maltese people accept the behaviour of their potentates.

The government, backed by its loudspeaker, The Times, does everything to give the impression to the Maltese people that Malta has an important role to play in EU and in the rest of the world. If prime minister Gonzi for instance travels to some conference abroad, the articles in The Times have headlines giving the impression that the other prime ministers were there just to listen to Mr. Gonzi. Malta also has a Head of State, a President with his own flag and a car with a special license plate. His wife is called Malta's first lady! Even the The Commissioner of Police has his own flag as well as the Archbishop. The corruption is widely spread. But there is of course a reason for all these cars and flags and mumbo jumbo; the government wants to give the people the impression that Malta has a bigger role to play in EU and in the world than it really has and therefore one also must have men in formal high positions with attributes. One must remember that Malta, although a sovereign state, is not bigger than a middlesized european town and ought to be be governed more in accordance with that and not like United States of America..



Archbishops BMW license plate
Gozo bishops Toyota license plate
The catholic faith is state religion in Malta. The archbishop as well as the bishop of Gozo has company cars, the latter a smaller one than the BMW that is archbishop Cremona's company car. Do not for a moment think that these cars have ordinary license plates. No way, they have plates of a silvery material in the shape of a bishop’s miter. If you do not believe me, look at the pictures. And, of course, the archbishop has a more expensive car than the Gozo bishop (The Observer wonders what Jesus would think of that!).To a foreigner from a more secular state this looks really ridiculous. Of course also the prime minister’s car have special plates. As far as the Head of the State, the President, is concerned, it is more understandable. He is, after all, a symbol. If the president and the prime minister want to attend a mass in Valletta they travel by these cars about 200 meters to the church. This is just window dressing. One could argue that they travel by car for security reasons; no way, anyone could go close to these potentates. All this is also a part of implementing the belief in people that Malta and its potentates are very important, separated from and above the people. They act like royalties more than the royalties in the Netherlands, Belgium and Sweden.

President Abela's car and flag
To a foreigner all these attributes are kind of sweet and touching, except for the corruption. Malta is a Lilliput with its attributes similar to those in operettas. This is sweet, but, of course,  fulfills a not so honorable cause, namely to keep the people in a feeling that Malta is something it is not.