Liza Shulyayeva

Migrating to Laravel 5

A few days ago I decided that there’s no use putting it off any longer - it’s time to upgrade to Laravel 5. I’ve been sitting on 4.2 for months and 5 is a major revision to…well…everything.

I knew this would be a large setback in terms of feature work. The migration would break things, things that would make me wish I’d never done it at all. In addition the plugins I’d been using for 4.2 would no longer be compatible with 5 (in fact, I don’t think any of them are…)

I was using:

  • Confide for user authentication
  • Dispatcher for scheduled commands
  • Latchet for a Laravel-specific implementation of Ratchet.

The first two I just got rid of completely, using Laravel 5’s authentication features and new command scheduling feature that does exactly what Dispatcher used to for me.

The last one I haven’t even started on yet. It’s going to be the toughest.

The most “breaking” update in Laravel 5 has been namespaces. I’ve been sitting here adding namespace declaration to all of my files. It’s time consuming, but better in the long run and actually pretty relaxing. If this is the biggest problem I’ll run into during this migration I’ll be happy (Latchet aside, of course).

Anyway, within the next couple of days I hope to have the migration complete and functional. Then it’s back to substrate and brains!

Thinking Through Substrate

After checking in the basic substrate item implementation yesterday I got to thinking - never a good sign.

The original idea was to have some pre-set types of substrate - garden dirt, rock, potting soil, pellets, whatever. But how would these items affect the snails and the jar? Would I need to invent some sort of set of attribute templates? Like “Oh well this garden dirt item is going to decrease jar temperature by 1C.” and “Oh well some snails somehow don’t like gardend dirt and prefer other substrates”. But why? Why would a snail prefer one template to another and how would this be decided?

Considering I’m already going for a lot of detail with consumables (making sure consumable items have macro and vitamin attributes based on their real life counterparts), I should maybe do the same thing for substrate. For example, garden dirt isn’t just garden dirt…it can contain varying amounts of clay, humus, sand, rock, etc. An item called “Garden Dirt” would really be made up of multiple base elements in varying proportions. And that led me to thinking - while a template called “Garden Dirt” should exist and be available for pre-mixed purchase from the Habitat store, users should also be able to mix these elements themselves. As a user I want to buy my own sand, clay, rocks, whatever, and experiment with proportions of each to create substrates of different moisture, porosity, pH level, etc.

I don’t know exactly how this is going to work yet - in fact from this point on I’m kind of making this up as I type. But here’s a quick overview of how consumable items already work.

The database has the following item-related tables (with the specified columns):

  • item_types
    • typeID
    • name
  • item_templates
    • templateID
    • typeID
    • luminance
    • temperature
    • roughness
    • description
    • enduranceMod
    • speedMod
    • aggressionMod
    • modDurationMins
    • weightG
    • bites
    • baseDaysToRot
    • imageName
    • imageSubdir
    • rarity
    • basePrice
    • priorityLayer
    • pingsJar
    • isApplied
  • item_nutrition
    • templateID
    • carbohydrates
    • sugar
    • fat
    • protein
    • vitA
    • vitC
    • vitD
    • vitB6
    • vitB12
    • calcium
    • iron
    • magnesium
  • items
    • itemID
    • templateID
    • ownerID
    • jarID
    • deleted
    • bitesTaken
    • posX
    • posY

I suspect that I will need another table on the same “level” as item_nutrition. Something like item_terrain_elements…or something. It would contain the following columns (or something like this):

  • item_terrain_elements
    • templateID
    • pH
    • porosity
    • carbon (primary nutrient)
    • hydrogen (primary nutrient)
    • oxygen (primary nutrient)
    • nitrogen (primary macronutrient)
    • phosphorus (primary macronutrient)
    • potassium (primary macronutrient)
    • calcium (primary macronutrient)
    • magnesium (primary macronutrient)
    • sulfur (primary macronutrient)
    • iron (primary micronutrient)
    • manganese (primary micronutrient)
    • boron (primary micronutrient)
    • copper (primary micronutrient)
    • zinc (primary micronutrient)
    • molybdenum (primary micronutrient)
    • chloride (primary micronutrient)
    • nickel (primary micronutrient)
    • iodine (other)
    • fluorine (other)
    • selenium (other)
    • cobalt (other)
    • arsenic (other)
    • lithium (other)
    • chromium (other)
    • silicon (other)
    • tin (other)
    • vanadium (other)

The primary nutrients would affect plant growth and the “other” nutrients could affect the animals (ie snails) within the jar.

And looking at the above just now, I don’t see a reason not to just add the above nutrients to the item_nutrition table. Some of the columns (eg magnesium) would already be duplicates anyway…I could maybe just add the above columns to the nutrition table and set anything irrelevant to ‘0’…would there be something wrong with this? I don’t know, I have to think.

Jar Substrate Is a Go

It’s finally in. Well, the beginning stages anyway. Jar substrate. Anyone who knows anything about snails knows that they can’t live in a glass box without some sort of substrate to hide in, get moisture from, and burrow under. So now you can apply one type of substrate (so far) to a jar. Eventually there will be different kinds of substrate, and maybe even substrate you can mix together from other types of substrate. Currently the substrate has no effect on the snails or the environment outside of being present and visually represented, but eventually it can impact everything from snail nutrients to jar temperature and what kinds of plants you can grow inside the jar. Here’s how it works.

I added a new column to the item_templates table:isApplied. If an item template has this set to true it means that you apply it to a jar instead of placing it into the jar as a moveable item (like a potato, for example). Once you place substrate in you cannot drag it around, you can only remove it.

The substrate item has a terrain item type in the item_types table. There are different actions available from the user’s closet based on item type and sometimes template:

    protected function getAvailableActionsAttribute() {
        $possibleActions = [];
        switch ($this->template->type->name) {
            case 'consumable':
                array_push($possibleActions, array('text' => 'Put in Jar', 'onclick' => "return showPutInJarForm($this->itemID)"));
            case 'decorative':
                array_push($possibleActions, array('text' => 'Put in Jar', 'onclick' => "return showPutInJarForm($this->itemID)"));
            case 'substrate':
                array_push($possibleActions, array('text' => 'Put in Jar', 'onclick' => "return showPutInJarForm($this->itemID)"));
            case 'jar':
                array_push($possibleActions, array('text' => 'Install Jar', 'onclick' => "return showInstallJarForm($this->itemID)"));
            case 'breeding':
                if(strpos($this->template->name,'Fertility Spray') !== false) {
                    array_push($possibleActions, array('text' => 'Spray', 'onclick' => "return showPutInJarForm($this->itemID)"));
            case 'training':
                array_push($possibleActions, array('text' => 'Put in Jar', 'onclick' => "return showPutInJarForm($this->itemID)"));
            case 'terrain':
                array_push($possibleActions, array('text' => 'Apply to Jar', 'onclick' => "return showPutInJarForm($this->itemID)"));
        return $possibleActions;

So if the item type is ‘terrain’ the action text that appears is “Apply to Jar” vs “Put in Jar”. It could call a different function when clicked as well, but in this case we handle the application step in the same function as the putting-in step so we show the same form.

So a user goes to their closet, scrolls to the Garden Dirt item, clicks “Apply to Jar”, and selects which jar to apply the item to.

Then we update the item as we usually would by placing it inside the jar, except we only assign the item a position if !$item->isApplied. At the end we run any special actions the item may have (which in this case it does) via item->runSpecialActions():

case 'terrain':
    $jarController = new JarController();
    $jar = $jarController->findJar($this->jarID);
    $jar->terrainItemID = $this->itemID;
    $propertiesToUpdate = [
        'terrainItemID' => $this->itemID

So the terrain gets applied. The item is not deleted until the substrate is thrown away. And if a jar has a terrain applied we draw the terrain tiles in the background:

Jar with substrate

Of course the next step is to have the substrate actually have some sort of effect. Snails housed in a jar without substrate should be affected by the lack of proper environment. Unfortunately right now I do not yet have snail health implemented. That is, snails can die of lack of energy via starvation, but they also need to be able to get ill from environmental and genetic factors and then die that way, too. The terrain will be just one of many things that should affect a snail’s overall health and performance.

The Month From Hell

Note: Veterinarian clinic/hospital names in this post have been changed. If you know the vets in Stockholm you may be able to easily get an idea of which places I’m talking about, and if you want some clarification you can message me in private. I wasn’t sure if it was right to include real names here.

This is Rigel on his trip home to us from his breeders in Norrköping. He was 3 months old and the nicest of cats. He slept quietly through the long train ride to Stockholm. When we got home he walked out of his carrier, sniffed around, and claimed the house - and us - as his own.

Here I am channeling Overly Attached Girlfriend on his first day home:

Rigel was the most amazing kitten. He’d follow us around everywhere, do flop-downs and chirp at us; he talked to us, developed his own quirky habits and personality. He was one of the best things that’s ever happened to me.

On February 12, at a bit over 6 months of age, Rigel had his neutering surgery. He was born with a condition called “cryptorchidism”, which meant that his testicles hadn’t descended. This didn’t cause him any health problems, but it did mean that the neutering surgery would be a little more involved - it would more closely resemble spaying a female because the surgeon would have to go into the abdomen to retrieve the testicles. Nevertheless, it’s meant to be very safe and routine. We took him to a clinic a little north of T-Centralen that we heard great things about (even though we live South of the city), “DA”. I was worried as you would be with any surgery, but this is done all the time and we heard good things about them.

DA actually did an ultrasound before the surgery to find Rigel’s testicles in his abdomen (instead of having to dig around in there looking for them during the surgery itself). I hung around the area for a few hours during the procedure, waiting for the call that he was ready to go home.

When I finally came to pick him up the veterinarian wanted to talk to me. She said the surgery went well, everything was fine, but they did notice one thing during the operation - he had what they thought was a very big bladder that was also more elongated than a “normal” bladder would be. They thought there may be some blockage or infection so they passed in a catheter to check for both. They drained the urine with a catheter, found no blockage, and no infection. They said the bladder contracted nicely after being drained. So he was good to go! I thanked her and brought Rigel home, excited to have him start his post-op recovery.

Unfortunately on February 14th we noticed that Rigel wasn’t peeing. He kept straining to go to the litter box, but nothing was coming out. We read that after an operation the cat’s urination and pooping habits might be a bit wonky, but this was worrying - he just couldn’t seem to pee.

We took him back to DA, where they I think passed in another catheter to drain the urine and again tested for infection. Unlike the test during the surgery, they now found bacteria. They sent him home with antibiotics.

The next day he still did not pee. We rushed him back to DA. They said that at this point they should put in a catheter and keep him overnight. However, DA do not have staff on-site 24/7 and said they would understand if we wanted to go to a larger hospital who did. They recommended Baker, a big hospital about 5km from our house. We took a taxi there instead.

During the consultation Rigel was trying to pee and got a few drops of bloody urine out. At this point we were starting to put two and two together and the veterinarian diplomatically confirmed - judging by the fact that Rigel was totally fine and had no problems peeing before the surgery, that the first catheter passed in during the surgery found no bacteria and two days later there was suddenly an infection, it seems that DA introduced a urinary infection while testing for a urinary infection. We were devastated - here we had a perfectly healthy kitten who went in for a routine surgery, had a catheter stuck in him (unrelated to the actual surgery) because they thought his bladder looked big, and was now in this mess. Thank god…or whoever…we had insurance.

Rigel stayed at Baker for I think two nights with a catheter (though I’d have to check the journal to know for sure). Finally they called us and said he peed on his own and that he can come home! We were ecstatic - our kitten was ok again!

So we took him home. Except he still didn’t pee on his own. And this time he wasn’t even trying. At first I thought maybe that’s a good sign…maybe his bladder just hadn’t filled enough? If he didn’t need to pee that’s good, right?! When he hadn’t peed in 24 hours we took him back again. They drained 400ml of urine. Did they send him home with an already filling bladder?! And now there was talk of atony and distension. This is where “distended bladder” starts showing up in the journal, and nerve damage. It wasn’t good that he didn’t feel the need to pee after all - it was a sign that his bladder was now damaged to the point of him not being able to feel the need to go. The infection may be gone, but now we are on to a whole new problem.

They kept him again. We visited him every day. They put him on new meds and put in a catheter.

A few days later they called us saying he ripped out his catheter, but we should take him home because the new meds seem promising. We take him home. At this point our nerves are shot and we have no idea what’s going on. We just want him to get better.

Rigel has been to the hospital so much now that we have a routine. I bring him in. They take him to an individual waiting room after the main waiting room. I take off my jacket and spread it out on a chair for him. He curls up there and has a nap.

He tries to pee and can’t (but at least he tries now). We rush him back. This is a nightmare. I notice the penis looks a bit swollen and ask someone if it’s possible that there is now a blockage or injury or scarring or SOMETHING there after he ripped out his catheter. They say it looks a little swollen but that’s normal after the catheters. They suspect the problem is the bladder, not the urethra - but then why is he trying to pee? Clearly he can feel his bladder still! We are very confused, but the vets are saying he’s been checked for blockage several times and there has been none. Ok, fine..but he hasn’t been checked since he last ripped out his catheter, right? Baker has also been hoping that letting his bladder get full will encourage him to pee, so they suggested waiting 2, maybe up to 3 days at a time before emptying it. His bladder is naturally big and by this time it was so stretched that it wasn’t going “hard” from fullness in even that time. But it didn’t help. They start talking about putting him to sleep, about us soon running out of options. His insurance is running out, but we reiterate that we don’t care how much it costs - I’ll pay for the treatment without insurance. Rigel was registered to me and Kaytu was officially David’s, so Rigel’s costs were on me. He started off as a perfectly healthy young kitten and now he is going through this mess because someone decided to stick a catheter in him because his bladder looked big.

Baker’s plan is to do a surgery to put in an abdominal catheter and send Rigel home with it for a week, hoping this will give his bladder a chance to rest and recover function. But I’m worried - if there IS some blockage in the urethra now how would an abdominal catheter help? Won’t we just be back at square one? At this point I don’t know who to trust anymore and we are contacting anyone we can who may be able to help. What’s more, little things keep going wrong - he keeps seeing a new vet each time, and none of them seem to know all the details even though they all know his “general” story. On our last visit there a nurse feels his bladder and says it feels small. We get excited! But then the vet checks the bladder and says it’s very large and needs to be drained again. What is going on?! One place keeps coming up from multiple sources - a big university hospital (“UH”) in Uppsala. This is a large univeristy animal hospital that’s meant to be the best.

We hold off on the surgery until Monday, take Rigel home for the weekend, and call the UH small animal hospital in Uppsala. We ask if we can bring Rigel for a second opinion tomorrow and they say yes. It’s two hours away by public transport but a very kind friend of ours takes the time to drive Rigel and me there on a Sunday. He is inspected and stays there, to hopefully see an internal medicine specialist the next day.

We are cautiously optimistic - we’re told this place is the best. If anyone can fix him they can.

He stays there for…I think a week? Two? Time is now blurring together. They put him on new medication, but he is not trying to pee. This is devastating, because just the day before we brought him in he was trying but unable to go and now they say he’s not going at all!

I visit him throughout this time, catching trains to Uppsala after work. The vets are surprised that he still seems to be in such good spirits through all this - all the pills, the procedures. He has to be sedated daily to have his bladder drained with a needle, and yet he’s still active, playing, and “doesn’t even know he’s sick”. One time I visit and the nurse spends 30 minutes explaining to me how serious his situation is, how they are running out of options, and how there may be nothing we can do because the situation is so serious. Thank you very much. We did not know how serious his situation is. We just happened to stumble into what’s meant to be the best animal hospital hours from home for the heck of it. I came home and cried all night, expecting that the next day I’d get a call from the vet saying they were done.

But the next day I do get a call, and they decide to do a bladder biopsy - surgery #2 after neutering. At the same time they check for blockage by trying to pass a catheter in from the bladder out - no go. Then from the bladder in - very difficult. And finally from the bladder out again. This indicates a potential stricture. I wonder how long it’s been there?! Maybe all that time he’s been trying and unable to pee at Baker he’s actually had a stricture?

The biopsy results themselves apparently don’t show any very useful information, but after finding the stricture (and after he rips out yet another catheter), and after my potentially dumb insistence that we can’t give up now, they decide to do a Perineal Urethrostomy. Rigel has been through a lot and I didn’t want him to suffer by putting him through more procedures that he could handle, but the vets themselves in their daily updates have said that he remains a happy and active cat who is not suffering. The Perineal Urethrostomy is a big surgery that basically amputates part of the penis to remove the thinnest point with the stricture, making the genitals look more like that of a female cat. They don’t know if this will save him - they just know it may alleviate ONE of the problems. The other is his atonic and distended bladder.

It doesn’t seem to help. He yet again rips out a catheter. They wait for a few days, giving him a few hours to feel the need to pee between catheter drainings, but he just does not go. Finally they say that it’s time. They say there is nothing more they can try - the meds just don’t seem to be working, and neither did the surgery. At this point David is in Japan for work and I’m alone at home (well, not alone - our other kitten is there). I ask if it’s ok for them to drain Rigel’s bladder one last time that night so that I can come pick him up and have him spend his last day at home with his family. They say yes, but only under the condition that if he doesn’t try to pee within 24 hours he be put to sleep. I know he can go longer - Baker had waited for days at a time, but they are insistent.

At this point I have a week off of work. I had originally booked it to go away with David, but now of course I’m not going anywhere. I make arrangements and set an appointment with a veterinarian to come to our house and put him to sleep at 4:30pm on Thursday, March 12. As a last ditch effort, desperate, I look for any other veterinarians who might be able to help. Plenty of people live with handicapped pets who can’t pee on their own - they can express their bladder manually 3 times a day and the pets live happy and long lives, and sometimes bladder function even recovers. But nobody’s been able to express Rigel even after the stricture was removed and I find it difficult to understand why.

I find the website of a holistic vet Wednesday morning and email her out of desperation. It just so happens that she lives near the UH hospital and is kind enough to invite us to her house on our way home. I hate the thought of dragging him elsewhere on his last night, but it’s close and I can’t give up now. We go there. He likes her, but he is so tired and uncomfortable after all of the procedures he’s been through. The holistic vet performs acupuncture, which Rigel tolerates well at the time. We go home.

I think about how his last trip with me is on same kind of train that we took when I was bringing him home, just going from the opposite direction, in exactly the same carrier.

On the train we sit next to a kind lady who asks me questions about him and asks if she can pet him in the carrier. I say yes and she reaches in. She ends up getting off at our stop and saying that she “did some healing”. I thank her - he can use all the healing he can get. I explain to her that I’m bringing him home for his last day and she says “We’ll see what happens. It’s up to him now. Just take that cone off when you get home.”

The giant cone on his head is there so that he doesn’t lick his urethrostomy stitches and he hates it. When we get home I take it off and watch him like a hawk to stop him from licking. I spend all night awake, watching him and trying to accept that our kitten is going to die in less than 24 hours and at the same time hoping that some miracle might happen even though the vets say it can’t. Rigel is exhausted. I’m a nervous wreck. The kittens and I are locked in the bedroom with a litter box, toys, and water. I keep us all in the room so that I can stay awake and watch to make sure he’s not licking. He doesn’t mind - he’s not in the mood to play or roam anyway.

Rigel is exhausted. He tries to play with our other kitten, Kaytu, but tires quickly and sleeps.

The next morning he got up to drink some water. Then he started pacing. He’d grumble, pace, grumble, pace, lie down, eye the litter box, pace. I gently scruffed him with one hand and felt for the bladder with the other. I’m not sure if I was feeling the right spot, but I thought I felt it there, full and balloony. Shaking, I gently carried him to the litter box and dug my hand in the litter in front of him. I stepped away and waited. He sniffed around, circled slowly a few times, dug weakly, crouched, and PEED! He peed! By himself! For the first time in over a month!

I tried to get a non-blurry photo but was shaking so much it was impossible.

I was on the phone to UH immediately. I waited and waited and then excitedly told the receptionist that Rigel just peed and that I had to speak to one of the veterinarians who had treated him immediately. They told me to call them straight away if he even so much as tried to get any urine out. I wanted to make sure they knew he peed, and ask what to do next. We were only given a few days of medication and no post-urethrostomy-care instructions, I guess because they thought he wouldn’t need them. But here he was peeing, so maybe he still stood a chance!

I was told someone would call me back as soon as possible. No one called back. In the meantime I contacted the holistic vet, who was very helpful and also got a hold of relevant people at UH to let them know. They had threatened to call “the authorities” if they didn’t hear from me that he tried to pee OR from the vet who’d be putting him to sleep that it was done, so it was important for them to know.

That night I took him to Baker (which is less than 5km away) to check his bladder and make sure it wasn’t too full. They did a ultrasound and confirmed that the bladder was large, but for him at this point it may be a “normal” large. It wasn’t bursting and was still “wavy” instead of “hard”. I was told that if he goes once a day that is good enough. They represcribed some of his medication and said at this point all we can do is wait and see what happens because if he stops peeing there’s not really much they can do anyway, since they’ve already tried everything else. It was terrifying.

The next day I thought I’d made a terrible mistake. I felt Rigel’s bladder in the morning - sometimes he peed right after I palpated it gently, so I did and then picked him up to carry him to the litter box. He started convulsing in my arms. I put him down, terrified that his bladder had ruptured and he was dying. I was on the phone with the taxi, calling to take us to Baker to put him to sleep because I thought he was dying in pain in the house. I was afraid it would be too late. But then he vomited what smelled like the food we were given at Baker for me to give him with his medicine the previous night (the next dose was due while we were there, so they gave me a packet of Hills food to give him with it). Maybe the new food just didn’t agree with him…anyway, after vomiting he seemed better. I put him in the box gently and he peed again, then demanded food.

I again called UH, again to no response. I thought they’d be happy that he started peeing, but they seemed to want nothing to do with Rigel anymore. I’m not sure why…I wanted to thank them for everything they’ve done for him, for the surgery, etc, but I still haven’t heard back from them since.

And so it went on. As soon as it started to get dark I’d start counting the hours. It was the worst week of my life but I know it would have been a million times worse for Rigel himself. Sometimes Rigel would pee twice a day, and then suddenly he didn’t pee for 25 hours. It fluctuated wildly. The holistic vet came and looked at him last Sunday - she said he looked much better than when she first saw him and said that his bladder felt good.

We spent the days in the sunniest rooms, where the cats preferred to be. I’d spread out some blankets on the floor and watch him, and take quick naps when he did. We were both so tired.

Last Monday we had an appointment back at Baker to bring him in and see how to proceed. After all, we had no idea what the heck happened. His meds were running out within days and I had no idea where to go from here. We managed to get an appointment with the internal medicine specialist at Baker - the first time we’ve actually met one of these specialists in person. She was very nice, looked through his gigantic journal history, and represecribed the medications. She explained what she thought had happened, and also that the bladder, like any other organ, can be a highly individual thing. Just because it may look more elongated or larger than normal doesn’t mean you necessarily have to start poking around in there if no problems had been reported. They took a blood test and instructed me to get a urine sample to test for organ failure, infection, etc. She said he looked like a…normal cat. By that point he seems to have rested from the long and stressful hospital stay and was feeling more himself, playing, exploring.

At this point I’d been running on maybe 7 hours of sleep since the previous Wednesday and feeling loopy. I was dragging Rigel’s pee clumps around to the vet in case they were relevant, hadn’t had a hot meal in days, and all of my pants were now falling off of me. That afternoon the vet called with blood test results - kidneys were functioning well, he had slight anemia (she said normal after surgery) and potentially a sign of either some mild allergy OR a parasite. She said normally in this case they’d deworm the cat, but he’s already balancing so many medications that they didn’t want to risk it just then.

She also said to take him off of one of the meds - Stesolid (Valium). I was scared to make it worse, but I know he can’t be on these high dosages and medications forever, so we stopped with the Stesolid.

I managed to get a urine sample by holding a measuring cup under him a couple of mornings later. I brought it in to the hospital at about 5am. The specialist called us the next day saying there was no obvious sign of infection, the urine concentration and pH level looked good, and the one slightly concerning thing she saw was some bladder cells coming out in the urine. She says that also may be normal after surgery, but I need to submit another urine sample this upcoming Monday to recheck.

David also got home from his work trip Tuesday night, and made me my first warm meal in a week. He’s been helping to watch him while I’ve had to go back to work since.

The holistic vet looked through his UH journals and confirmed that the stitches they used for the urethrostomy were non-dissolving and need to be taken out in 10 days. That was day 10, so I made an appointment to have them looked at and potentially removed the next day (yesterday). It was much rougher than I thought! The vet just ripped off his scab down there with her hand - it started bleeding. Then bled some more while they were cutting the stitches around his urethral opening. I had read that one serious potential complication of the urethrostomy is tissue healing over the opening, creating yet another obstruction, and I was worried that continued damage to the area like this could make this worse! We were told he’d have to not lick that area for another 7 days at least until it healed, and even afterwards we’d have to watch him to make sure he’s not obsessively licking there (but he’s never been an obsessive licker, at least not until now). Rigel was so good throughout, though. I had to help hold him in the front while the nurse removed the stitches. He just wrapped a foreleg around my arm, buried his face in my sweater, and cried. The area there is tender now, but he’s peed twice since he got back…we are watching like hawks for any signs of him straining or having other trouble.

Rigel has become adept at removing his cone by himself. I ended up getting a harness from a pet store and tying the bandage-tie around his neck to that, so that he can’t pull it over his head.

When I come home now he bolts down the stairs to meet me - he used to meet me at the top of the stairs, but now he trots down to the door and looks up at me for scratches. It’s always so nice to see him.

I’m still so scared of something going wrong - bladder getting worse, stricture post-surgery, something. Nobody knows what’s going to happen. It’s been just over a week since the day he was meant to be put to sleep and he seems to be feeling much better and acting very playful and affectionate. He is still having some constipation but we’re managing that. But I’m afraid of getting too confident - things can go downhill at any time, and so many things have already gone wrong. But at least he’s still here now - still happy, relaxed, and (please knock all the wood in your house for this one) still peeing.

Tackling Gastropoda’s Memory Usage - Round One

I’ve been having to power cycle my Gastropoda Digital Ocean droplet every day lately because something was hogging up all the memory. It was a little annoying to diagnose because I know the problem had to do with the recurring events that are run using a cron job, of which there are quite a few. I know ideally PHP isn’t something you would use for a long running server process, but these jobs weren’t long running - they were just frequent.

The problem ended up being something very obvious. Every minute I run an event called CheckIdleSnailActions. It loops through all living snails in the world and sees what they’re doing. Unfortunately at some point that event began to take more than a minute to run. So when I ran ps aux --sort -rss to sort all running processes by memory usage I saw two instances of CheckIdleSnailActions running at the same time, one taking something like 60% memory and the other ~30%.

I always knew running these checks every minute would see me encounter issues like these and know I need to find a more efficient way of doing this. In the meantime, the first step was to avoid running these events in parallel.

To do this I ended up using lock files. The cron job runs a Dispatcher command called RunRecurringEvents. This command grabs all recurring events that are scheduled to run at this time from the database and runs them. These events include things like:

  • CheckIdleSnailActions
  • TickOrientationToNeutral
  • TickStressToNeutral
  • DepleteEnergyByTime
  • …etc

I created a new directory in app/storage called lockFiles.

I didn’t want to stop all of these things from running in parallel for now. The heaviest event by far is CheckIdleSnailActions. This is where we generate the brain, where the neurons do their work for each snail, where we comb through each snail’s memories for recognition of an object, retrieve and record mood impact, etc.

When each recurring event is triggered it runs only if there is no lock file matching the event’s name in app/storage/lockFiles. So if there is a file called app/storage/lockFiles/CheckIdleSnailActions.txt, the event will not run. If there is no lock file by this name it creates one and starts running, and when it finishes running it just deletes the lock file and allows the next instance of the event to run when it is triggered.

So far I haven’t had to power cycle the droplet since this went in. It’s not a full solution (I can’t even imagine how long it might take for one CheckIdleSnailActions event to run if the world ever has thousands of living snails in it), so this is a work in progress.

On Your Mark, Get Set, Crawl!

In my previous post I wrote about rethinking racing (aka ripping out the existing racing system).

Today I got most of the work done on that. There is a lot left to do, but as of right now:

  • A new jar gets created when a user hosts a race
  • When the race starts all entrants are placed into that jar in order of initiative, on the left end of the jar
  • An Attractor item is placed on the right end of the jar
  • The snails begin crawling toward the attractor item, their actions checked every minute just like in a normal jar. Snails can change direction and perform other actions live as this happens (and can be observed doing so)
  • As a snail touches the item its time is recorded and it is returned back to its parent jar in the owner’s stable
  • When all snails finish and are relocated back to their owners’ jars all items within the jar are deleted, and then the jar is deleted
  • The race is marked as “Finished” and results are displayed.

This has taught me that my way of estimating the snail’s position (between its last current position and target position) is nowhere near accurate enough. The snail that was coming in first visually actually finished 2 seconds after another snail in the race. I’ll need to work on this. Here are some screenshots:

Ready: Gastropoda race start

Go! Gastropoda race progress

Why did this snail turn around?! Gastropoda race turnaround

The last racer, straggling behind: Gastropoda last racer

Race results:

Gastropoda race results

Rethinking Racing. Also Cool Snail Art!

Racing in Gastorpoda has been implemented for months in its most basic state, but has never really gotten the attention it needs. So things like jars, in-jar positioning, and movement ended up evolving past the stage of the racing and making the current racing system kind of an outdated one.

Basically, right now racing is kind of simulating my simulation of jar movement. But really, I now have jar movement so I don’t need to try to simulate it when racing. All I really have to do is create a jar, put the entrants in it, place an Attractor item at the other end, and watch them go.

Right now in racing the snails’ steps are calculated based on time. So we basically loop through all the entrants until they’ve all either finished or dropped out and record their places as they come in. I would later be implementing stuff like snail interaction if two snails are side by side (one snail might try to bite the other, for example). But if I just make the whole race take place in an instance of a jar I don’t have to worry about any of those things. The snails will interact naturally.

This does mean that I’ll have to reimplement some attributes I used in current races to work in a jar context. Things like initiative (which dictates which snail starts moving faster), endurance (which, when depleted, causes a snail to be unable to move any farther and drop out). So it won’t be a simple plug-in-a-jar-and-done thing just yet. I’m also creating a virtual user, Mr Casinir, who will own all of these racing jars (since we don’t want any individual user hosting a race to have ownership, otherwise they’d be able to drag the snails and items around and ruin the race).

So I guess I’ll be ripping out the whole current racing system and doing this instead.

Also - check out the cool new iteration of the snail by Nicholas Lives, who kindly offered to team up for art for Gastropoda. This is just the first iteration of a new snail and I already like it a thousand times better than the ugly placeholders I’ve been living with for over a year now:

Gastropoda snail 1Gastropoda snail 2Gastropoda snail 3Gastropoda snail 4

You should also check out the game he’s working on, We Need to go Deeper.

Snail Brain Semi-stable and Reviewing Visual Traits Set During Breeding

The snail brain, while still very basic, seems somewhat stable now. By “stable” I mean a snail can survive and reproduce without human intervention if it has a steady supply of food.

When I first embarked on the journey to power my snails’ actions with a simple snail brain I threw together this diagram in the middle of the night:

Gastropoda snail brain draft 1

Now it looks a little more like this:

Gastropoda snail brain draft 1

Many things need to be refined and added on to. For example, right now a snail’s stress increases if it is claustrophobic. However, all snails tend to react aggressively to stress - I need to implement a fight or flight response. Snails either attack other snails or try to run away from the crowding. I alraedy have attributes like fear and aggression (based on stress), but so far aggression is the only one that actually affects the snail’s action.

I’m also starting to learn that I should trust the simulation a little bit more. In the past when something weird happend I knew it was most likely a bug of some sort. But now I’ve been running into more and more behaviours that, while odd, are in-line with what should actually be happening. I’ll use this breeding as an example.

Two of my snails - Baloo and Lemur - mated. Baloo ate all of the eggs except for one because he was feeling claustrophobic. Here’s what the remaining baby snail’s family tree looks like:

Lemurs Bagheera Family

However, as the baby grew and its shell color and pattern became more distinguishable I couldn’t help but wonder…how did a snail baby coming from two very colorful looking snails end up so…prune-colored. Remember that the snails are hermaphrodites. The gender symbols below only display the role each snail took on in that mating. Their orientation ticks back to neutral post-mating. A snail that mated as a female in one session could mate as a male in another (based on a few factors).

Lemurs Bagheera Family Tree

So I took a look at the parents. In this breeding Lemur bred as a male and Baloo bred as the female. Here are four of the visual traits (I’d say the major ones, although pattern radius also plays a big role) and how they came to be (the bolded pairs are the ones that actually got chosen for Lemur’s Bagheera as it was being conceived and the values on the right are the final color values and pattern shape chosen for the baby):

Lemurs Bagheera Visual Traits

And actually…it all kind of makes sense. I mean obviously I’m not going into the actual color-picking here (ie how you get a certain color value based on parents after a dominant allele is picked), but the general gist looks correct at first glance. I guess an ugly prune colored snail can legitimately come from colorful parents.

So out of curiosity I took a look at the dead babies. You can’t really see what they’d look like by eye since they died as eggs. But due to a bug that I’ve since fixed, they continued to hatch after death and just stayed at a scale of ~0.00001 (so almost invisible to the naked eye). I used Chrome dev tools to increase their scale to 0.5 and check out what they would’ve looked like:

Lemurs Bagheera littermates

So…all pretty ugly. Either this is as it should be or the actual color value calculations make the colors more and more muddy each generation. I wish it was that pretty green one that survived. But that is not a mess I want to wade into at 11:51 at night.

From Amazon Web Services to Digital Ocean

Amazon, I quit.

I tried, Amazon. I really did. For the last few months I tried to make it work with an EC2 instance for Gastropoda. I tried two main methods of deployment, both of which worked sporadically at various points:

  • Elastic Beanstalk. Main Problem: Alongside seemingly miscellaneous issues causing EB to terminate and re-spin-up EC2 instances, it would also spin up these new instances in wrong availability zones, causing instances to not be deployed in the right zone to utilize by reserved instance.
  • CodeDepoy. Main Problem: CodeDeploy was my preferred solution. It worked great. Push to GitHub and it would start a deployment. This was a bit more nitty-gritty to set up than Elastic Beanstalk, but also provided more control. However, one day my EC2 instance just couldn’t be connected to…by anything…

I ran into various problems with the EC2 instance itself regardless of deployment method. The last straw was my EC2 instance suddenly going down one day when nothing was being deployed or changed at all. Or rather, it said it was up, but nothing could connect. I tried a few different solutions and configurations, tried cloning the instance, setting up a new one, etc. Finally I got sick of it. I’ve heard great things about Digital Ocean from many sides, including the Laravel community. During this latest bout of EC2 problems @lauhakari and @niklasmodess recommended Digital Ocean again and finally I caved.

I set up a $5 droplet on DO and was fully operational by the next day. It still gives me plenty of flexibility and control, but somehow it’s just not as fiddly. I decided to try out for autodeployment. After a pain free setup everything seems good knocking all the wood.

“We want to help”

The funny thing is that the Amazon twitter account has a couple of times told me they want to “help” when I mentioned having EC2 problems on Twitter. They recommended I post my issue on the AWS forums. While the social media response is admirable, the offer of assistance rings hollow. I have made threads on the forums and have seen others make threads - usually after one fairly speedy response from Amazon, which tends to not solve much, further communication in the thread is dropped and no more support is extended. Usually you end up solving the problem yourself or it magically resolves itself a few weeks later (which is actually what happened in the case of the last thread I created about Amazon’s GitHub autodeployment instructions failing).

I should note that I am still using S3 for this blog. But as for EC2…I think I’m done.

Snail update

Gastropoda has been chugging along slowly but surely. I’m focusing on fixing bugs in the brain and the snails’ environment detection. I need to move on to racing functionality soon, but I don’t want to do that until I make sure that the main brain stuff is working as it should.

I have also added item rot. Some items (usually consumables) will rot and disappear from the jar if left in there too long. Some snails will later also be more picky about the kinds of food they eat based on its rot stage (keep in mind snails tend to actually prefer slightly rotten food).

One interesting bug I ran into recently was a weird error message about eggs not being able to hatch. They couldn’t find the jar they were meant to hatch into! After some digging it looks like the doe snail actually somehow died mid-mating, resulting in the eggs being laid in jar ‘0’ (basically the death or unassigned jar). Then when hatching the snail eggs were trying to get some jar attributes, but since it didn’t exist everything just failed miserably. I did have a check for this implemented on snail death (if a snail dies all of its unlaid eggs are meant to be deleted), but I guess there was some sort of timing issue there. I added a second check during actual hatching just in case.

It’s Not So Bad. We Have Snail Babies, After All

Sometimes I think about what I’ve been working on in my spare time since the beginning of last year and I’m like “What the crap, Liza. You’re spending your time trying to make toy slugs. Go learn a useful skill or something.”

The reason I keep getting drawn to simulations in the first place is the idea of virtual life, something with some sort of autonomy and - ok, I’ll say it - sentience. I know I won’t get to this point with my snails.

All aboard the robot train

JakeThompson: Karinario told me that he likes you…but don’t say that I told you ok?
Guest14361: Ok
JakeThompson: ok then….
Guest14361: Do you hate life?
JakeThompson: Can’t say that I do…
Guest14361: Mmk
JakeThompson: *hits computer* stupid thing.
Guest14361: Calm down
JakeThompson: But I don’t want to calm down
Guest14361: Do you hate me?
JakeThompson: Never! ure like the coolest person ive met so far
Guest14361: Awe thank you
JakeThompson: No prob.
Guest14361: I’m ugly
JakeThompson: Have you always been ugly?
Guest14361: yes
JakeThompson: Great…People say that I’m in denial….I wonder why that is…
Guest14361: People suck
JakeThompson: What’s your favorite food?
Guest14361: Pizza
JakeThompson: uh huh
Guest14361: What’s you’re fav food
JakeThompson: Figure it out yourself.
Guest14361: Pizza?
JakeThompson: Before you go any further, can you make sure that you’re actually making SENSE from now on?
Guest14361: You’re an asshole
JakeThompson: That was mean.
Guest14361: Bye!
JakeThompson: Bye.
Guest14361: Bye!
JakeThompson: Stop repeating yourself.

When I was a teenager in Alabama I spent a couple of years working on this chat bot on a site called Personality Forge. Thousands of keyphrases and responses later I had a bot who could fool a few unlucky people into believing that he was a person for a little while (mostly if they catered the conversation to his training in vulgar themes, which were among the more popular topics with passing human speakers) and managed to place something like 13th in a yearly chat bot contest called The Chatterbox Challenge. But just like with snails, the idea that drew me to wanting to make a chat bot in the first place wasn’t the thrill of having a program fake a conversation with a few hardcoded sayings. I guess I was excited about playing a game in which I simulated a truer simulation of life, AI twice removed.

I was trying to find out some old details about my bot on Google for this blog post and ran into this in my search - a snippet of a book in which he turns out to have been extremely briefly mentioned. It’s pretty cool to see your bot’s name in a book (I actually considered buying it because it sounds like a really interesting read, but it apparently costs >$170 on Amazon - what?!), but the context is actually kind of what I’m ranting about here:

“Examples of the ‘best’ chatbot answers to the remaining eight questions in the round assessing ‘regular’ conversational systems, as awarded with maximum 4 points by Shah as judge in CBC 2005, are shown below (the name of the system is left of their response):

Do you like me?
Jake Thompson: One hundred percent!”

-Creating Synthetic Emotions through Technological and Robotic Advancements by Jordi Vallverdú

After once again spending too long trying to remember my password to the Personality Forge, where the bot was made, I tried to dig up the response in his language center but could no longer find it - I must’ve made some change since the challenge. But here’s how he would respond to a question of “Do you love me?”, which would be pretty similar to how he’d have treated the above. You can see the original keyphrase affects his mood (asking the bot if he likes you will give him +1 to happiness and be treated as a high-importance phrase judging by the rank). In this case he wants the speaker to reveal their own feelings first and then answer based on this:

Do you like me?

The whole bot is this. Hardcoded keyphrases and responses with some wildcards thrown in and some rudimentary “mood” magic. I don’t know why most people make chat bots. Maybe the above generic response of “One hundred percent!” would be acceptable for some since it manages to not sound completely off-base in relation to the question, but when I saw my bot’s replies to The Chatterbox Challenge judges’ questions back in 2005, and the responses of bots who were much much more sophisticated than this, all I could really feel was disappointment. When you look back at the transcripts some may be amusing and it might be pretty cool when the bot manages to carry on some sort of conversation, but it’s so clear that it’s just a hunk of nothing underneath. At the time I wanted to make something more like ALICE, but even ALICE didn’t live up to the thing that made me like the idea of chat bots.

If I wanted to make a more “proper” chat bot it would have to be a learning bot. Learning bots back then to me sounded fascinating and still do. Maybe, maybe one day a chat bot capable of learning could surpass its programming, is what my wishful thinking is telling me. At one point I was interested in trying to make one of those, but then I got distracted by other things and eventually by snails.

Fake it till it makes it?

At Interzone Games I got to work with a lot of really smart people. One of them was Jason Hutchens, who created a chat bot called MegaHAL (and before that HeX, who won the Loebner Prize Contest in 1996). I remember right before I had actually accepted the job offer (or maybe soon after) the whole team went out for drinks and we talked briefly about the idea of strong AI and intelligence in relation to robots. That’s the first time I remember actually talking about this with anybody in person and it was interesting enough for me to still remember parts of the conversation despite the alcohol consumed that night. We talked about whether the definition of intelligence even matters - maybe if the bot is good enough to make people think it’s intelligent, that qualifies it as intelligent. Maybe that’s all you need. I mean, everyone I speak to in real life could be a robot, but I perceive them as intelligent, sentient beings because they manage to convince me. And that makes sense - if a bot can fool you into thinking it can think or is sentient or whatever it is that you hope it would be, maybe we should just accept that it is. But the real test is probably not a bot fooling some random external person interacting with it. I think the real test is the bot fooling its creator.

My Personality Forge chat bot could never have fooled me into thinking he’s intelligent or sentient (even if he could fool other people…which he also can’t). I know he’s just a collection of preset phrases. I can talk to him and often remember exactly when I put in a response and why (usually I’d peruse transcripts, find parts where he’d get stuck, and add responses to those parts as I went - that’s how his language expanded and became so questionably-themed). Even if I can’t remember adding a certain phrase now, years down the line, all I have to do is go into his language center and do a search. The other thing is lack of change. My bot has been a 16 year old “human boy” since 2003. He never changed or evolved into anything. Life changes. In a true life simulation, the subjects have to change somehow.

So the snails

I guess the snails were a way for me to try to go one step beyond a rudimentary chatbot. Snails are considerably lower on the totem pole than humans in terms of intelligence, but I figured that would allow me to build in much more perceived depth and realism by simulating a simpler system better. It’s not even artificial “intelligence” that I care so much about as opposed to artificial sentience. But just like with a chat bot, I don’t think these snails are ever going to surprise me or convince me they’re anything more than a bunch of hardcoded behaviours. It’s the same thing, really, just in a different format. There are a few positive enhancements, like:

  • Unlike the chat bot, my snails do change. They are born, experience their jars, form memories which influence their behaviour based on those experiences, and die.
  • They do sometimes do things even I don’t expect. But this tends to be a fluke - if I don’t expect something it’s probably a bug anyway and not an indicator of anything special or in any way truly autonomous.

So I have to make them better. I think the further I get with Gastropoda the less satisfied I become with the life side of things. Looking back it’s painfully obvious that all of the layers I’ve been adding - visual and behavioural attributes, genetics, now the brain - have been weak attempts to make my own creation be able to surprise me.

But hey - it’s not all hopeless. We have snail babies, after all.

Gastropoda tutorial