The history of “Ultimate Collector”, Garriott’s stab at social gaming

In 2018, Portalarium is mostly associated with Shroud of the Avatar, the controversial multi-million dollars crowdfunded MMO / Single Player computer RPG. With all the noise it has caused, it’s easy to assume this game was Garriott’s comeback project after his long post-Tabula-Rasa hiatus.

However, before diving into the first new millennium iteration of his “Ultimate RPG” dream, Richard was strong on taking his newly founded company, “Portalarium“, into something completely different: games in social networks, and their efforts ultimately led them to partner with one of the biggest names on the scene: Zynga.

UC3

As you might have guessed, the game is now long gone. It actually never managed to have a broad public launch (although a couple of videos in youtube about hacking the game indicate it might have been shortly available to the public). Portalarium removed all information about the game from their website and killed all of its presence in social media, and it seemingly never made it past the threshold to be included on Zynga’s social games portfolio.

Still, the history of the development of this game is intertwined with Richard plans for the “Ultimate RPG”, which makes it interesting to imagine what Shroud of the Avatar could have been.

CLICK HERE TO READ THE FULL ARTICLE!

Hulk-Bobble-Head

ProcJam Summer 2018 – Pokemon Building Generator – Part 1

Procjam Summer 2018 has started so here I go. This will be a small project to create classic Pokemon style houses. (Guess what I might end up using it for)

This will be a two steps generator, the first thing to do is defining a logical model for the houses. We start by examining some examples to extract the structure and an initial set of variations:

Screen Shot 2018-06-20 at 3.23.33 PM

Structure

  • Blocks of 4 tiles
  • Windows and walls can be placed at tiles, having one tile for padding at every side (available tiles = blocks – 1) * 2, this padding is used to project the shadows of the building.
  • Doors can be placed at blocks, having one block for padding at every side.
  • Distorted perspective, the “depth” of the building is represented as blocks of the ceiling.
  • The last floor gets 2 less available tiles due to roof slant

Attributes:

  • Structure
    • Width: 6 blocks
    • Height: 2 blocks
    • Depth: 2 blocks
  • Front
    • 1st floor
      • Windows: Tiles 1, 2, 3, 6, 7, 8, 9 and 10
      • A door at block 3
      • Wooden wall (1 to 10)
    • 2nd floor
      • Windows: Tiles 2, 3, 4, 7, 8 and 9
      • Wooden wall (1 to 3)
      • Brick wall (4 to 10)
  • Roof
    • Slanted
    • Tiled

Next example:

Screen Shot 2018-06-20 at 3.34.38 PM

Front

  • 2nd floor
    • Bar border

Next Example:

Screen Shot 2018-06-20 at 3.43.19 PM

Structure: The last floor gets all available tiles if the roof is flat

  • Front, First floor
    • Poke sign at block 3
  •  Roof
    • Flat

Let’s confirm our model covers all wanted cases

Screen Shot 2018-06-20 at 3.52.51 PM

  • Structure
    • Width: 8 blocks
    • Height: 6 blocks
    • Depth: 2 blocks
  • Front
    • 1st floor
      • Windows: Tiles 6, 7, 10, 11
      • Doors at blocks 2 and 4
      • Mart sign at block 6
      • Brick wall
    • 2nd floor (…)
  • Roof
    • Flat
    • Tiled

Having this, we can start thinking on our higher level generator, its input will be the type of building and its size. Following are the types of buildings we’ll support: House, Gym, Mart. As for the sizes, they will be: Tiny, Small, Large, Huge.

The output of the high-level generator is a logical model of the building, which is used by the lower-level generator to produce a map of tiles. An example of the 1st output for a Large House would be:

Screen Shot 2018-06-20 at 3.34.38 PM

{
  width: 4,
  height: 2,
  depth: 2,
  floors: [
    {
      wall: 'wood',
      windows: [4, 5],
      doors: [1]
    },
    {
      wall: 'wood',
      windows: [2, 4, 5],
      border: true
    }
  ],
  roof: {
    type: 'slanted',
    material: 'tiles'
  }
}

Let’sa go! We fire subl and produce this:

const Random = {
  chance(c) {
    return this.range(0, 100) <= c;
  },
  range(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }
};


const SIZE_RANGES = {
  tiny: {
    minw: 3,
    maxw: 4,
    minh: 1,
    maxh: 1,
    mind: 1,
    maxd: 1
  },
  small: {
    minw: 4,
    maxw: 5,
    minh: 1,
    maxh: 2,
    mind: 1,
    maxd: 1
  },
  large: {
    minw: 5,
    maxw: 6,
    minh: 2,
    maxh: 3,
    mind: 1,
    maxd: 2
  },
  huge: {
    minw: 5,
    maxw: 8,
    minh: 3,
    maxh: 5,
    mind: 2,
    maxd: 4
  }
};

const SLANTED_ROOF_CHANCES = {
  house: 90,
  gym: 20,
  mart: 10
};

const WINDOW_CHANCES = {
  house: 50,
  gym: 20,
  mart: 50
};

// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

const generator = {
  generate(type, size) {
    const model = {
      width: 0,
      height: 0,
      depth: 0,
      floors: [],
      roof: {},
      type,
      size
    }
    // Size of the building
    const sizeRanges = SIZE_RANGES[size];
    model.width = Random.range(sizeRanges.minw, sizeRanges.maxw);
    model.height = Random.range(sizeRanges.minh, sizeRanges.maxh);
    model.depth = Random.range(sizeRanges.mind, sizeRanges.maxd);
    // Type of roof
    model.roof.type = Random.chance(SLANTED_ROOF_CHANCES[type]) ? 'slanted' : 'flat';

    for (let i = 0; i < model.height; i++) {
      model.floors[i] = this.generateFloor(model, i);
    }
    return model;
  },

  generateFloor(model, floorNumber) {
    const floorModel = {
      wall: '',
      windows: [],
      features: []
    }
    const useableBlocks = [];
    for (let i = 0; i < model.width - 2; i++){
      useableBlocks[i] = true;
    }
    const useableTiles = [];
    for (let i = 0; i  {
      if (!t) {
        return;
      }
      if (Random.chance(WINDOW_CHANCES[model.type])) {
        floorModel.windows.push(i);
      }
    });
    return floorModel;
  },

  getRandomSpace(array) {
    const availables = array.find(x => x === true);
    if (!availables) {
      return undefined;
    }
    const spaces = array.map((x, i) => ({x, i})).filter(x => x.x === true);
    return shuffle(spaces)[0].i;
  }
}

const model = generator.generate('mart', 'huge');

console.log(JSON.stringify(model));

Running it with nodejs gives us a variety of models already:

{
  "width":6,
  "height":2,
  "depth":2,
  "floors":[
    {
      "wall":"",
      "windows":[
        4,
        7
      ],
      "features":[
        {
          "x":1,
          "type":"door"
        },
        {
          "x":3,
          "type":"gymSign"
        }
      ]
    },
    {
      "wall":"",
      "windows":[
        3,
        9
      ],
      "features":[

      ]
    }
  ],
  "roof":{
    "type":"flat"
  },
  "type":"gym",
  "size":"large"
}

 

{
  "width":8,
  "height":5,
  "depth":3,
  "floors":[
    {
      "wall":"",
      "windows":[
        0,
        4,
        5,
        13
      ],
      "features":[
        {
          "x":3,
          "type":"door"
        },
        {
          "x":0,
          "type":"martSign"
        }
      ]
    },
    {
      "wall":"",
      "windows":[
        1,
        3,
        5,
        6,
        7,
        9,
        10,
        11,
        12,
        13
      ],
      "features":[

      ]
    },
    {
      "wall":"",
      "windows":[
        0,
        1,
        3,
        4,
        5,
        7,
        10,
        12,
        13
      ],
      "features":[

      ]
    },
    {
      "wall":"",
      "windows":[
        0,
        1,
        5,
        7,
        8,
        9,
        11,
        13
      ],
      "features":[

      ]
    },
    {
      "wall":"",
      "windows":[
        0,
        1,
        4,
        5,
        8,
        9
      ],
      "features":[

      ]
    }
  ],
  "roof":{
    "type":"flat"
  },
  "type":"mart",
  "size":"huge"
}

Next step is using these models to create the maps of tiles.

Roguelike Origin section at Wikipedia

I added a new section to the “Roguelike” Wikipedia article on the origins of the “roguelike” term, based on my USENET findings.

 

Screen Shot 2018-05-18 at 7.44.41 AM
First version

 

I agree words should evolve based on their usage, but I think it’s important not to forget what they were originally used for. Lots of people just fall for “roguelike” games being “like Rogue” and stop there, leaving room for a lot of ambiguity. That’s also the reason why I proposed a “Traditional Roguelike” definition to make it easier to find games that better keep the spirit of the originals.

So far, the section has survived for about half a day with some minor edits, let’s see how long it survives!

 

Screen Shot 2018-05-18 at 7.45.02 AM
6 hours later

 

Here are the references I used, for historical purposes:

  1.  Solovay, Andrew. (July 27, 1993). “CFV: rec.games.roguelike reorganization”. Newsgroupnews.announce.newgroupsUsenet: rec.games.roguelike-CFV1@uunet.uu.netI would like to propose formally that a new hierarchy be created, namely rec.games.roguelike. This hierarchy would contain groups dedicated to discussion of rogue-type games.
  2. Panitz, Aliza. (June 18, 1993). “Time for a new level of heirarchy?”Newsgrouprec.games.moriaUsenet: 1vsuhk$mj7@bronze.lcs.mit.edu. Retrieved May 17, 2018It seems to me that we’d do a lot better taking all of the dungeon-adventure games, including ones that don’t have their own newsgroups like larn and omega, and reorganizing them under rec.games.dungeon – recognizing the intrinsic similarities of all these games. It would make it a lot easier for people who like one of these games to find newsgroups about other, basically similar games, and would finally provide a home for all those random posts about Larn and other games of the same genre that keep popping up in rec.games.hack and other inappropriate places.
  3. Solovay, Andrew. (July 2, 1993). “RFD: rec.games.dungeon.* hierarchy”Newsgroupnews.announce.newgroupsUsenet: 211gvmINNsnp@rodan.UU.NET. Retrieved May 17, 2018I would like to propose formally that a new hierarchy be created, namely rec.games.dungeon. This hierarchy would contain groups dedicated to discussion of rogue-type games.
  4. Solovay, Andrew. (July 20, 1993). “3rd RFD: rec.games.roguelike.* hierarchy”. Newsgroupnews.announce.newgroupsUsenet: 22ie07INNbaa@rodan.UU.NETThose people who agree on a name seem to favor “roguelike” as the least of all available evils.
  5. Grabiner, David. (March 9, 1998). “RFD: rec.games.roguelike.development”. Newsgroupnews.announce.newgroupsUsenet: 889443102.8279@isc.orgWith the large number of Roguelike games and variants in existence and in development, there are occasional discussions about programming problems such as dungeon-generation algorithms which are of interest to designers of several games.

Two new articles added to roguetemple

Based on my recent research and considerations of the roguelikes in the videogames scene in 2018, I just published two new articles into Temple of the Roguelike. Both originate from my talk on the Roguelike Celebration 2017.

The first one is “A short history of the “roguelike” term“, which expands upon my previous article “On the Historical Origin of the “Roguelike” Term“, covering the events after the term was established and the subsequent confusion.

Screen Shot 2018-01-17 at 12.08.04 AM
A fragment from the second age of roguelike development.

The other related article is What is a Traditional Roguelike; after 10 years of trying to come up with long lists of definitions, I narrowed it down to 4 critical aspects I think traditional roguelikes should keep:

1. Permanent Consequences

The outcome of any action you take into the game cannot be rolled back by reloading a saved game (including death).

This encourages both careful tactical play and long-term strategies and planning and increases the excitement of advancing through the procedural content generated by the game.

2. Character-centric

The player personifies a single character into the game at a time, this is in contrast to both a.) games where the player doesn’t control person-like characters directly (for example puzzles) and b.) “god” style games where the player is an abstract entity creating and controlling multiple discardable “units”.

Besides providing a common, shared base format for the Traditional Roguelikes, being character-centric helps the player establish a strong relationship with the individual characters, increasing the impact of the permanent consequences.

3. Procedural content

Increases the replayability of the game by having most or all of the world be generated by the game for every new gameplay session.

In addition to providing an incentive for players to dig into the game, procedural content serves as a tool to prevent the player from being frustrated by the harsh effect of permanent consequences, having to start gameplay session from scratch frequently.

4. Turn Based

Gameplay is similar to a board game where you can think your actions carefully, having infinite time to reflect on your available options to face the situations that the game presents you with the resources you have at hand.

This is relevant given consequences are permanent, and the intent of the game is not testing how quick the player can take an acceptable decision but rather challenging him to think out the best move he can make in critical scenarios.

Researching the historical origin of the “Roguelike” term

On November 11 2017, at the Roguelike Celebration in San Francisco, I had the pleasure of doing the opening talk, titled “What is a Roguelike?, 2017 Edition”, where I explored some of the interpretations on the Roguelike term.

keynote

Something interesting I found while doing research for the talk was what could be the first efforts to organize a group of games similar to rogue under an umbrella term. This happened on Usenet, the technological precursor to Internet Forums, throughout which most of the discussion of computer games happened.

My current progress on this research indicates that the efforts to define this hierarchical relationship, intended mainly to facilitate discussion, ended up serving the purpose of creating a community of niche developers and players who through the constant usage of the term ended up giving it an evolving, collective meaning that was relatively stable until the 2010’s decade, with the growth of the indie games scene and diffusion of the more action focused “Roguelike” labeled games.

Read the full article here