MapReducing plants and players

I haven’t been doing much work on Germination X lately, but we are now up to 101 players, and 766 plants alive at time of writing. Of the 101 players 60 of them are on the first “level” of planting ground cover plants, 24 are at level 2 planting shrubs and 4 have made it to tree planting. 13 have completed the tree planting level and are free to plant what they like.

The mongodb database the game now uses allows you to connect via a console and pull out some statistics using bits of JavaScript with a feature called mapReduce – an idea based on the lisp functions map and reduce (or fold in Scheme) and made popular by Google with it’s search algorithm.

Each tile in the world contains a list of entities (each plants is an entity), so we can “map” over the tiles, creating a new list of plant counts. Then we “reduce” over the counts with another function to find the total. This approach allows the database to do the operations in parallel, and control the amount of memory required – which would be necessary if we had a fair few more players :)

db.tiles.mapReduce(
    // map fn 
    function() { 
        emit("total",{count:this.entities.length}); 
    },
    // reduce fn
    function(key, values) { 
        var result={count:0}; 
        values.forEach(function(v) { 
            result.count+=v.count; 
        }); 
        return result;
    }, 
    // tell it to spit out the result in the console
    {out: {inline:1}}
)

This more complex example tells us the distribution of players by how far they have got:

db.players.mapReduce( 
    // map fn
    function() { 
        if (this.layer==0) emit("ground cover",{count:1}); 
        if (this.layer==1) emit("shrub",{count:1}); 
        if (this.layer==2) emit("tree",{count:1}); 
        if (this.layer==3) emit("complete",{count:1}); 
    },
    // reduce fn
    function(key, values) { 
        var result={count:0}; 
        values.forEach(function(v) { 
            result.count+=v.count; 
        }); 
        return result;}, 
    {out: {inline:1}}
)

Leave a Reply

Your email address will not be published. Required fields are marked *