Liza Shulyayeva

Summer Holidays and Amsterdam

July is when Sweden goes on holidays. Businesses are closed for the summer (quite a few of them, anyway), people take time off work, the weather doesn’t suck. Usually people tend to go away to other countries, which to me is ludicrous because after all that snow and cold these months are finally when Sweden gets warm and sunny. I guess I’m kind of fibbing - I get it. You want to get out and see other places during your vacation.

So we went to Amsterdam for two days this month. It was great, but too short. On the last day we almost “forgot” that we had a plane to catch that night and considered maybe just “accidentally missing it”. It’d be an adventure, that’s for sure. But as the day went on I actually got excited about coming back home to Sweden. Amsterdam is great to visit, but there’s nothing there that makes me feel like I’d rather be there than in Stockholm. One big thing I did take away from it though was the desire to bike far more regularly instead of catching the train. I think since we got back we haven’t gotten on a train to Södermalm once, opting to cycle instead.

We didn’t take our laptops and put heavy restrictions on internet use. Mostly we just wanted to disconnect and relax. It worked, although I kept thinking about snails, taking notes, etc.

When we got to the Amsterdam airport we saw the TVs in an electronics store talking about a flight and showing disturbing footage. Through a store clerk who translated for us we learned that flight MH17 had just been shot down by terrorists in Ukraine after leaving that same airport that same evening. We were in shock for a while, with no idea of what was happening. I finally got to wifi to be able to read some English and Russian-language news. I hope that the terrorists - and anyone sponsoring them - are brought to justice.

Custom Validators in Laravel

I’m still going with the Laravel port. One thing I’ve found really interesting is custom validators. In Laravel models you can set field rules, such as…

public static $rules = array(
    'name'                => 'required|alpha_spaces|unique:jars',
    'ownerID'             => 'integer',
    'isBreedingJar'       => 'boolean',
    'capacity'            => 'integer|max:15',
    'comment'             => 'between:0,32|alpha_spaces',
);

In the vanilla PHP version I had to perform a check in updateSnail() - if the modified field was currentJarID, I had to find the number of snails inside a jar with that same ID and compare the jar’s capacity to the count of those snails. If capacity <= current snail count, the snail was not allowed to be placed into that jar.

With Laravel, I hacked together the same thing in the form of a new validation rule. This way I don’t have to explicitly perform this check whenever I move a snail myself - I just set the rule name in the rules array for the Snail model and it does the rest whenever it sees the snail’s currentJarID being modified.

I plan on changing this when I can see better ways of doing this. For now, setting it up like this seems to work:

1) Create app/validators.php

2) Extend Validator with your own rule

Validator::extend('limited_jar_space', function($attribute, $value, $parameters)
{
    $jarID = Input::get('currentJarID');

    $jarController = new JarController();
    $jar = $jarController->getJarDetails($jarID, 'capacity');
    
    $snailController = new SnailController();
    $snailCount = count($snailController->findSnailsInJar($jarID));

    if ($jar->capacity <= $snailCount) {
        return false;
    }
    return true;
});

3) Create a custom error message in lang/x/validation.php

"limited_jar_space"        => "The jar is full!",

4) Add app/validators.php to start/global.php

require app_path().'/validators.php';

5) So now I can use the rule "limited_jar_space" for currentJarID in the snail model to make sure the jar a user is trying to move their snail to has enough space left.

public static $rules = array(
    'name'                   => 'alpha_spaces|unique:snails',
    'ownerID'                => 'integer',
    'currentJarID'           => 'integer|limited_jar_space',
);

Experimenting With Laravel

I’m sitting here working on Gastropoda on a train to Norrköping. A couple of days ago I started experimenting with Laravel after the friendly folks on /r/php provided some invaluable input to my vanilla PHP vs framework question.

Laravel has been easy to set up. All in all getting Vagrant up and running and Laravel installed took maybe up to an hour. I’ve been trying to think of a good way to port my existing setup to an MVC-based framework. I’m basically going to paste a copy of what I posted on the laravel.io forum to explain the work ahead.

Basically, in the vanilla PHP version I have pages, main object classes, and manager object classes. Two examples:

  • snail.php
  • snail.class.php
  • snailmanager.class.php

  • jar.php
  • jar.class.php
  • jarmanager.class.php

I should note that snail data is not limited to being displayed on snail.php - snails are also instantiated and displayed on jar.php, for example.

Currently, in the no-framework version, I’ve been structuring every main object class (ie snail.class.php) in a way that ensures the class only contains methods that pertain to a specific instance of an object. So you’d never see a method like findSnailsByJarID() in snail.class.php because it would often return more than one snail. Instead, those sorts of things - methods that require pulling out multiple snails based on given requirements or trigger any sort of events on a set of snails/jars/whatever would go into snailmanager.class.php, jarmanager.class.php, etc.

An example of stuff in snail.class.php would be: updateSnail, loadSnailInfo, generateNewbornSnail, generateGeneString, depleteEnergy, etc.

An example of stuff in snailmanager.class.php would be: findSnailsByJarID, nightlyEnergyDepletion (which would call depleteEnergy for each relevant snail), etc.

The question

How should I split this up in an MVC pattern as pertaining to Laravel? Where should the logic pertaining to each instance of an object go? Some people have suggested putting everything into the controller, others in the model. Most seem to suggest not separating methods that affect one instance of an object from methods that perform actions on multiple objects (so there would be no separation such as the one I had with snail.class.php and snailmanager.class.php).

Anyway, while I do more research I’ve kind of been hacking it together with the expectation of later changing it as I learn. So the way I have it set up now for a jar is:

  • /models/Jar.php
  • /controllers/JarController.php
  • /views/stable/jar.php

The data I need to pass to the view is retrieved via a View Composer, which communicates with JarController, SnailController, and UserController to get information about a jar’s owner and all the snails within it. In a sense my controllers in Laravel kind of take on the role of the managers in the vanilla PHP version, except when data needs to change the view would never talk directly to the model but go through a relevant controller. The view also no longer decides anything (eg, whether to show the Edit form for a jar if the user viewing a jar is its owner). This is all done before, in the view composer, and from there the edit form is displayed if it is available.

Anyway, I am going to have to change how this works a likely stupid amount of time as I go.

The Beginnings of a Currency

When I moved back to the PHP version of Gastropoda I implemented snail death, so that snails actually die when their energy reaches 0. This resulted in all of my snails dying because they were both far below 0 (the cron job that depleted their energy daily continued to run while I was on a different branch).

So there’s currency now. Each user gets 500SEK when they start their stable. I’ve already used mine up on lettuce leaves from the other new thing - the Corner Store:

Gastropoda corner store

(Eh, obviously I need to still build grouping of listings of the same item/price combinations).

When I buy an item it ends up in my closet, which is accessible from my Stable page.

Gastropoda closet

From there you can choose what to do with the item (so far you can only place it in a jar). It ends up here:

Lettuce in jar

At which point snails can eat it to absorb the vitamins and nutrients from that item.

Now…lettuce leaves don’t contain much other than water, so unless I want to keep buying craploads of lettuce leaves on a daily basis to stick them in for the snails they are still going to die. Not to mention, I can’t stock up on lettuce leaves in advance because food is soon going to rot just as in real life if left too long. Snails can handle rotten food, but only to an extent.

Oh also the store restocks itself based on the rarity of each item template. Eh…very far from done, but here:

    function RestockStore() {
        $itemmanager = new ItemManager();
        // Loop through all item templates
        $qry = 'Select templateID, basePrice, rarity from item_templates';
        $result = DB::$mysqli->query($qry);
        if (!$result) {
            return false;
        }
        // Get each template as an array (to make into object later..this is separate from the Item object)
        while ($itemTemplate = $result->fetch_assoc()) {
            // Generate a random integer from 0 to 100
            $randomInteger = Utility::RandomInteger(0,100);
            // If the random integer is higher than the item's rarity (from 0-100)...
            if ($randomInteger > $itemTemplate['rarity']) {
                // Create one instance of that item 
                $item = $itemmanager->CreateNewItem($itemTemplate['templateID']);
                // Create a store listing
                $storeListing = new StoreListing();
                $storeListing->itemID = $item->itemID;
                $storeListing->sellerID = 0;
                $storeListing->price = $itemTemplate['basePrice'];
                $storeListing->SaveListing();
            }
        }
        return true;        
    }

This currently runs every 5 minutes, but I will make this less frequent when I’ve made it restock multiple instances of the same item.

Up next…

Next I will do a few days of bug fixing and cleaning everything up, then I’ll add a more substantial consumable (so that I can feed the snails only once a day for example), and then I need to start taking a look at snail growth. Currently babies are born at their adult size, but in reality they need to grow over the course of at least a few days.

To the Node and Back

I spent a couple of weeks porting Gastropoda from PHP to Node.js after caving in to peer pressure and hearing “PHP sucks” from every side imaginable.

And yes, I know - Why would you go from PHP to JS? Screw JS! Boo!

I like JavaScript. All of my hobby project save Time to Die have been made in JavaScript. And even JS doesn’t seem to be quite as hated as PHP (not anymore, anyway).

So I finished most of the port (from PHP and MySQL to Node and MongoDB). It was ok. I mean, it was pretty quick and aside from a few mild detours it went pretty smoothly.

But as I was maybe 3/4 of the way to having an exact replica of the functionality of the PHP version I reflected and realized that I just wasn’t having very much fun. Gastropoda is a hobby project - who the crap cares if I use the “worst language in the world” to build it? I’m doing my best to build it the right way (as much as there is a right way with PHP), but it will never be perfect. The Node version would have never been perfect, either. I’m not sure why I didn’t enjoy it as much. Maybe it had something to do with reimplementing all the features that I had already done just a few weeks ago. And refactoring the JS version as I learned better Node practices, implementing promises, etc. The weird thing is I don’t even mind revising the PHP version as I learn better ways of doing things. It was only boring when I was using Node, and I can’t really explain why.

It’s really just as I got Bluebird working for promises that I decided that the process of developing the same exact simulation with Node just wasn’t as fun for me as it had been this whole time in PHP. You could argue that maybe I’ve gotten too comfortable with PHP and Node just had more of a hump that I had to get over, that maybe I got lazy and went back to the “easier” option, but I don’t know if that’s the case. After all, the very first draft of Gastropoda, when I built it for One Game a Month last year, was built using Node and Mongo. All of my other projects were JS. That was before I’d written a single PHP project. Gastropoda is the first PHP hobby project I’ve ever done and while I don’t hate using it as much as many people seem to I’m certainly not comfortable with it in any sense of the word. There is always something new to learn…some weird quirk or best practice that has me rewriting tons of work. It’s just that for some reason with PHP I don’t really mind doing all that.

Anyway, instead of spending any more time on the port I switched back to the PHP branch and implemented snail death. I’m not against trying out ports to other languages, but I have a feeling in the end I’ll keep coming back to PHP for this particular project. In the future I’d love to dig into Go, and maybe play around with Rust. Just…probably not for this. Ever since I first thought of the idea of Gastropoda (before it ever had that name, or any name), I had imagined it in PHP - just like the games I played when we got our first computer and a dial-up connection after moving to the US. And maybe for a hobby project that nostalgia is reason enough to stick with “a fractal of bad design”.

A Move and a Quick Gastropoda Update

Moving

Buying an apartment in Sweden is refreshingly hassle-free but by no means stress-free. You find one you like online, you go to a viewing, you bid…and bid…and bid until you can’t bid no mo’. Alternatively, you find one you like online and just bid.

So we just moved in today. We only took some essentials with us, so here we are in a huge empty apartment. It’s nice - our goal is to not clutter it with crap. We’ll only buy the things that we actually need. For now that’s a bed. Maybe some chairs.

Moving out of the old place is going to be the most stressful part. There is all the packing and then the moving and then the cleaning. I wish I could just never go back to the old place again, but it’s not that easy. I’ll just focus on the fact that we have a porch now.

It still hasn’t really sunk in that I actually bought an apartment with someone (or at all). People have suggested that I buy back in Australia, but it never seemed like a good idea. It would just tie me down to a country that, while nice, I knew I didn’t want to stay in. I guess that went for more than just the place, too. On the other hand, Sweden feels much more like “home”, so the question of committment never crossed my mind.

Gastropoda

I have been battling it out with the nutrition system. Energy wasn’t being converted properly between calories/joules/carbs/fat/protein, resulting in some very annoying and difficult to diagnose behaviour. Snails with 200% energy and whatnot, snails whose energies didn’t deplete as much as they should in the daily event, etc.

That’s sorted out now. It’s now time to go back and review/clean up everything and make sure it’s all commented before working on any further features. I swear I’m going to forget what the crap I did unless I add some notes.

The Day of the Lettuce Leaf

Today I put the first item (a consumable lettuce leaf) into Gastropoda.

The items

The lettuce leaf was to be the first food item in Gastropoda. However, before I could make the leaf itself I had to make the food system, which I hadn’t yet planned out in great detail. Four new tables were involved:

  • items
  • item_templates
  • item_types
  • item_nutrition

item_templates is the main one, where every possible item is going to be stored. items is the one that actually records each instance of each item currently owned by a user in the world. item_types defines what kind of item a certain entry in the template is (eg “consumable”, “decorative”, “substrate”, etc). item_nutrition is exclusively used for items of the consumable type (which is why I separated it out into a separate table; it’s not going to be relevant for every item template).

So I created a template for the Lettuce Leaf in item_templates:

Lettuce Leaf item template

Then, I looked up the nutritional information of a lettuce leaf and added an entry for it in the item_nutrition table:

Lettuce Leaf nutrition

The energy here is in Joules and the rest of the measurements are in milligrams.

Next, I created an actual lettuce leaf item in the items table, listing my user as the owner:

Lettuce Leaf item

I put it into jar #2, where all of my snails are currently housed.

There is now also an Item class.

The snail stuff

I had to add a few new attributes to the snails:

  • carbohydratesCurrent (in milligrams)
  • carbohydratesIdealPercentage (of total energy)
  • fatCurrent (in mg)
  • fatIdealPercentage (of total energy)
  • proteinCurrent (in mg)
  • proteinIdealPercentage (of total energy)
  • vitCCurrent (mg)
  • vitCIdealPercentage (of current body weight; overall growth)
  • vitDCurrent (mg)
  • vitDIdealPercentage (of current body weight; calcium absorption)
  • vitB6Current (mg)
  • vitB6IdealPercentage (of current body weight; brain development, metabolism)
  • vitB12Current (mg)
  • vitB12IdealPercentage (of current body weight; blood and energy)
  • calciumCurrent (mg)
  • calciumIdealPercentage (body weight; shell growth/shell strength)
  • ironCurrent (mg)
  • ironIdealPercentage (body weight; none. Requirement is 0; toxic unless in tiny doses)
  • magnesiumCurrent (mg)
  • magnesiumIdealPercentage (body weight; calcium absorption)

I read whatever snail nutrition research papers I could find, but there wasn’t that much about their vitamin requirements so at the moment these are largely based on human RDIs modified for snail weights (with some randomization).

This does mean that I’ll have to update the way I do energy depletion. I have to find out how quickly vitamins are metabolized, and decrease energy by burning down carbs, fat, and protein at appropriate rates.

Item consumed

The other stuff

As I mentioned previously, you can’t really feed a snail individually unless it’s in its own jar (or you’re injecting it, which is a bit extreme). So you place food inside a jar and then any snail in that jar has a chance of taking a bite. Right now it’s random, but there are already some attributes in place which, when hooked up, will increase or decrease the likelihood that the snail will try to eat food - and also that it’ll actually get it when competing with the other snails.

The issue right now is that even though you can see the snails crawling around live on the canvas, and the food when it’s there, you do not see snail actions in real time (yet). So you won’t actually see the snail crawl up to the lettuce to eat it - it’ll all be done in the background and you’ll just see a new event on your snail when it’s consumed something. It’s kind of unsatisfying, since if you’re seeing them crawling around you feel like you should be able to see them also performing various actions. I’ll have to work on this down the line.

Lettuce Leaf in a jar (Obviously it’s not being properly positioned yet…)

So basically a snail takes a bite of the lettuce leaf and its nutritional stats are updated based on the item it’s consumed. These will then be used to calculate deficiencies and other effects that the snail’s diet has on its health and performance.

When the lettuce leaf has no bites left, it’s simply deleted.

So that’s the gist of it!

Taking It Easy on the Snailing With Some Lazy Layout Work

I’m too sleepy to do any proper work on Gastropoda today. I was hoping to implement the first food item, but yeah…that’s not happening. This morning I decided to head to the office early to get some work done on a largeish task while I had some distraction-free time. I did get a lot done, but waking up at 4am also meant that I was completely beat by about 1. Now I’m in bed, half asleep, wishing someone would bring me some cheese.

Anyway, so instead of working on the rough draft of the feeding implementation I decided to take it easy and mess around with the site layout. I’m pretty sick of looking at completely unformatted HTML pages, but I also don’t want to start fancifying it too much. So I noodled around and ended up with this:

Gastropoda - rough layout

And that’s it. It’s bed time. Tomorrow I’ll try to get to the feeding and the proper daily energy consumption reporting (right now the event log only reports how much energy the snail lost as part of its daily Resting Metabolic Rate consumption, but the snail also loses energy every time it races, so the daily amount should take into account all energy-draining events).

Recording Snail History Logs

I’ve decided that it’s about time to start recording event histories for snails. I keep going back to the database and checking which event ran on which snail by IDs and such and it’s getting to be a hassle. I’d rather just be able to go to the snail’s profile page and see all the important stuff that’s happened to it. Since this was always meant to be a feature anyway, I figured I may as well do it now.

I’m still not sure if I’m doing it in the dumbest way possible, but here’s how I set it up.

The tables

I added two new tables to the database:

  • snail_history_templates
  • snail_history_logs

snail_history_templates

The structure of this table is as follows:

Gastropoda - snail history templates table structure

The purpose of the table is to have a number of pre-set templates for events to follow. So far I have 4 templates defined, but eventually there will be much more.

Gastropoda - snail history templates table

You’ll see above that some of the templates use punctuation in them…these are meant to be replaced with relevant information when the log is actually pulled out for display:

  • ”@” is replaced with the snail’s name.
  • ”*” is replaced with the name of the target object.
  • ”#” is replaced with the numerical value specified in the event log.

snail_history_logs

So far the snail_history_logs table is structured like this:

Gastropoda - snail history logs table structure

Here is what’s been recorded in this table so far. I think I will end up adding a field for what kind of object is being referenced as the targetObjectID (after all, it should be able to be a snail, user, item, etc).

Gastropoda - snail history logs table

And here is what it looks like when you go to a snail’s profile page (I’ll have to reverse the table to show most recent events first):

Gastropoda - Lil Dude event log

How events are recorded and displayed

Events like birth or energy consumption are recorded using an object called HistoricalEvent, which extends Event. When you go to a snail’s profile page, all HistoricalEvents are loaded and their full text is generated (as you can see targetObject isn’t implemented yet):

    function GenerateFullText() {
        $snailmanager = new SnailManager();
        $snail = $snailmanager->LoadSnailInfo($this->snailID);
        if (!$snail->name) {
            $snail->name = "Unnamed";
        }
        $this->text = str_replace("@",$snail->name,$this->text);
        $this->text = str_replace("#",$this->numericalValue,$this->text);
    }

Thoughts on @HobbyGameDev’s Post on Starting Simple

Chris DeLeon of HobbyGameDev has written a post all about the importance of starting simple in game development, and of picking projects that make you reach as opposed to scramble in terms of their complexity versus your current skillset.

It looks like the article came about after a Twitter exchange with “Orange Rectangle” (O.R.), who got pretty defensive about making this super big an awesome idea comparable in scope (in his/her words) to CoD and Uncharted.

I totally know how O.C. feels because this happened to me. The fist video “game” (that’s in quotes because it’s actually more a simulation, in its current form I wouldn’t call it a game anymore) I really really wanted to make was Gastropoda (without the name at the time). When we moved to Australia at the end of 2005 I spent most of my free time in our apartment in Fremantle planning it out - or walking around the city thinking about it. I filled notebooks with layout sketches, attribute lists, database layout plans, snail observation notes, drawings of snails, excerpts of things I read about snails in textbooks, ten-page-long feature lists, etc.

The project had three real false-starts before the current interation, spanning about the last ten years. Every time I started I got stuck on something, spent a few days beating my head against the wall trying to figure it out, and then gave up. I’ve been trying to make this one thing for ten fricking years and getting nowhere. I simply didn’t have the ability to actually code the thing that was in my head. I imagine this is how new artists feel when they have an image in their mind that just doesn’t seem to translate on to paper no matter how much they try. It is infuriating.

Over the years I’ve now seen a number of people massively overshoot their means on an early project and fail spectacularly. In most cases that unfinished game is the last one they work on, never fully recovering from having dug a pit of embarrassment and fighting through considerable frustration every step of the way. Getting some practice before diving headfirst into these kinds of undertakings can help steel us to the complications that they entail.

The above is painfully accurate. I never really had the “embarrassment” part because I never publicly came out and said I’m going to make this super amazing thing and it will be awesome and it will be out in the year 2005 and everyone will be into it. I mean come on. We’re talking about snails here. User base: me. Even with tiny games I’m always more cautious when talking about them (don’t try to skin the bear before you’ve killed it, as they say). But I did definitely experience “fighting through considerable frustration”. I gave up on the idea so many times and every time I failed I said I wouldn’t make another attempt, until it came back and I thought “Hey, maybe it’ll be different this time”. It wasn’t. It wasn’t different until I learned the hard way, by accident, to do exactly what HobbyGameDev suggests and start making less ambitious projects.

I started making tiny JavaScript games instead (starting with a 3-level platformer that took 3 months to complete, then a Space Invaders clone that took a few days, and then a bunch of other things). And after a couple of years of tiny games I finally ended up with The Game of Snails - a very rough JS attempt to implement some tiny version of the idea.

When I finally decided to try to really make Gastropoda for the fourth time in PHP form, I wasn’t holding my breath. Except all of a sudden the problems I got stuck on years ago were no longer problems and the things I didn’t know (which is still a lot) were much easier to figure out. My problem before wasn’t just not being familiar with PHP syntax - it was not being familiar with basic concepts of how to structure the program as a whole. And I still don’t know exactly how to structure this entire thing - now I just know where to start and how to take it from there. I’ve refactored the whole thing once already and am constantly rethinking and changing how existing features work. I think I’m spending as much time on revising as features.

The point is - I think it’s totally cool to have big ideas before you’ve made anything small. But (if you’re anything like me) you really won’t be able to do that big idea justice until exactly the time that the rest of your brain is ready for it. Refusing to work on smaller things in the interim to get yourself to that stage is the equivalent of trying to dig a tunnel with a toothpick. You might eventually get to the end, but it’s much more likely that you’ll get sick of it and quit…or die of old age…well before that happens.