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.

OpenArthurianX6 – Plans for the first public release

Almost one year ago, I lay down a general plan for the development of the engine, lots of things happened since the campaign was funded, and there has been progress, but not at the pace I expected.

But now, I have much greater control of my work schedule, and it’s time to get serious. I also spoke with my friend Exodus Destiny Dragon, and he’s up to continue pushing the development

I still believe the original model, based on “capabilities” and “engine aspects”, is the way to go to get to the first release. I will include an additional facet: a plotline, for a game using the engine.

You may wonder, why is this important? and I believe it comes down to… motivation. It is hard to keep a constant influx of motivation when working on an engine, it’s cool to see things come together, but it’s too easy to lose direction if there isn’t something tying everything together.

From that initial plan, we have covered the following:

Capabilities

World

  • Move around the map
  • Pick up an item from the map

Dialogs

  • Talk with a NPC

Inventory

  • Check the inventory of a party member (Some progress)
  • Drop an item on the map

Combat

  • Enter and leave combat mode
  • Attack an enemy within melee distance
  • Attack a far away enemy

Engine Aspects

Maps

  • Day and Night Cycle: Some progress

Mobs

  • Follow player

How does the plotline affect this plan? all the items will be steered towards the construction of the scenario supporting it.

When the game starts the intro is displayed as follows:

  • The Avatar has been summoned back into Britannia, arriving during the night in a forest near Yew.
  • He finds Shamino and talks with him, learning about what has happened on Britannia.
  • They decide to head back into a safe place but are suddenly attacked by a group of soldiers led by Lord Asteroth of Empath Abbey.

The game starts in a forest clearing at night in combat mode (Similar to Ultima VI)

  • The Day/Night skyline indicator is visible, showing night.
  • The party is the Avatar and Shamino, they take turns to attack the enemy.
  • While in combat, the party members can move around
  • The Avatar is armed with a sword so he can do melee attacks
  • Shamino is armed with a bow so he can do ranged attacks
  • The enemy soldiers attack the party members using melee and ranged attacks

After 2 turns, Shamino is shot by a magic bolt by Lord Asteroth and is taken out of combat. Cutscene unfolds:

  • Out of nowhere, Iolo appears along with a band of resistance members
  • He shots Lord Asteroth with his crossbow and forces the soldiers to flee.
  • Then they disband leaving the party alone.
  • Iolo says they must seek refuge on his hut to the west.
  • Party is transported to Iolo’s hut.

Inside Iolo’s hut, the Avatar can:

  • Save the Game, Exit and Restore
  • Examine Iolo
  • Talk to Iolo using keywords
  • Ask Iolo to join the party
  • Open and close its main door
  • Read a book containing Iolo’s notes during the Quest of the Avatar
  • Get a key and use it to open an inside door going into his workshop
  • Go to the second floor
  • Examine a wall finding a secret lever (Revealed by Iolo in conversation)
  • Use the lever to open a hidden door into a room with a mystic sword.
  • Switch main character to Iolo
  • Get Mystic Sword
  • Examine Mystic Sword (in Inventory)
  • Get Magic Axe
  • Get a bag
  • Switch main character to Avatar
  • Check Avatar’s inventory
  • Check Iolo’s inventory
  • Put Mystic Sword into bag
  • Put Magic Axe into bag
  • Take Mystic Sword out of bag
  • Give Mystic Sword to Avatar
  • Make Avatar Use Mystic Sword (Wear)
  • Get yellow and blue potion
  • Drink Yellow potion, recover 5 HP
  • Drink Blue potion, recover 5 MP
  • Get lute
  • Use lute (go into instrument mode, can play using numbers)
  • Exit instrument mode
  • Use torch in the wall (put it off)
  • Use torch again (light it)
  • Get torch

In the area surrounding the hut, the Avatar can

  • Move around, having the party members follow him.
  • Examine the trees around
  • Examine a rock laying around
  • Get the rock
  • Drop the rock
  • Examine crate (Has some corn inside)
  • Move rock into crate
  • Examine crate, pick corn from crate
  • Use corn, be less hungry
  • Read a gravestone
  • Check the status of Shamino
  • Talk with Shamino, ask him to leave the party.
  • Talk with Shamino, ask him to join the party.
  • Get bucket, drop next to cow.
  • Use Cow (bucket gets filled with milk)
  • Attack Cow (Switch to combat mode)
  • Cow flees (peaceful animal AI)
  • Switch off combat mode
  • There are two friendly NPCs around (resistance members). They are hiding at Iolo’s
  • The friendly NPCs sleep at night in the barn, go to the fields during the morning, and have lunch at home at noon.

The party travels south

  • Smooth transition into another map segment (forest)
  • Time goes on into dawn and morning.
  • Party attacked by headlesses group. (Switch into combat mode)
  • Cannot switch out of combat mode.
  • When a headless is killed, he drops a corpse
  • After killing all headless, combat mode is automatically turned off
  • Corpses of headless can be examined as containers, they can have a club or not.

Or the party can be defeated…

  • If the headlesses or the soldiers kill the party, it’s game over

While implementing this flow doesn’t ensure the engine is completed, I believe iterating over it making it progressively better and more flexible every time will push forward the development of the engine.

Now comes the question about the dates. The idea is to produce biweekly builds and the plan is to have a working version of this flow within 20 work weeks, as detailed here.

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.

Paladin’s Quest LCD

20180509_183241

An entry for the LCD Jam, about 8 hours dev.

JavaScript + Phaser as usual for great quickness. Pretty happy with results, nice feedback received, may develop further afterwards.

Play online here (Source code here)

Screen Shot 2018-05-07 at 7.51.39 AM

The game is a simplified dungeon crawler, classic style roguelike, which emulates (loosely) a LCD game display.

There are 4 different enemies: Headless, Floating Skull, and Phantom. Scattered in the dungeon you will find strong weapons and replacements for your shield, you will need these to survive!

Each level is 3×3 rooms, you must find the exit which is located in the middle of one of the 9 rooms.

Screen Shot 2018-05-07 at 7.51.11 AM

The LCD shapes (i.e. the different parts of the paladin) were made by Giovanny Ramirez, the wiggly dungeon room and the “brick game” frame I made myself.

Tales of the Avatar: The Law of Virtue

It has been over four years since our Lord British’s expedition set forth into the underworld, never to be seen again. With our sovereign gone and The Avatar having returned triumphant to his home world, you, the people of Britannia, seems to have lost your way.

We were once proud of our town-states being places where you could conduct business safely and live a tranquil daily life, but now you steal and deceive each other continuously, seeking to build up your personal riches instead of striving for equality by giving to those in need. As this inequality grows, gangs of bandits roam the land, but you now cowardly refuse to join the ranks of the royal army to keep our cities safe from rogues and monsters.

Crime spreads throughout the land, and we have to double down in our efforts to upkeep the virtues as a way of living. But in our crusade for the good, we met with an unexpected reality: you are unwilling to contribute your resources to our difficult enterprise. You disgrace your taken oaths, challenging and distrusting the will of your superiors and following your own primal instincts instead.

Britannians have forgotten the sanctity of virtue. You now take pride in your self-imposed ideals as individuals, neglecting following the wisdom of your rulers.

It is in these dark times, when our Britannian society is on its direst need, that I have to proclaim the Law of Virtue. Under this law, Britannia will flourish again as the great virtuous society that it once was. We have gathered together a new council of the greatest thinkers and philosophers of the realm, who have contributed their experience and knowledge into a set of rules and actions that will bring us back to the way of the Avatar.

As a critical measure to put this new law into action, the current heads of our bastions will be removed from their post, replaced with three virtuous individuals of my utmost trust.

Lord Faulinei is to replace Lord Shalineth as the head of the Lycaeum and to act as the new Royal Chancellor. His main task will be ensuring our judiciary system can upkeep with the rising tide of crime, modernizing the laws and providing our inquisitorial prosecutors with all the tools they need to clean our lands from vices that corrupt it. Whoever opposes our law will be dealt with swift, relentless justice.

Lady Nosfentor will replace Lord Malone as commander of Serpent’s Hold, As Captain of the Army and Admiral of the Navy, she has been entrusted with bringing safety back to our realm. May the hordes of bandits and vicious rogues and outlaws fear our swords for they will soon perish along with their vices. Also, until noted otherwise, a curfew is in effect and all individuals roaming the cities during nighttime will be subject to being engaged in the name of the virtues by our royal knights and the newly created order of the Defenders of Virtue.

Finally, Lord Asteroth will replace Lord Michael as Empath Abbey. He will be given the daunting task of redistributing the riches of our land ensuring that no single individual owns more than he needs. You, people of Britannia, need to leave aside your greed and contribute to the work our institutions do to create and upkeep a better society. Eventually, all farmland will be redistributed and every Britannian family will have the means to strive through hard and loving work.

The mayors of all cities have also willingly removed themselves from their posts; their duties will be fulfilled by local committees of virtue, whose members will be revealed on each town as part of their re-educational programs.

Britannia counts with your submission into this new law. Help us make a better world for you and your children, or suffer our wrath.

Walk in the path of Virtue.

 

Always vigilant, your humble servant.

Lord Blackthorn
Regent of Britannia