The 2021 Less Wrong Darwin Game

post by lsusr · 2021-09-24T21:16:35.356Z · LW · GW · 102 comments

Contents

  Food
    Predation
    Foraging for Plants
  Simple Ecosystems
    Example 1
    Example 2
    Example 3
    Example 4
    Example 5
  Multi-Biome Ecosystems
    Example 1
    Example 2
  Surviving the environment
    Temperature
  The actual game settings
    Biomes
  Questions and Answers
    How do I win?
    Can I coordinate with other players?
    Can I betray the other players who think I'm coordinating with them?
    I'm worried my species will do poorly and I'll be publicly shamed.
    How many species can I enter?
    If multiple participants enter species with the same name, will you differentiate the names so that they can prey on each other?
    Can I use multiple entry slots to spawn the same species in multiple biomes?
    Do I have to be a Less Wrong user to participate?
    I found a bug in your code.
    I like your work and would like to support you.
    What can I win?
  Example source code
  How do I participate?
None
105 comments

It's fall and that means it's time for another Less Wrong Darwin Game. This year, you'll be designing up to ten species that will compete for food including (sometimes) eating each other.

Click here to participate [Entries are now closed.] You have one week from September 23 to design your species. Submit them by September 30th or earlier.

Each player starts with a population of organisms. Each round each of your organisms will be randomly paired with another organism. At this point, one of two things will happen:

After everyone has eaten, each organism will attempt to reproduce. The more an organism eats you eat the most descendents an organism can leave.

Food

Each round your organisms lose 20% of their energy to metabolism resulting (on average) in a 20% decrease in population. You must eat food to counteract metabolism. There are two sources of food: plants and other animals.

Predation

There are two phases to combat. In the first phase organisms size each other up to figure out which is the predator and which is prey. There are two ways for an organism to become the predator.

  1. Venom. If one organism has venom but the other does not have antivenom then the organism with venom is the predator. (Antivenom is a prerequisite to venom.)
  2. Weapons. Weapons represent claws, teeth and tusks. If either organism's weapons value exceeds the prey's weapons + armor then the organism with the higher weapons value will become the predator.

Venom takes priority over weapons. Once a predator-prey relationship is established (if a predator-prey relationship is established) the prey will get a chance to escape. If the prey's speed equals or exceeds the predator's then nobody gets eaten.

Venom, weapons and antivenom all make your organism bigger, which slows down reproduction.

Adaptation Size Notes
Venom 6 Requires Antivenom
Antivenom 1
Weapons
Armor
Speed

Omnivores priorize meat over plants, when they can get it even if foraging for plants would be more metabolically efficient[1].

Predation has an efficiency of 0.95[2]. That means 95% of the prey's energy can be used by the predator.

Only organisms of different species eat each other. Cannibalism is disabled.

Foraging for Plants

There are various kinds of plant food available. In order to eat each food you'll need the proper digestive system.

Food Nutritional Value Size
Leaves 7 5
Grass 6 3
Seeds 5 1

Whether your organism can digest a particular plant food is a binary value. No organism is better at digesting leaves than any other organism.

There is a tradeoff. The ability to eat leaves/grass/seeds makes your organism bigger which slows down reproduction. Also, there is a finite supply of leaves/grass/seeds. The more other organisms are foraging from a plant source, the less advantageous it is for you to forage for it youself.

Simple Ecosystems

Consider an ecosystem with three kinds of plant food available: seeds, leaves and grass. 1,000 units of each plant food are produced per round.

Example 1

This all may sound a little confusing but it makes sense once we use some real exampless. Let's start with two species: housecats and mice.

Species Weapons Speed Eats Seeds?
Housecat 1 2 No
Mouse 0 1 Yes

At first, both populations grow. The mice reproduce faster than the cats. Then the cats catch up and eat all of the mice. Having exhausted their food supply, the cat population starves to extinction.

Example 2

What happens if we add songbirds? Songbirds fly. They are fast enough to evade cats. But speed costs energy which makes it more expensive for songbirds to breed than for mice to breed. Mice outcompete songbirds in a world without cats.

Species Weapons Speed Eats Seeds?
Mouse 0 1 Yes
Songbird 0 3 Yes

We can establish a periodic equilibrium by reintroducing cats. If the mouse population rises too much the cat population rises to eat them, decreasing the mouse population. But there is a limit to how high the cat population can get because the cat population is matched randomly with other organisms and those other organism are often songbirds.

Species Weapons Speed Eats Seeds?
Housecat 1 2 No
Mouse 0 1 Yes
Songbird 0 3 Yes

Example 3

What happens if we add a falcon so fast it can catch both mice and songbirds? The falcons and housecats eat all of their prey. Our previous equilibrium has been broken. The ecosystem collapses. Everyone dies.

Species Weapons Speed Eats Seeds?
Falcon 1 20[3] No
Housecat 1 2 No
Mouse 0 1 Yes
Songbird 0 3 Yes

To restabilize things we need more prey. Let's add koalas. Koalas eat leaves. I made them venomous to protect them from predators.

Species Weapons Speed Eats Seeds? Eats leaves? Venom/Antivenom?
Falcon 1 20 No No No
Housecat 1 2 No No No
Mouse 0 1 Yes No No
Songbird 0 3 Yes No No
Koala 0 0 No Yes Venom

The venomous koalas eat a food source (leaves) disconnected from the rest of the food chain which relies on seeds. Nothing preys on them because they are venomous and no other animals have antivenom. They koals are effectively disconnected from the rest of the ecosystem. They just get in the way of predation by the falcons and the housecats which helps stabalize the seed-based food web.

Example 4

A world where nothing preys on nor competes with koalas is boring. Let's add owls. Owls really do prey on koalas.

Species Weapons Speed Eats Seeds? Eats leaves? Venom/Antivenom?
Falcon 1 20 No No No
Housecat 1 2 No No No
Mouse 0 1 Yes No No
Songbird 0 3 Yes No No
Koala 0 0 No Yes Venom
Owl 1 2 No No Antivenom

Introducing owls gets us exciting population spikes and crashes but it wipes out the mice and housecats.

The problem is owls have too much of an advantage over housecats. Owls and housecats are almost identical. The only difference is antivenom, which is cheap. Koalas are a major food source because only owls prey on them. To give housecats a chance we need something else to prey on koalas.

Species Weapons Speed Eats Seeds? Eats leaves? Venom/Antivenom?
Falcon 1 20 No No No
Housecat 1 2 No No No
Mouse 0 1 Yes No No
Songbird 0 3 Yes No No
Koala 0 0 No Yes Venom
Owl 1 2 No No Antivenom
Mongoose 1 1 No No Antivenom

The mongeese do keep the owls in check. I'm starting to think housecats might be a lost cause. Whatever the case, we need a stabalizing animal which thrives when mongeese are present and declines when there are too many koalas. (This is just the songbirds we introduced in the beginning except for leaves/koalas/owls instead of seeds/mice/housecats.)

Giraffes eat leaves just like koalas but they are nonvenomous. I gave giraffes armor instead of weapons because if they had weapons they might eat small animals instead of leaves.

Species Weapons Armor Speed Eats Seeds? Eats leaves? Venom/Antivenom?
Falcon 1 0 20 No No No
Housecat 1 0 2 No No No
Mouse 0 0 1 Yes No No
Songbird 0 0 3 Yes No No
Koala 0 0 0 No Yes Venom
Giraffe 0 2 6 No Yes No
Owl 1 0 2 No No Antivenom
Mongoose 1 0 1 No No Antivenom

Adding giraffes got us mice and housecats back but we lost koalas along with the owls and mongeese that prey on koalas.

Example 5

Our herbivores only eat seeds and leaves. All the grass is going to waste. Lets add some grass eaters to our menagerie.

Species Weapons Armor Speed Eats Seeds? Eats leaves? Eats Grass? Venom/Antivenom?
Rabbit 0 0 0 Yes Yes Yes No
Panda 0 2 0 No Yes Yes No
Snake 0 0 1 No No No Venom

Out new ecosystem has no more diversity than the previous one. (Only six species survive to equilibrium.) But we have achieved something new. The new ecosystem sustains a food chain three trophic levels deep. Owls eat snakes eat pandas.

Multi-Biome Ecosystems

Let's compare two biomes.

Name Seed Leaf Grass
Grassland 100 10 200
Rainforest 100 200 10

Note that I set the overall plant production lower. This results in smaller populations which are more likely to be made extinct by random fluctuations. In the grassland, everything dies but songbirds. Leaves and grass go uneaten. In the rainforest we get a 3-species equilibrium of owls, pandas and mice.

Example 1

Suppose we give each animal a small chance (proportional to its speed) of wandering to a random biome. Our two biomes are now connected.

This increases biodiversity in ecah particular ecosystem. However, it does not increase overall biodiversity.

Example 2

What if we add an additional biome?

Name Seed Leaf Grass
Grassland 100 10 200
Rainforest 100 200 10
Temperate Forest 200 10 100

Housecats and falcons are back but we lost owls and snakes.

Surviving the environment

The world is a dangerous place. It's not just starvation and other animals that can kill you. You can only survive in the Ocean/Benthic if you breathe water. You can only survive on land if you breathe air. Both air and water breathers can survive on the Rivers and Coasts.

You do not have to manually set whether your organism breathes air or water. This will be inferred from your spawning location. You cannot start in a river or on a coast.

Temperature

You need heat tolerance to survive in the desert. You need cold tolerance to survive in the tundra.

Temperature Adaptation Size
Heat Tolerance 2[4]
Cold Tolerance 2[4:1]

Heat and cold tolerance are not useful for aquatic organisms.

The actual game settings

The actual game is more complicated than my examples. There are more biomes and more plant foods available. I will not be entering my own animals into the game. Only player animals will be included.

Food Nutritional Value Size
Carrion 10 6
Leaves 7 5
Grass 6 3
Seeds 5 1
Detritus 4 3
Coconuts 3 4
Algae 2 2
Lichen 1 1[5]

Biomes

Name Carrion Leaves Grass Seeds Detritus Coconuts Algae Lichen
Grassland 0 100 1000 2,000 0 0 0 50
Rainforest 0 1000 2,000 100 0 0 0 50
Temperate Forest 0 2,000 100 1000 0 0 0 50
Ocean 10 0 0 0 10 0 10,000 0
Benthic 10 0 0 0 1000 0 0 0
Tundra 1 1 1 1 1 0 0 300
Desert 100 0 1 1 1 0 0 0
Shore 0 0 0 0 20 1000 1000 10
River 500 500 500 500 500 500 500 500
Human Garbage Dump 100 100 100 100 100 100 100 100

Edit: I recognize, after posting this, that "Grassland" produces less grass than the Rainforest. Too late now; players have already submitted organisms.

Questions and Answers

How do I win?

Your species survives.

Can I coordinate with other players?

There is no rule against it.

Can I betray the other players who think I'm coordinating with them?

There is no rule against it.

I'm worried my species will do poorly and I'll be publicly shamed.

Use a pseudonym. I will only link to social media if you do well.

How many species can I enter?

Up to 10. I am relying on the honor system. Please do not abuse it.

If multiple participants enter species with the same name, will you differentiate the names so that they can prey on each other?

Yes.

Can I use multiple entry slots to spawn the same species in multiple biomes?

Sort of. I will differentiate the names. You will have two separate species with identical stats but different starting conditions.

Do I have to be a Less Wrong user to participate?

You do not have to be affiliated with Less Wrong. Anyone is welcome to participate. Invite your friends to play!

I found a bug in your code.

Please post a comment or private message me.

Edit: Multicore discovered some major bugs in the code I used for examples. The real game may be very different.

I like your work and would like to support you.

You are under no obligation whatsoever to send donations. My primary objective is to make a fun, educational game for lots of people.

That said, I do like money. You can Venmo me @Lsusr

What can I win?

Honor and glory. I will link to the winners' social media accounts. (Unless it is something I consider dangerous or object to on moral grounds.)

Example source code

You can try out different strategies with the source code below. It is run with hy. You can install hy with pip $ pip3 install hy. You will need matplotlib too. Install it with $ pip3 install matplotlib.

Source code available on GitLab

How do I participate?

Design your species here. [Entries are now closed.] You have one week from September 23 to design your species. Submit them by September 30th or earlier.


  1. This seemingly-irrational behavior has precedent among human beings due to sexual competition. Jared Diamond writes about why in his book Why Is Sex Fun?: The Evolution of Human Sexuality. ↩︎

  2. Changed from 0.80. ↩︎

  3. In the real game, weapons, armor and speed will all be limited to 10. ↩︎

  4. Reduced from 5. ↩︎ ↩︎

  5. Changed from 3. ↩︎

102 comments

Comments sorted by top scores.

comment by Multicore (KaynanK) · 2021-09-24T13:05:09.735Z · LW(p) · GW(p)

The original post does not explain in detail how organisms move from biome to biome. Looking at the code it seems to be like this:

-Each organism has a chance to roam at each step proportional to its speed. An organism with speed 10 will roam 1/1000 of the time. An organism with speed 0 will never roam to another biome. This seems like an extremely important consideration for any species that could survive in multiple biomes: put at least one point into speed.

-If an organism chooses to roam, it goes to a randomly chosen biome, including the one it just came from.

-If it can't survive in that biome, it dies.

Replies from: lsusr, elspood
comment by lsusr · 2021-09-24T20:55:56.834Z · LW(p) · GW(p)

Yes. Confirmed. Thank you for elaborating.

comment by elspood · 2021-09-25T03:56:57.033Z · LW(p) · GW(p)

If my understanding of the code is correct, if the organism successfully roams, it basically spawns another copy of itself, leaving the original behind to compete in the source biome . That organism isn't removed from the competition pool. Given the relatively low roaming rate, I'm not sure this makes a huge difference, but it doesn't seem like it should be intended behavior.

Replies from: lsusr
comment by lsusr · 2021-09-25T06:57:17.738Z · LW(p) · GW(p)

The method .pop removes the roamer from the original population.

Replies from: elspood
comment by elspood · 2021-09-25T10:25:23.125Z · LW(p) · GW(p)

Ah, ok. So instead of competing in that generation, the individual roams.

Replies from: lsusr
comment by lsusr · 2021-09-25T19:58:51.009Z · LW(p) · GW(p)

Roamers don't skip competitions. Roaming happens between competitions for food.

Edit: I was wrong. See thread.

Replies from: elspood
comment by elspood · 2021-09-25T20:45:22.005Z · LW(p) · GW(p)

Not what I'm seeing. Roamers start roaming before the encounters in each biome, then after every biome is processed, the roamers find a new home. So the roamers go a whole generation without competing or foraging. Is that not what was intended?

Replies from: lsusr
comment by lsusr · 2021-09-25T20:54:04.289Z · LW(p) · GW(p)

You're right. I'm wrong. Good spotting! This behavior wasn't intended but I'm keeping it because it's interesting and makes some biological sense.

Replies from: elspood
comment by elspood · 2021-09-25T21:29:45.682Z · LW(p) · GW(p)

It would also be kind of a pain in the ass to change! :)

comment by elspood · 2021-09-29T22:14:13.472Z · LW(p) · GW(p)

Embarrassing story:

I spent a lot of time writing a fast simulator and testing all kinds of approaches. Today I let my daughter (8) design a species without really understanding the game mechanics...and it performed better than every other creature on the first try. Granted, I had to help her correct some obviously suboptimal choices, but still...let's just say my confidence is not high.

I'll precommit to suggesting a secondary scoring mechanism for bragging rights: not simply the highest total number of surviving organisms but the total energy of the organisms (population * base energy).

Good luck everyone!

Replies from: __nobody
comment by __nobody · 2021-10-01T02:33:33.679Z · LW(p) · GW(p)

I didn't trusty myself to reimplement the simulator - any subtle change would likely have invalidated all results. So simulations were real slow... I still somehow went through about 0.1% of the search space (25K of about 27M possible different species), and I hope it was the better part of the space / largely excluding "obviously" bad ideas. (Carefully tweaking random generation to bias it towards preferring saner choices, while never making weird things too unlikely.) Of course, the pairings matter a lot so I'm not at all certain that I didn't accidentally discard the best ones just because they repeatedly ended up in very unfortunate circumstances.

There certainly were some kinda non-intuitive choices found, for example: A Benthic creature that can (also) eat grass -- it can't start in the river, but that's where it wants to go; and travel-wise, Ocean/Benthic are equivalent! (Also, for some reason, others trying the same strategy in the ocean performed way worse... absolutely no idea why yet.)

I'd have loved for this to happen in a less-busy week (not exactly the end of the quarter year with all the bookkeeping) and to have about 2-3x as much time to get the infrastructure working... managed to barely get simple mutation working, but didn't have time for the full genetic algorithm or other fancy stuff. :(

Replies from: Measure
comment by Measure · 2021-10-01T11:16:57.867Z · LW(p) · GW(p)

There's definitely a rock-paper-scissors dynamic where smaller herbivores are more efficient than larger ones while being less resilient to predators. There could also be a strong random element if the total number of species is much higher than what the food sources can support and the RNG has to decide who starves first (not to mention the people who submit identical species).

comment by Multicore (KaynanK) · 2021-09-30T01:56:34.202Z · LW(p) · GW(p)

Here's some embedded prediction elicitation thingies about how the game will go.

(I've already made my submissions; this is not a ploy to gather information.)

Replies from: Taleuntum, aphyer
comment by Taleuntum · 2021-10-01T12:32:59.188Z · LW(p) · GW(p)

One common outcome (though not universal) in my simulations was that the carni/omnivores kill the non invincibles, then the pure carnivores starve to death and then the minimal size invincibles outcompete to extinction the non-minimal invincibles (which also includes the omnivores, the multi-herbivores and the animals able to migrate). I'm curious on how many biomes this outcome will play out.

Replies from: Measure
comment by Measure · 2021-10-01T12:58:51.660Z · LW(p) · GW(p)

I may or may not have submitted multiple minimal invincibles.

Replies from: elspood
comment by elspood · 2021-10-01T13:16:28.894Z · LW(p) · GW(p)

My definition of "minimal invincibles" here:

0 ATK, 10 DEF, 1SPD, Antivenom herbivore

OR

0 ATK, 0 DEF, 10SPD herbivore

These definitely win in a field of hundreds of participants. In my simulations, they were outcompeted by "less" invincible creatures fitting the invincible prototypes with 20-50 participants (200-500 creatures). I hedged my bets with a few invincibles, some hard-to-kills, and some things I found surprisingly hard to kill.

Also, my daughter's creature, so she has a chance to embarrass us all. :)

Did anyone find a way to reliably crash the populations of non-invincibles with fewer than 200 creatures (a reasonable amount of confederates you could wrangle)?

Replies from: Bruce G
comment by Bruce G · 2021-10-02T03:05:55.568Z · LW(p) · GW(p)

Why would something with full armor, no weapons, and antivenom benefit from even 1 speed?  It does not need to escape from anything.  And if it has no weapons or venom, it can not catch any prey either.

Edit: I suppose if you want it to occasionally wander to other biomes, then that could be a reason to give it 1 speed.

comment by aphyer · 2021-10-01T20:07:56.241Z · LW(p) · GW(p)

Since submissions are already in, one thing that makes me think Energy 20 creatures can survive is the Desert. The smallest creature that can survive in the desert (a defenseless heat-adapted Carrion-eater) is Size 8. This makes me expect that genuinely large predators can survive at least in the Desert, if perhaps nowhere else.

comment by lsusr · 2021-09-25T00:20:59.494Z · LW(p) · GW(p)

Announcement

I made a few small changes, including bug fixes, due to reader feedback. The changes are listed in the footnotes. Make sure you are using the newest code.

Replies from: lsusr
comment by lsusr · 2021-09-25T20:12:24.260Z · LW(p) · GW(p)

Announcement

I fixed another bug [LW(p) · GW(p)]. If you're running the code locally, pull from GitLab so herbivore roaming works properly.

Replies from: lsusr
comment by lsusr · 2021-09-25T20:31:45.960Z · LW(p) · GW(p)

Announcement

Spencer Pearson noticed a bug that increased the variance by letting only half of the animals reproduce and causing the other half to reproduce twice. I have fixed it.

comment by Nathan Helm-Burger (nathan-helm-burger) · 2021-10-03T02:01:03.856Z · LW(p) · GW(p)

Hey so, this tickled my curiosity and I went exploring for similar projects just to see what's out there. I came across a couple youtube videos I enjoyed enough to feel they were worth passing on. So just in case you are also fascinated by similar sorts of sims...

 

comment by Multicore (KaynanK) · 2021-09-24T21:38:38.128Z · LW(p) · GW(p)

Here's the elephant in the room I think a lot of our discussion should be centered around:

Consider an organism that has the ability to eat seeds and absolutely nothing else, for a total energy of 1.1. Call it a locust.

Because each species gets a starting energy budget rather than a starting population, Locusts will have a starting population of almost 1000, while an organism with a size of 20 would have a starting population of only 50.

A seed gives five energy, and reproduction is energy over cost, so every locust that eats a seed means about five new locusts in the next generation. That population advantage will only increase until they hit carrying capacity. Grassland has 2000 seeds, so it can sustain something like ten thousand locusts.

You might expect predators to handle them, but a locust's corpse gives less food than the least nutritious plant. Most predators when faced with locusts will starve to death while having a successful hunt every day.

The only way for predators to compete in the same biome is for them to be small, with a cost of 4 or less, small enough to have population growth while eating nothing but locusts. Potentially these small predators could then provide a food supply for larger predators, but if small predators aren't submitted or go extinct, larger predators are probably locked out of biomes that have locusts in them. This would be good news for vegetarians, who would then compete with each other over the non-seed food sources.

If you're feeling lazy I suggest submitting the locust design for one of the biomes with seeds, because it seems really strong.

Replies from: Measure, lsusr, simon
comment by Measure · 2021-09-25T00:35:31.459Z · LW(p) · GW(p)

I also came up with this strategy (I called them weevils), but I think it's beaten by a small omnivore that eats both seeds and weevils/locusts.

Replies from: simon
comment by simon · 2021-09-25T03:22:03.574Z · LW(p) · GW(p)

Tested: 

Verified: the omnivore wipes them out in 40 generations in my test with both starting on grassland and no other animals in the simulation.

on the other hand:

if a specialized killer of the omnivore is added (weapons 2, speed 2, nothing else) then it eventually (85 generations) killed off the omnivore in my simulation and was able to subsequently co-exist with the minimal seed-eater, which it also predated but not enough to crash the population. Theoretically, the omnivore could move somewhere else, but no such populations got established in my simulation.

 (edit: post bugfix, this was 38 generations and 114 generations. The omnivore did spread to other biomes, but its nemesis spread too and wiped out the colonies before dying out in the biomes without the mimimalist)

comment by lsusr · 2021-09-24T21:42:08.847Z · LW(p) · GW(p)

You might expect predators to handle them, but a locust's corpse gives less food than the least nutritious plant.

Update: I changed the efficiency of predation from 0.80 to 0.95. Eating a locust now gives slightly more food than the least nutritious plant.

Replies from: lsusr
comment by lsusr · 2021-09-24T22:01:00.537Z · LW(p) · GW(p)

Another update: I have reduced the price of temperature adaptations from 5 to 2. Previously, it was barely possible to survive in the tundra even under ideal conditions.

comment by simon · 2021-09-24T23:40:03.668Z · LW(p) · GW(p)

I was thinking of the name Tribbles for this strategy.  Locusts would be fast, I think.

comment by hath · 2021-09-24T14:01:14.396Z · LW(p) · GW(p)

Invitation to any potential collaborators who want to design species that will be able to survive in equilibrium with each other; PM me for details.

comment by elspood · 2021-09-25T10:46:46.805Z · LW(p) · GW(p)

There is no initial check to see if a species can survive in its spawning biome. Obviously this doesn't matter for breathing, but species could live in the desert or tundra for free without the corresponding traits.

Replies from: lsusr
comment by lsusr · 2021-09-25T20:00:20.417Z · LW(p) · GW(p)

Whoops. That is a bug. Thanks for spotting. I will fix it before running the final competition, either by writing code or just manually removing the organisms initially spawned into a biome they can't survive.

Replies from: lsusr
comment by lsusr · 2021-09-25T20:20:45.688Z · LW(p) · GW(p)

I have added code that raises an exception when an organism is spawned somewhere it can't survive.

comment by GuySrinivasan · 2021-09-24T22:58:08.326Z · LW(p) · GW(p)

I have submitted 10 entries. At least two are guaranteed to lose. At least two are elephants, because why not, c'mon. I have high hopes for two. I have extremely high hopes for two more but not because I think they're likely to survive. The last two are unremarkable.

Thanks for putting this together Isusr!

comment by aphyer · 2021-09-24T21:12:22.543Z · LW(p) · GW(p)

I'm publicly announcing an intent to consume grass. I will be submitting several animals that eat grass. If you do not wish to clash with me over food sources, I recommend choosing a different food source for your herbivores.

comment by aphyer · 2021-09-25T12:21:59.923Z · LW(p) · GW(p)

I may be mistaken, but I think there is an issue in the code that will make spreading to new biomes very difficult.

It looks like animals are only evaluated in pairs. If there are an odd number of animals, the one at the end will not be evaluated (and so will automatically die).

If you spread to a new biome that already has its own population, this is not a problem.

But if you are the first herbivore to wander into the empty River, I think this means you will automatically die.

I think the only way empty biomes can be populated is if two herbivores happen to wander into the same biome at the same time.

Am I misunderstanding?

Replies from: elspood
comment by elspood · 2021-09-25T13:50:14.776Z · LW(p) · GW(p)

I thought the same thing at first, but I think if the interact method is called with only one argument, then that creature ends up foraging normally. Since spawning depends on creature size and reproduction depends on energy, it seems equally likely that each biome will have an even number of creatures after each generation as they would odd. So this situation would happen whether roaming is occurring or not.

The tough situation is for carnivores; if they're the odd one out, they'll die, even if there are species that they could eat.

Replies from: aphyer
comment by aphyer · 2021-09-25T14:27:49.475Z · LW(p) · GW(p)

Hm.  I'm looking at the code and I don't quite understand how it works (argh, Lisp).  Is anyone able to explain what's going on here:


    (lfor i (range (// (len biome.population) 2))
          (interact biome
                    (. biome.population [i])
                    (. biome.population [(inc i)])))))

 

Suppose you have 1001 animals in your region.  It looks to me like:

  • The range fills up with numbers up to 500 or 501 depending on rounding.
  • Then animal 1 interacts with animal 2.
  • I think the intended next step is for animal 3 to interact with animal 4, and so on.
  • At that point, depending on which way the rounding went we could either:
    • Stop when animal 999 interacts with animal 1000.  Animal 1001 won't interact with anything, and will die by default.
    • Attempt to have animal 1001 interact with animal 1002.  In languages I know this would lead to an error (when you try to pull element 1002 out of a 1001-element array).  Does this actually work as-intended in Lisp?
  • On looking at this in more detail, though, I'm worried that what actually happens is that animal 1 interacts with animal 2, then animal 2 interacts again with animal 3, then animal 3 with animal 4, and so on through animal 500 interacting with animal 501, and then animals 502-1001 do not interact with anything and just die?  

I'd imagine that the code should instead use 2i and 2i + 1 instead of i and i + 1 to index into the population, but I don't actually know Lisp and maybe I'm misunderstanding how loops/increments work.

Replies from: lsusr
comment by lsusr · 2021-09-25T20:11:20.102Z · LW(p) · GW(p)

So that's why it's been so hard for herbivores to colonize new biomes. Thank you aphyer. I have fixed both bugs.

comment by cousin_it · 2021-09-24T19:04:02.233Z · LW(p) · GW(p)

The "get in the way of predation" mechanic seems strange. In reality, if I'm a giraffe hunter and there are a lot of giraffes, adding a lot of songbirds (who don't interact with me or with giraffes) shouldn't make my giraffe hunting any less efficient. Maybe replace with some other mechanic?

Replies from: GuySrinivasan
comment by GuySrinivasan · 2021-09-24T19:25:20.073Z · LW(p) · GW(p)

OTOH I have seen my dog bark at a turtle for a long time and also my dog's weapons definitely do not beat the turtle's armor.

comment by Error · 2021-09-25T02:20:22.079Z · LW(p) · GW(p)

I want to test my organisms before submitting them and noticed there wasn't a way to tell the program to use my species files instead of the one in the repo. Also, the shabang line breaks on systems that aren't yours.

I sent you an MR covering both, but I don't know if you're watching them so I figured I'd mention it here.

Is it normal for it to take a couple seconds per generation to run?

Replies from: lsusr
comment by lsusr · 2021-09-25T02:30:47.539Z · LW(p) · GW(p)

You're right. I'm not watching the merge requests. Code merged. Thanks for the improvements.

Is it normal for it to take a couple seconds per generation to run?

Yes,

Replies from: lsusr, Error
comment by lsusr · 2021-09-25T20:19:18.708Z · LW(p) · GW(p)

I just used the -g flag and the CSV argument. Your changes are a quality of life improvement. Thank you.

comment by Error · 2021-09-25T15:00:48.364Z · LW(p) · GW(p)

Thanks, and you're welcome.

Hrm. So testing organisms takes a while. Oh well. I might try to parallelize it, but I don't actually know hy, I'm just blindly translating python idioms, and concurrency is hard.

I notice that the hy version in the ubuntu repos will not run the program, apparently due to an upstream bug. The version from pip will. I mention this in case anyone else runs into the same hiccup.

Replies from: hath
comment by hath · 2021-09-25T15:59:32.603Z · LW(p) · GW(p)

I might try to parallelize it to some degree. It seems like the biomes might be able to be run separately, and the pairings might as well. No promises, though.

comment by Edward Pascal (edward-pascal) · 2021-10-04T01:10:18.754Z · LW(p) · GW(p)

If I am not mistaken, your gitlab page is not functioning right now. No way to search for you as a user either.

PS: Thanks for offering this game. Being at the intersection of economics and D&D, I am almost exploding with excitement to see what happens!

Replies from: lsusr
comment by lsusr · 2021-10-04T01:13:12.265Z · LW(p) · GW(p)

I temporarily disabled it. I'l re-enable it after the game is finished.

Thanks for letting me know. I have added a note.

Replies from: lsusr
comment by lsusr · 2021-10-06T21:38:50.536Z · LW(p) · GW(p)

Update: The GitLab repo is back online.

comment by elspood · 2021-09-29T11:28:36.548Z · LW(p) · GW(p)

Can you give a more specific deadline? What timezone?

Replies from: __nobody
comment by __nobody · 2021-09-29T21:07:12.563Z · LW(p) · GW(p)

Seconding this, does 'by Sep 30th' mean start or end of the day? I'm currently assuming 'end of', in some unspecified time zone.

My computer's still crunching numbers and I'm about to head to bed… would be sad to miss the deadline.

Replies from: lsusr
comment by lsusr · 2021-09-29T21:38:25.496Z · LW(p) · GW(p)

End of September 30th, Pacific Time.

comment by MrThink (ViktorThink) · 2021-09-25T17:15:23.909Z · LW(p) · GW(p)

A question about mechanics:

When I run a simulation with only this animal on Tundra:

Biome: Tundra

Venomous: No

Weapon: 0

Armour: 1

Speed: 0

Eats: Seeds

Cold (Allows survival in the Tundra): Yes

It goes down to 2-3 population for a while, and then dies after 25 generations.

However, I calculate the size is 1.85 (0.1 base + 0.75 armour + 1 eats seed size), and it should only need 20% of that in food per turn, which is <0.4. Tundra has 1 seeds per turn, which should give 5 food. Does anyone have an explanation why it doesn't stabilize around a population of 5/0.4≈12?

I'm not sure if I just misunderstood the mechanics, or if maybe I messed up something when testing the code, but would be grateful if anyone could clarify what should happen in this situation.

Replies from: aphyer
comment by aphyer · 2021-09-25T18:24:17.477Z · LW(p) · GW(p)

There is a random element in reproduction.  If your animal would have an average of let's say 1.1 descendants, what actually happens is that it gets 11 separate 1-in-10 chances to reproduce, and could in theory produce any number of descendants from 0 to 11 (though with an average of 1.1).

On average, with large numbers of animals, this averages out the same way.  However, when your population is very small, there's always a chance that it'll randomly die.  I imagine this is what's going on with your population, though not certain.

Replies from: aphyer
comment by aphyer · 2021-09-25T18:25:52.168Z · LW(p) · GW(p)

(Also, your animal is larger than you think: Cold Resistance has a size cost of 2, so your animal's size is actually 3.85)

Replies from: ViktorThink
comment by MrThink (ViktorThink) · 2021-09-25T19:13:26.194Z · LW(p) · GW(p)

Thank you aphyer! You're absolutely right, the size is 3.85, so it needs like 0.8 energy per turn.

5/0.8≈6, with this number it's more likely for the animal to die out by random chance.

I redid the experiment on the Benthic biome, and removed the cold resistance, set Seeds in the biome to 1, and the species survives with around 6-21 in population, which is around the population of 12 we would expect.
 

comment by MatIsk · 2021-09-25T07:39:29.909Z · LW(p) · GW(p)

The problem: your predator-prey system leads by default to extinction. 

Lotka-Volterra equations did not. Maybe something else should be changed in the model (like the carrying capacity? reproduction rate coefficient with prey abundance? the random mating simulation?), so that this problem is resolved in a similar way?

I know anecdotally, that models of evolving food webs typically are unstable. It would be great to hear more insights on this from the community :)

comment by aphyer · 2021-09-24T23:44:13.764Z · LW(p) · GW(p)

Thank you for making this!  I've made my submissions, now just time to hang around and see if any of them work...

Replies from: lsusr
comment by lsusr · 2021-09-24T23:58:57.201Z · LW(p) · GW(p)

I look forward to finding out how well they do.

comment by 1a3orn · 2021-09-24T13:52:11.969Z · LW(p) · GW(p)

Will all user-submitted species entered into a single environment at the end? I.e., does the biodiversity depend on the number of submissions?

Replies from: hath
comment by hath · 2021-09-24T16:25:39.391Z · LW(p) · GW(p)

From the code, yes.

Replies from: lsusr
comment by lsusr · 2021-09-24T20:55:40.328Z · LW(p) · GW(p)

Yes. Confirmed.

comment by elspood · 2021-09-24T12:36:38.514Z · LW(p) · GW(p)

Spelling: *dEtritus

Replies from: lsusr
comment by lsusr · 2021-09-24T20:59:09.963Z · LW(p) · GW(p)

Fixed. Thanks.

Replies from: Milli
comment by Milli | Martin (Milli) · 2021-09-27T17:15:01.429Z · LW(p) · GW(p)

There are some occurrences in the git of Ditritus as well and more importantly in the google Form.

Replies from: lsusr
comment by lsusr · 2021-09-27T18:54:15.552Z · LW(p) · GW(p)

Thanks. I fixed the form and the git repo.

comment by Bruce G · 2021-09-29T11:32:16.858Z · LW(p) · GW(p)

One thing I am confused about:

Suppose an organism can eat more than one kind of plant food and both are available in its biome on a given round. Say it can eat both leaves and grass and they are both present and have not been eaten by others on that round yet.

Will the organism eat both a unit of leaves AND a unit of grass that round - and thus increase its expected number of offspring for the next round compared to if it had only eaten one thing?  Or will it only eat the first one it finds (leaves in this case) and then stop foraging?  From the source code, it looks like it is probably eating only the one thing and then stopping, but I am not really familiar with Hy or Lisp syntax so I am not sure.

Replies from: aphyer
comment by aphyer · 2021-09-29T14:29:59.173Z · LW(p) · GW(p)

It will eat the first thing it finds, looking for things in descending order of how much nutrition they give (so yes, leaves in this case).

Replies from: Bruce G
comment by Bruce G · 2021-09-30T01:44:19.829Z · LW(p) · GW(p)

Got it, thanks.

comment by Cate Hall (cate-hall) · 2021-09-26T19:07:11.370Z · LW(p) · GW(p)

Point of clarification: Does venom/antivenom merely determine the direction of the predator/prey relationship, and then the ordinary numerical comparison of predator weapons vs. prey (weapons + armor) determines whether predation occurs?

Replies from: lsusr
comment by lsusr · 2021-09-26T20:03:49.957Z · LW(p) · GW(p)

No. Venom/antivenom merely takes priority over weapons+armor.

If one species has venom and the other lacks antivenom then weapons+armor doesn't matter. The venomous species becomes the predator.

If either species has antivenom or neither species has venom then weapons+armor determines whether predation occurs.

Either way, once the predator-prey relationship is established (if it is established), the predator must have higher speed too in order to catch it's prey.

Replies from: cate-hall
comment by Cate Hall (cate-hall) · 2021-09-26T20:20:17.453Z · LW(p) · GW(p)

Ah, thanks! So (venom, 0 weapons, 0 armor, 10 speed) > (no antivenom, 100 weapons, 100 armor, 9 speed)? Thanks!

Replies from: lsusr
comment by lsusr · 2021-09-26T20:28:08.711Z · LW(p) · GW(p)

The first eats the second, yes. Do note that the second could eat (antivenom, 0 weapons, 0 armor, 0 speed) whereas the first cannot.

comment by Yonge · 2021-09-26T11:31:44.377Z · LW(p) · GW(p)

When I attempt to run the script from the command line I get the following errror:

File "c:\programfileswithnospace\lib\site-packages\matplotlib\__init__.py", line 107, in <module>
   from . import _api, cbook, docstring, rcsetup
 File "c:\programfileswithnospace\lib\site-packages\matplotlib\rcsetup.py", line 24, in <module>
   from matplotlib import _api, animation, cbook
 File "c:\programfileswithnospace\lib\site-packages\matplotlib\animation.py", line 34, in <module>
   from PIL import Image
 File "c:\programfileswithnospace\lib\site-packages\PIL\Image.py", line 114, in <module>
   from . import _imaging as core
ImportError: DLL load failed while importing _imaging: The specified module could not be found.

 

Does anyone know how this could be fixed?

Replies from: lsusr
comment by lsusr · 2021-09-26T18:24:09.209Z · LW(p) · GW(p)

That appears to be Windows related. I don't know how to fix it properly. But the error looks like it's limited to graphing. The code might work if you disable all the matplotlib graphing and do everything via text instead.

comment by __nobody · 2021-09-25T14:14:05.991Z · LW(p) · GW(p)

Another question: where does the script save the data / graphs when running it? Or does it do that at all?

It looks like it might try to open a plot window, but I'm running it on a headless server... so nothing will happen. Is the (hard-to-parse) text scrolling by all that I'll get at the end of a run?

Replies from: Measure, lsusr
comment by Measure · 2021-09-25T14:42:29.877Z · LW(p) · GW(p)

On my Windows machine it opens a plot window that has UI to save the image.

Replies from: Measure
comment by Measure · 2021-09-25T15:01:03.721Z · LW(p) · GW(p)

lsusr might know what command to add to trigger the save operation.

Replies from: lsusr, __nobody
comment by lsusr · 2021-09-25T20:48:56.401Z · LW(p) · GW(p)

On my Linux machine it opens a plot window that has UI to save the image.

comment by __nobody · 2021-09-25T15:54:26.368Z · LW(p) · GW(p)

I've got it mostly working now... problem is that the default plot size is unusable, the legend overlaps, etc. etc. -- when run interactively, you can just resize the window and it'll redraw, and then you save it once you're happy. So now I'm also setting plot size, font size, legend position, and then it's "just" a (plt.savefig "plot.png") added before the (plt.show).

I might also add a more easily parseable log output, but for now tee and a small Lua script mangling it into CSV is enough.

I'll probably clean up all of that in a couple of hours and send another patch / merge request. Tho it's probably a good idea to get someone else to review it given that I have near-zero prior experience w/ Python.

comment by lsusr · 2021-09-25T20:27:05.511Z · LW(p) · GW(p)

[W]here does the script save the data / graphs when running it?

It doesn't. The project should have a persistent memoization system but I didn't implement one. The way to save the data is to pipe your output into a file. The way I save the graphs is to click "Save the figure" on your graph.

Is the (hard-to-parse) text scrolling by all that I'll get at the end of a run?

Yup. If anyone wants to improve the system I am happy to accept merge requests.

comment by MatIsk · 2021-09-25T08:35:45.969Z · LW(p) · GW(p)

We need a full specification of what is a legitimate entry. Is there no size limit?

Replies from: lsusr
comment by lsusr · 2021-09-25T08:40:05.770Z · LW(p) · GW(p)

There is no size limit. If you can submit a species via the Google Form then it is valid. The only rule besides that is "no submitting more than 10 species".

comment by simon · 2021-09-25T02:04:21.954Z · LW(p) · GW(p)

I'm trying to run the source code to test it, but unfortunately I'm not familiar with hylang (and low familiarity with python). 

I've (or at least attempted to) installed hy and matplotlib and tried to run "hy main.hy" (is that the way you are supposed to run it?):

I get an error in line 105 when I run that:

    (return 1))
   ^
hy.errors.HySyntaxError: parse error for pattern macro 'if': got unexpected token: hy.models.Expression([
 hy.models.Symbol('return'),
 hy.models.Integer(1)]), expected: end of file

Anyone know what I'm doing wrong?

Replies from: lsusr
comment by lsusr · 2021-09-25T02:09:17.383Z · LW(p) · GW(p)

Are you running the same version of hy and python3 that I am [LW(p) · GW(p)]?

$ hy main.hy is indeed the standard way or running the code. An alternative method is available here [LW(p) · GW(p)].

Replies from: simon
comment by simon · 2021-09-25T02:14:08.523Z · LW(p) · GW(p)

(cleaned up with edits) OK, I was running:

hy 1.0a3 

matplotlib 3.4.3

python 3.9.0

And thanks, after the following it worked, no need to change the others:

pip3 uninstall hy

pip3 install --user hy==0.20.0

Replies from: lsusr
comment by lsusr · 2021-09-25T02:25:20.235Z · LW(p) · GW(p)

Whelp. Looks like I need to update my own hy after this game is over.

comment by __nobody · 2021-09-25T00:51:51.935Z · LW(p) · GW(p)

Do you have a more exact version spec? Because I don't even have pip3 and I don't use Python, so I just installed the hy that comes with my distro... and then I get

  File "./main.hy", line 63, column 1

  (defn initial-population [biome]
    "Creates a list of initial organisms"
    (+ [] #*
       (lfor species +species-list+
             (if (= (. species ["spawning-zone"])
                    biome)
               (do
                 (setv organisms [])
                 (setv energy +seed-population-energy+)
                 (while (> energy 0)
                   (.append organisms (.copy species))
                   (-= energy (energy-of species)))
                 organisms)
               []))))
HyTypeError: b"`*' is not a defined reader macro."

and I don't even have a clue what the b"``*' part is supposed to mean...


I experimented some more, no clue what package I'd have to install to get pip - neither pip nor pip3 exist. On the systems that I have, I get matplotlib 3.0.2-2 with hy 0.12.1-2.

Replies from: Zack_M_Davis, lsusr
comment by Zack_M_Davis · 2021-09-25T01:54:26.951Z · LW(p) · GW(p)

no clue what package I'd have to install to get pip - neither pip nor pip3 exist

On Ubuntu, at least, there's a python3-pip package, separately from the python3 package? (Other distros may be similar.) It's also supposed to be possible to install pip using Python itself.

comment by lsusr · 2021-09-25T00:57:05.918Z · LW(p) · GW(p)

Here is a workaround.

  1. cd into the project directory
  2. Run the python3 interpreter
  3. In the python3 interpretor, call import hy
  4. In the python3 interpretor, call import main
Replies from: __nobody
comment by __nobody · 2021-09-25T01:05:05.567Z · LW(p) · GW(p)

That just gets me an even longer error message:

Python 3.7.3 (default, Jan 22 2021, 20:04:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hy
>>> import main
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/hy/macros.py", line 238, in reader_macroexpand
    reader_macro = _hy_reader[None][char]
KeyError: '*'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 668, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 638, in _load_backward_compatible
  File "/usr/lib/python3/dist-packages/hy/importer.py", line 197, in load_module
    self.path)
[...(*snip*)...]
  File "/usr/lib/python3/dist-packages/hy/compiler.py", line 424, in compile_atom
    ret = _compile_table[atom_type](self, atom)
  File "/usr/lib/python3/dist-packages/hy/compiler.py", line 365, in checker
    return fn(self, expression)
  File "/usr/lib/python3/dist-packages/hy/compiler.py", line 2559, in compile_dispatch_reader_macro
    expr = reader_macroexpand(str_char, expression.pop(0), self)
  File "/usr/lib/python3/dist-packages/hy/macros.py", line 242, in reader_macroexpand
    "`{0}' is not a defined reader macro.".format(char)
hy.errors.HyTypeError:   File "/home/nobody/projects/darwin/main.hy", line 63, column 1
[and then as before]

Guess I'll try setting things up on another system tomorrow, or else I'll skip.

Replies from: lsusr
comment by lsusr · 2021-09-25T01:38:55.413Z · LW(p) · GW(p)

The import main workaround did solve the error for someone else. In case it helps, I'm using Python 3.8.10 with the following two libraries installed via pip3.

hy==0.20.0
matplotlib=3.4.2
Replies from: __nobody
comment by __nobody · 2021-09-25T01:47:00.724Z · LW(p) · GW(p)

Thanks!

Turns out it needs a newer hy, then it works. (And in case anyone else has a similar problem and is also a Python noob, pip's package is probably called python3-pip or something like that. After that, the rest is explained either in the article or by pip itself.)

comment by Rochambeau · 2021-09-24T23:34:33.892Z · LW(p) · GW(p)

Someone please correct me if my interpretation of food and reproduction are incorrect as my programing experience is limited.

I see the energy being reduced by 20%, but what is the threshold for death? 

The number of offspring is determined by rolling a number between 0 and 1 rolled 10 * creature energy times, and for each random number  less than 1 / (body size x 10), a baby is created with the same energy as the original creature and no impact on the original creature?

I think I am missing where predator efficiency is accounted for. 

In line 163/164: 

          (reproduce (. [organism-0 organism-1] [fight-flight-result]

                    (energy-of (. [organism-1 organism-1] [fight-flight-result])

does this mean reproduction of organism-1 and organism-0 is only dependent on the body size of organism-1?  no impact of stored energy?

Replies from: lsusr, aphyer
comment by lsusr · 2021-09-25T00:05:14.226Z · LW(p) · GW(p)

The code you're looking at has a bug. I fixed the bug. Here is the new code.

(reproduce (. [organism-0 organism-1] [fight-flight-result])
              (* +predatory-efficiency+
                  (energy-of (. [organism-1 organism-0]
                                [fight-flight-result]))))
comment by aphyer · 2021-09-24T23:47:45.679Z · LW(p) · GW(p)

Not a Lisp expert, people can correct me if I am wrong, but:

Death is the default.  If 'reproduce' is not called for an organism, it will not exist next iteration.  If one organism kills the other, 'reproduce' is called only for the winner - if they both eat plants, 'reproduce' is called for both.

Predator efficiency seems as of this writing to be in lines 163/4 with the code you quoted, might have been added as a bug fix more recently?

What's happening in the code you see if that the winner of the fight is being given as the first arg to the reproduce function (the animal that will reproduce), while the size (energy) of the loser is being given as the second arg.  The size of the winner will be taken into account in the reproduce function.

Replies from: lsusr, Rochambeau
comment by lsusr · 2021-09-25T00:02:41.135Z · LW(p) · GW(p)

This is correct. No organism ever survives a round. It must replace itself with a baby. An organism/species with no babies dies out instantly.

comment by Rochambeau · 2021-09-25T00:18:11.294Z · LW(p) · GW(p)

Thanks for the explanation.

comment by elspood · 2021-09-24T22:32:30.937Z · LW(p) · GW(p)

Can you elaborate on the winning condition? I expect most biomes will have surviving species; will that mean multiple winners, or will the ultimate winner be the species with the most total biomass? How long will the simulation be run? I can imagine stable equilibrium conditions with multiple survivors, even after an arbitrarily large number of simulation rounds.

Replies from: lsusr
comment by lsusr · 2021-09-24T22:40:17.249Z · LW(p) · GW(p)

Everyone who survives counts as a winner. If you enter multiple species then you can win multiple times. This is a non-zero-sum game. I may rank them according to average population.

The simulation will be run until I feel like it has hit an equilibrium.

I encourage you to enter one or more species even if you don't think it'll win. More biodiversity makes for a more interesting experience.

It is possible there will be no winners.

comment by aphyer · 2021-09-24T20:36:14.806Z · LW(p) · GW(p)

To give housecats a chance we need something else to prey on koalas that also provides food for housecats.

 

I might be misunderstanding something here in the rules.  How do mongooses (mongeese?) provide food for housecats?  By my understanding of the rules both have Weapons 1 and neither has Venom, so no predator-prey relationship exists at all?  Am I missing something?

Replies from: lsusr
comment by lsusr · 2021-09-24T20:57:09.046Z · LW(p) · GW(p)

You're right. Mongeese don't prey on housecats. That was a mistake. I have removed it from the post.

comment by [deleted] · 2021-09-25T18:28:20.943Z · LW(p) · GW(p)Replies from: lsusr
comment by lsusr · 2021-09-25T20:23:38.426Z · LW(p) · GW(p)

That would be nice. Alas, implementing a web interface would (with my set of skills) double (or more) the amount of work this project takes.

Replies from: None
comment by [deleted] · 2021-09-26T05:11:06.302Z · LW(p) · GW(p)