Thursday, December 22, 2016

Dark Souls III Analysis

Another game analysis from earlier in 2016.

1 Overview


Dark Souls III is an action RPG developed by FromSoftware and it was published by Bandai Namco in 2016.

2 Formal Elements


2.1 Players


Dark Souls III is a mostly single-player game, but features unique multiplayer elements. The player is an ”Unkindled,” which is an undead zombie like creature created from the ashes of a fire. This fire represents an age of gods, or knowledge, or power, or something that is not directly told or explained to the player. The player’s character can be male or female, and can start as any of 10 classes, each with slightly different stats and starting level.

LevelVigorAttunementEnduranceVitalityStrengthDexterityIntelligenceFaithLuck











Knight 9 12 10 11 15 13 12 9 9 7











Mercenary 8 11 12 11 10 10 16 10 8 9











Warrior 7 14 6 12 11 16 9 8 9 11











Herald 9 12 10 9 12 12 11 8 13 11











Thief 5 10 11 10 9 9 13 10 8 14











Assassin 10 10 14 11 10 10 14 11 9 10











Sorcerer 6 9 16 9 7 7 12 16 7 12











Pyromancer8 11 12 10 8 12 9 14 14 7











Cleric 7 10 14 9 7 12 8 7 16 13











Deprived 10 10 10 10 10 10 10 10 10 10












The player can also choose a starting gift, although the significance of the gift is difficult to gauge.
The player moves a 3D avatar around a 3D world, interacting with NPCs, killing monsters, and finding items and equipment. The motivation is to defeat 4 Lords of Cinder and return their embers to theirs thrones. Once this is accomplished, the player will face a final enemy boss and may choose to link the First Flame, let it die, or (if the player has completed certain side quests) to usurp the flame and start an age of fire controlled by the Undead.
While the player explores and fights, the player may be invaded by other players if the player is in their ”ember form.” In ember form, the player may also summon other players or NPCs into their world for duels, or for assistance in certain areas, or against certain bosses. The player may also leave messages to assist or to trick other players. When other players die, they leave blood stains that are sometimes visible in your game. If you touch them, they will show the last ten seconds of their life, thus giving a clue as to how they died and how the player may avoid it. The player can even invade other players while they are playing. Invading is rewarded with XP and special items, as is assisting others and defeating invaders.
The player can even join in-game covenants that specialize in invading, assisting, or defeating invaders.

2.2 Objectives


The main objective in Dark Souls III is to defeat the final boss and link the First Flame. This is accomplished by defeating a series of lesser bosses which unlock new areas of the game and allow the player to finally unlock the final Lord of Cinder’s arena.
There are covenants to discover and join, as well as optional ”quests” for NPCs to complete. These quests, however, are structured and presented similarly to the rest of Dark Souls III: the player must repeatedly talk to NPCs, listening carefully to dialogue, search every environment carefully for any possible link to that or another NPC, and figure out what to do next. This could mean purchasing armor and dropping it off at an appropriate location, finding a hidden location, or performing rituals. There is no quest journal with notes or quests, and there is no in-game map to guide the player around in these ”quests.”
There are also optional bosses and areas to defeat and explore.

2.3 Rules


2.3.1 Bars, Form and Souls

In Dark Souls III, there are three bars that must be managed at all times: health, stamina, and focus. Health partly determines the amount of damage the player can take and if it reaches zero, the player will die. In the Souls series, dying means losing all the souls the player was carrying at the time of death. Souls are the Souls series’ form of XP and money, so this is a huge loss. Luckily, dying does not mean a permanent loss of these souls. After dying, the player will also lose their ember form and respawn at the nearest bonfire. If the player can fight their way back to the place they died, they can retrieve their lost souls by touching a green glowing blood stain. If, however, the player dies before retrieving their lost souls, they will lose those souls forever. The amount of health is determined by the player’s form, Vigor stat, and any items that affect health. Unlike in Dark Souls II, there are only two basic health states: undead form and ember form, and does not get progressively lower the more the player dies. Health can be regained by resting at a bonfire, dying and respawning at a bonfire, drinking an estus flask, or using special items, like certain weapons or rings that drain health from enemies, regenerate health based on killing enemies, or regenerate health based on (consecutive) attacks.
Stamina must also be managed during combat. All physical attacks drain stamina, as does running and roll-dodging. If stamina drops to zero, the player cannot attack or dodge until it recharges high enough to meet the stamina requirements for that move. The player’s amount of stamina is controlled by the Endurance stat. Stamina regenerates naturally by itself over time, although holding the block button slows its regeneration rate.
Focus is used when the player makes magic-,pyromancy-,or miracle-based attacks. Like stamina, if focus drops to zero or is less than the required amount to cast a spell, the player will not be able to cast it. The amount of focus is determined by the Attunement stat and certain special items. Attunement also determines the number of spells, pyromancies, or miracles the player may have active at a time. Focus regeneration works like health regeneration: it does not regenerate naturally by itself, but can be regenerated by resting at a bonfire, using special items, or drinking an ashen estus flask.
There are only two basic forms: ember form and undead form. Ember form is similar to the human form from Dark Souls and Dark Souls II. Being in ember form gives the player increased health, stamina, and focus, and allows the player to access the multiplayer components of the game. The player can also gain levels from an NPC in exchange for accepting a Dark Sigil, which will cause the player to become hollowed. This has no real effect outside of making the player look like a zombie. If the player wants to return to their normal form, they may use a special item or be cured by talking to certain NPCs, but this will lock off certain endings.
As mentioned before, souls are both the money and the XP. They are used to buy items from vendors, and are used to increase the player’s level by talking to the Firekeeper NPC at Firelink Shrine. The number of souls required to increase from one level to the next roughly follows the formula y = 1062.760.0459x, where y is the number of souls required to increase to the next level and x is one’s current level.
2.3.2 Stats and Leveling

There are nine stats that the player may invest in when they level up:
  • Vigor, increases health and frost resistance
  • Attunement, increases focus and spell slots
  • Endurance, increases stamina, lightning defense, and bleed resistance
  • Vitality, increases equipment load, physical defense, and poison resistance
  • Strength, increases damage with weapons, fire defense, physical defense, and other defenses
  • Dexterity, increases damage with weapons, and all defenses
  • Intelligence, increases spell damage and magic defense
  • Faith, increases miracle damage, and damage resistances
  • Luck, increases item discovery

How the player invests in these stats and what weapons and armor they decide to use basically determines how they will play the game.
2.3.3 Combat and Magic

In the Souls series, weapons, shields, and the different kinds of magic usually scale according to the player’s stats. So, for example, if the player is using a Greatsword in one hand, and has 28 Strength and 9 Dexterity, it will do 159 base damage plus 42 damage based on attribute scaling. Adding one point to Dexterity increases the bonus to 43, while adding one point to strength instead increases it to 44. While this is admittedly a small difference, if the player reinforces the Greatsword to +3, while keeping Strength at 28 and Dexterity at 9, the base damage increases to 206 plus 63 damage based on attribute scaling. If the player continues to reinforce the Greatsword to its maximum of +10, the scaling due to attributes is 119 damage.
What all that boils down to is that if you find a weapon that you like to use, it makes sense to pay attention to which attributes the weapon scales with, and then level up a character to best match that scaling. Infusing the weapon with fire damage, or other kinds of damage will also change how the weapon scales, which could make it a better or worse match for certain builds. The same holds true for the different kinds of magic: they are cast using different magic weapons, which scale according to different attributes, and the player must find items that match how they want to play the game.
In general, the combat in the Souls series has been described as weighty, precise, and tactical because the movements are slow compared to other action RPGs and practically glacial compared to hack-and-slash games. Success in combat revolves around learning the enemy’s moveset and attack patterns, and responding to openings and opportunities to attack by punishing the enemy. Thoughtlessly smashing away at the attack buttons will almost always result in player death, as will brash and greedy attacking. Caution is almost always rewarded.
Compounding this is the fact that actions cannot be interrupted by the player: once you press the attack, use item, or dodge button, you are fully committed to the action and must wait for the animation to finish before initiating your next move.
The player can run, dodge, jump, attack, block, and parry during combat. When dodging, there are a certain number of framing during the animation during which the player is invincible. Running, dodging, jumping, attacking, parrying, and receiving a hit during blocking all cost stamina.
The player may also use a ”weapon art” during combat. This is a special move that is determined by the weapon equipped in the player’s right hand. These moves cost focus and have a wide range of effects: some greatswords have a stance weapon art that allows two new moves when used in combination with the regular light an heavy attacks. Others have status boosters, like increased poised or damage, while others trigger special attacks.
2.3.4 Areas

Unlike the first two games in the Souls series, Demons Souls and Dark Souls, the areas are mostly linearly connected. This means that the player can more easily gauge their progress through the game, but also reduces the amount of discovery and connections between areas. Dark Souls, in particular, featured many weird and interesting shortcuts between areas that could only be unlocked by first progressing quite far in an area, before unlocking an elevator or door that would return the player to the starting area or another previously discovered location.
In Dark Souls III, progress is made by killing a boss, which will either have an item that unlocks a later area, or that automatically allows access to the next area.
There are several extremely hidden areas that most players would normally never discover, for example, an area unlocked by attacking a bridge which can then be climbed down like a ladder, or by performing a gesture in a certain location.
Also in contrast to previous games, the number of bonfires is quite large and many are extremely close together.

2.4 Procedures


2.4.1 Leveling and Upgrading

After finding items and slaying enough enemies, it is time to return to the main hub of the game, Firelink Shrine. By talking to the Fire Keeper, the player can level up, and by talking to different NPCs there, the player can increase the number of healing items carried and their power, upgrade weapons, and buy and sell weapons, armor, and items.
2.4.2 Exploring

A large part of game play is exploring the environments the player finds themselves in. Often, the next area can only be found by going over each section of the current environment, panning the camera around, and looking for ledges, hidden doors, obscure paths, and banging one’s weapon against walls to find illusory walls. Another incentive to exploring is item discovery. Often really amazing items are hidden around each level, and finding the next one is always a thrill.
2.4.3 Boss-Slaying

Like the lesser enemies, the bosses are each designed to be challenging to the player in different ways. Some are extremely aggressive, some are fast, some attack slowly but do massive damage, others use mostly magic attacks. Many of the bosses have stages to their battle, and several actually come back to life after the player has ”killed” them.
Their attack patterns must be learned, and there are often clues as to what they are weak to somewhere in the environment or in dialogue with an NPC.
Thematically, each is linked to previous games in different ways.

2.5 Resources


2.5.1 Abstract
  • Health: Losing all your health means dying and respawning back at the nearest bonfire. As mentioned before, the player will lose all currently possessed souls as well.
  • Stamina: Stamina determines the player’s ability to attack, dodge, and block during combat, and managing it is critical in every encounter.
  • Focus: Focus, like health and stamina, must be managed carefully to ensure that you can use magic and special abilities when you need to.
  • Damage Meters: There are many kinds of special damage that the player can receive: frost damage, curse damage, bleeding damage, and poison damage, for example. These damages fill a special meter that only becomes visible when the player receives them. If the meter fills up completely, a special status effect will take effect on the player. Poison damage, for example, will cause the player to slowly lose health until the poison meter is empty, while frost damage will slow player movement and prevent rolling until it is empty.
  • Souls: Souls are both the currency and XP in Souls games, and are vital for upgrading weapons, purchasing weapons, armor and items, and of course for leveling up. Losing souls because of dying before being able to retrieve lost souls is a wake up call to be more cautious.
  • Form: In many areas, special hostile NPCs will only spawn in if the player is in ember form. These NPCs give the player a large number of souls if defeated, and often drop special items as well. The player’s form also determines whether multiplayer aspects of the game will be available.

2.5.2 Physical
  • Weapon and Armor Condition: Shields and weapons degrade through taking damage, and can break if their condition drops to zero. Resting at a bonfire will restore the damaged item to perfect, although if it breaks the player must return to Firelink Shrine to get it fixed.
  • Estus and Ashen Estus: These are the only healing items for health and focus in the game. They are limited in number and can only be refilled in two ways: randomly killed enemies sometimes replenish one flask of Estus, and resting at a bonfire fully replenishes all Estus and Ashen Estus flasks.
  • Weapons and Other Equipment: Different enemies and areas have different themes, and their strengths and weaknesses are reflected in those themes. Dragons are weak to lightning damage, but immune to fire, so a dragon-themed area will best be handled by switching to lightning weapons and fire-resistant armor and rings.
  • Items: Items like arrows, throwing knives, weapon buffers, and status removers are limited in number and must be farmed from the environment or bought from vendors. Using them wisely will help ensure success.

2.6 Conflicts


2.6.1 Stat Point Investment

As the player invests points, it becomes apparent that around 40, the benefit of each additional point invested starts to decrease. This effect of diminishing returns forces the player to consider whether investing in a different stat might better benefit them.
The cost for increase one’s level increases dramatically at higher levels, further forcing the player to carefully consider each investment.
2.6.2 NPCs

The NPCs in Dark Souls III each seem to have different objectives, and the player is free to help them or hinder them as they choose. However, helping some NPCs usually means hindering and earning the hostility of others. Deciding who to help and who to ignore or kill is no trivial task, considering the obscurity of what each one ultimately wants.

2.7 Boundaries


2.7.1 Stat Point Investment

There are hard limits to each stat at 99 points.
The player can only equip 4 rings, and three weapons for each hand at a time.
2.7.2 NPCs

It is impossible to help every NPC in complete their quest line in one play through.

2.8 Outcomes


There are three basic endings for Dark Souls III: the player may link to the first flame, causing the age of fire to continue. Or the player may not link the first flame, causing the age of fire to end, and the age of darkness to begin. A somewhat hidden and difficult to obtain third ending is to usurp the first flame, and begin an age of the undead, with the player as Lord of the Undead.

3 Dramatic Elements


Dark Souls III is strongly connected to the previous two games through recurring themes, characters, and events. However, these are presented in such an obscure and fragmentary manner that it is difficult for the average player (and I count myself as an average player) to piece together what is happening, why, and what has happened in the past.

3.1 Characters


Compared to the characters of previous Souls series games, the NPCs in Dark Souls III offer more helpful advice and guidance about where the player is, where the player should go, and how the player should get there. Several even describe basic game mechanics like the process of upgrading weapons. However, as previously mentioned, the characters related their histories, relationships with other characters and covenants quite indirectly, forcing the player to guess at how to find them, who they should help etc.

3.2 Story


The basic story revolves around the linking of the first flame. The gods created fire ages ago, but their age of fire was supposed to end and an age of dark was supposed to begin. However, a lord called Gwyn linked his soul to the first flame, thus causing an unnatural age of fire to begin. This linking of the first flame may have caused a side effect of the dead rising and the living transforming into the undead.
The player begins as an undead that has arisen from the ashes of one sacrificed at the first flame. At this point in time, the previous Lords that have linked the flame have abandoned their thrones, heralding the end of the age of flame and the beginning of the age of dark. The player is tasked with defeating the previous lords, returning them to their thrones, and linking the first flame themselves, thus becoming a Lord of Cinder. However, the player may decide on a different path over the course of the game, but the final ending is determined by the choice to link the flame or not (except in the case of the third ending, where the player must perform pretty).

4 Dynamic Elements


Compared to other games, the environment of Dark Souls III is quite static. Enemies will always be found in the same spawn areas, there is no day/night cycle or dynamic weather. Enemies do not change their movesets or armor as they react to the player’s moment to moment actions or even the player’s long term play style, although in each particular battle they will change between different stances and attempt to heal themselves if they are injured.
As the player progresses through the game, they will unlock more areas, and through careful exploration, discover secrets, items, and powerful weapons and spells. Further, since the weapons and spells’ damage scale to various player attributes, the amount of damage they deal changes quite a bit during the course of the game.
If the player chooses to join a covenant, as the player offers that covenant special items related to its goal, the player will receive weapons and spells as rewards.
If the player explores previous areas of the game, the player may sometimes find new items that were spawned in after defeating a character in a different part of the game.

5 Conclusion


Dark Souls III is probably the most accessible of the Souls series of games. Its story is fragmented, but intriguing, its gameplay is subtle, visceral and tactical all at the same time, and it offers a large amount of replay value as the player completes new game plus modes, tries different builds, and attempts to complete different endings. Even exploring each area, finding and defeating each boss, and especially finding each hidden item and covenant, offers enough challenging and rewarding play to keep you coming back for a long time.

5.1 Potent Elements


The combat is quicker than in previous Souls games, but still has a precise, tactical feel to it. Exploration, leveling, and combat make up the core of the game, and each is masterfully done.

5.2 Areas for Improvement


Although Dark Souls III is by far the most accessible of the Souls series, that does not make it as accessible as Fruit Ninja, for example. There is no in-game map, no in-game explanation for how to level up, and even after defeating the first boss and reaching Firelink Shrine (the hub area), there is no explanation for how to get to the next area. Although having an in-game map would probably ruin the game, providing more NPC dialogue to explain the other areas to the player would greatly improve its accessibility.
One other area of improvement is the magic system. The Souls series has used basically the same set of spells and miracles and pyromancies since the first game, and these did not allow the player to play as a pure magic user then. Although the focus bar and items that affect its regeneration make it more possible to play as a magic user, the variety of spells needs to be increased to allow crowd management and to give access to an increased number of damage types.

Bioshock II Analysis

Here is one of about 10 game analyses I've completed over the last year. Probably about as exciting as reading Wikipedia, but there you go. The 1960 Presidential Debates were less interesting than the ones between Clinton and Trump, but I'd still say they had a lot more actual content.

1 Overview


Bioshock II is a story-driven FPS with RPG elements developed by 2K Marin and published in 2010. It takes place after the events of Bioshock and the levels feature similar environments to the first game.

2 Formal Elements


2.1 Players


The main campaign is single-player only, but there is a multiplayer mode as well. You play as a Big Daddy, known as subject Delta, who has been separated from his Little Sister, Eleanor.

2.2 Objectives


The main objective is to reunite with the Little Sister which you are bonded to, but there are optional objectives in the form of rescuing or harvesting all the Little Sisters, buying and/or upgrading all plasmids, completing the research on some or all of the enemies, and a few others.

2.3 Rules


The player may only have one weapon in the right hand and one plasmid in the left. If the player dies, they will respawn at a Vita-Chamber with half-health and some amount of EVE restored.
As a Big Daddy, you can attack other Big Daddies and take possession of their Little Sister. If you choose to, you can have them guide you to a corpse with ADAM to be harvested. While they harvest the ADAM, the player will have to protect her from waves of enemies.
There are a limited number of Little Sisters in each level, and in the game as a whole. The player must decide how to treat them, either rescuing them or harvesting them. Either choice awards the player with ADAM to use in leveling up, but harvesting gives more immediate benefit. After gathering all the Little Sisters in a level, the player will face a Big Sister, which is a faster and plasmid-enhanced version of a Big Daddy.
The game is a linear set of levels, yet each level may be explored freely by the player. Unlike the first game, there is no backtracking, as some levels are flooded or destroyed following story-events.
2.3.1 Equipment and Inventory

Managing one’s inventory is extremely important. You may only carry a limited amount of ammo for each weapon (although this may be upgraded throughout the game), and 5 health kits and 5 EVE hypos. Running short of ammo, health kits, or EVE hypos can easily result in death and respawning. Scavenging around the environments for these items and for cash to buy them at vending machines.
2.3.2 Hacking and Plasmids

Throughout the levels, the player will find vending machines, security cameras, and turrets of different kinds. These may all be hacked. The vending machines give reduced prices to the player, while the security cameras, turrets, and flying bots become allies in a fight. If the player is clever, they can maneuver a Big Daddy or Bid Sister into an area with hacked security cameras and turrets, turning a challenging fight into a fair or even easy one.

2.4 Procedures


There are several procedures that the player will engage in during play.
  1. Defeat Big Daddy/Big Sister: In order to acquire a Little Sister, the player must defeat a Big Daddy. These are initially neutral to the player as you go through each level, and only become hostile upon attacking them. Before attacking, a wise player will pick an ambush spot and stock up on ammo and health kits/EVE hypos. The Big Sister encounters are more difficult, since they will occur automatically after the player has freed or harvested all the Little Sisters in a level. These are one of the few times where I felt frustrated in the game, since I would often die, only to respawn and have half health/EVE and be minus the ammo and health items I’d used trying to defeat her the previous times. The player cannot advance without defeating the Big Sister.
  2. Defend Little Sister: During ADAM harvesting, the Little Sister is defenseless, and the player must defend her from waves of enemies. As the game progresses, the level of the enemies increases, making each harvest more harrowing.
  3. Find/Destroy Item: At several points during the game, the player will be tasked with finding or destroying a specific item(s). The player must explore the environment or follow the quest markers until the item is taken care of.
  4. Defeat Boss: There are several bosses in the game, and the player must learn their attack patterns to some extent in order to defeat them. However, many of them are simple bullet sponges.
  5. Explore Level: Exploring each level is a joy. The developers have hidden audiologs which tell backstory, give combinations for safes and locked doors, rare plasmids, and lots of random items and cash. Scavenging the items is necessary to succeed in the game, but learning about the history of the city of Rapture is also a pleasure.

2.5 Resources


2.5.1 Abstract
  • Health: Health measures how much damage the player can take. If it runs out, the player will respawn at the nearest discovered Vita-Chamber.
  • EVE: EVE allows the player to use plasmids.
  • ADAM: ADAM is gathered from corpses by Little Sisters. The player may either rescue the Little Sisters to receive their ADAM, or harvest them directly. Either way, the ADAM is necessary to purchase and upgrade plasmids.
  • Plasmid (upgrades): There are 10 plasmids in the base game, each of which may be upgraded twice. Each allows the player different abilities, such as becoming invisible, causing enemies to become allies and attack other enemies, summoning fire, ice, or electricity, etc.
  • Passive Plasmids: There are a large number of passive plasmids that the player can equip. These include abilities like linking health kits and EVE, so that whenever the player uses a health kit, a small amount of EVE is also replenished.

2.5.2 Physical
  • Weapons: There are 8 different weapons, each of which uses different ammo and is useful in different situations. The speargun, for example, functions as a sniper rifle, but has the useful property of allowing the player to retrieve the spears from fallen enemies and the walls/floor, etc. However, like most sniper rifles in other games, the amount of ammo that can be carried is extremely limited and the firing rate is quite slow.
  • Health kits: Health kits are used to replenish health. Only a limited number may be carried at any given time.
  • EVE hypos: EVE hypos are used to replenish one’s EVE, which is like mana or magicka and is used to cast plasmids. Only a limited number may be carried at any given time.
  • Ammo: Each gun has multiple types of ammo, but the player can only carry a limited amount each time.
  • Cash: Money is used to buy ammo and other items.

2.6 Conflicts


2.6.1 Rescuing versus Harvesting

As mentioned before, there is an immediate reward versus delayed benefit mechanic at work in this conflict. Harvesting, although morally questionable, gives the player a larger reward initially. However, for rescuing the Little Sisters the player receives extra ADAM and plasmids later. Thus the player could look at this simply as an economic choice, but personally, I remember seeing the struggle of a Little Sister while I harvested her the first time I played Bioshock, and after that I created a new game file just so that I would not have that ”virtual” crime on my conscious.
2.6.2 Revenge versus Forgiveness

While playing through certain levels, three different NPCs will either taunt the player, or send the player on dangerous missions before helping. At the end of the level, the player is faced with the choice of killing them or sparing them. Sparing them allows the player to achieve a ”positive” game ending, and for one of the NPCs at least, gives the player robot allies at specific points in the game.

2.7 Boundaries


2.7.1 Map

Each map may be freely explored, but they are arranged in a linear order and there is no backtracking allowed.
2.7.2 NPCs

Almost every NPC in the game is an enemy and must be killed or avoided. The only exceptions are the Little Sisters.

2.8 Outcomes


The game has limited outcomes. Depending on how you treat the Little Sisters and how you treat three key NPCs throughout the game, your Little Sister, Eleanor, will either forgive or try to exact revenge on the woman who kidnapped her.

3 Dramatic Elements


Like the first Bioshock and its successor, Bioshock Infinite, Bioshock II features a strong, well-written and voice-acted story. As a Big Daddy, the player has been genetically and experimentally modified to be bigger and stronger than a normal person. You are also bonded to a Little Sister, whose death will break the bond and cause you to drop into a coma.
The action of the story takes place entirely in and around the mid-ocean underwater city of Rapture, a Libertarian haven created by Andrew Ryan. As learned from the first game, and during play of the second, Rapture was supposed to be a utopia for free thinkers, artists, business-people and scientists who wanted to live free of the restrictions of conventional society. However, soon classes emerged, gangs appeared, and scientists created plasmids, genetic modifications which gave powers like telekinesis, the ability to summon fire, and freeze or electrocute things.
Little Sisters were introduced to harvest ADAM, a resource needed to create plasmids, and the Big Daddies were created to control the them. Chaos soon ensued, with most citizens going crazy and selfishly trying to get as much ADAM as they could.
Whereas the first game primarily explores the breakdown of a Libertarian society, the second game introduces the character of Sophia Lamb, a Collectivist. This allows the game to explore the concepts of collectivism. However, from a game mechanics point of view, there are no enemy types that could be called collective, for instance, an enemy that grabs onto the player and is killed in order to allow other enemies to damage the player.

3.1 Characters


The player receives messages from Eleanor Lamb throughout the game, and is in frequent passive radio contact with Sophia Lamb, Augustus Sinclair, Holloway, Poole, and Alexander, which copies the first game’s use of radios to provide context and mission goals. The player may also find notes scrawled on walls, audiotapes, and other indirect forms of communication from other characters.

3.2 Story


Your Little Sister has been kidnapped, and you must rescue her. The rest of the plot revolves around the player encountering multiple obstacles on the way to rescuing her.

4 Dynamic Elements


4.1 Hacking


Hacking allows the player to save money and to turn the security elements of the environment to the player’s advantage.

4.2 Plasmid/Weapon Interactions


The Inferno and Electrocute plasmids cause enemies to become shocked or set on fire, and thus create opportunities for the player to attack them with impunity. The Freeze plasmid turns enemies into blocks of ice, which can be destroyed if enough damage is dealt.

4.3 Plasmid/Environment Interactions


The Inferno and Electrocute plasmids allow many interactions with the environment. Oil spills are flammable, and any pool of water will kill any enemy standing in it if electrocuted. These interactions encourage player awareness of the environment and tactical planning of battles.

5 Conclusion


Bioshock II enhances many gameplay features from the previous game and gives the player an interesting second look at the world of Rapture.

5.1 Potent Elements


The weapons and plasmids interact with the environment during combat, and exploration of the environment allows the player to freely discover as much or as little of the story and secrets that Rapture has to offer. Besides the pure gameplay, the story is quite interesting and provides a few challenging moral questions.

5.2 Areas for Improvement


Although the UI in itself is quite helpful, I played the game on PC using a controller, which is something that either didn’t exist when the game was released, or was something which the developers never thought of. Consequently, all the user tips and explanations for how to do things were for the mouse and keyboard, and I had to discover what button / button combination did what. Especially in a game where resources are limited, this lead to a lot of wasted ammo, health kits, EVE hypos, etc, until I figured out the controls. New abilities are introduced throughout the game that make use of these unexplained controls.
As mentioned before, the fights against the Big Sisters cannot be avoided or skipped, and this can lead to a cycle where the player has less and less ammo, health kits, and EVO hypos to aid in defeating it.

Multiple Characters and Basic Needs

hey all,

Another busy and dramatic week at work. Three more days of work til winter vacation. Just a quick demo showing multiple characters and displaying their needs and body state. The next step is decision making.




I've setup a new channel on Youtube where you can find my video game videos.
Cheers,

Friday, December 16, 2016

Busy Week

hey all,

Really busy week at work and outside of it as well. Outside, I've been doing research on Voronoi diagrams, how to simulate diffusion, and I've also done a complete revamping of my code for needs. Instead of having Physical Needs and Emotional Needs treated separately, I've decided to make a BaseNeed class, and then have the NPCs have a Needs class which sets them up, initializes them, and takes care of keeping them up to date. The main reason for this is that when I started to write my code for updating mood based on Physical and Emotional Needs, I needed to write some extra functions and variables for dealing with their contributions separately, and then combining them.

More to come.




using UnityEngine;
using System.Collections;
using Gamelogic.Extensions.Algorithms;

public class BaseNeed:IBaseNeed
{
 [Range(0, 100)]
 float severity;
 float maxTime;
 MeetNeedEvent typicalMNE;
 //research the actual rate at which each physical need must be met
 //water: about 250ml every 3 hours, for a total of 2,000ml per day. more could cause problems. but depends on exercise level and temperature.
 //food: 2,000~3,000kC every day, spread between 2~5 meals. also depends on exercise
 //rest: between 6~9 hours per day. 
 //sex:??? once/twice per week?
 //cleanliness: about once per day, depending on exercise
 //comfort: ???increases if:
 //                          standing
 //                          working
 //                          sitting on ground
 //                          
 //
 //
 //public float changeRate;
 NeedType needType;
 ResponseCurveFloat curve;
 float timeSinceMet;
 bool isBeingMet;

 //used for determining the effect during decision making
 float multiplier;
 //public PhysicalNeedType type;

 #region Getters and Setters


 public NeedType Type
 {
  get { return needType; }
  protected set {; }
 }

 public float Severity
 {
  get {return severity; }
  protected set {; }
 }

 public bool IsBeingMet
 {
  get { return isBeingMet; }
  protected set {; }
 }

 public float Multiplier
 {
  get { return multiplier; }
  protected set {; }
 }

 //this is probably not needed, as the response curve is only ever referenced internally
 public ResponseCurveFloat Curve
 {
  get { return curve; }
  protected set {; }
 }


 #endregion

 public BaseNeed(NeedType ty, float sev, ResponseCurveFloat rc, float maxT, MeetNeedEvent mne ,float mult)
 {
  severity = sev;
  curve = rc;
  multiplier = mult;
  isBeingMet = false;
  timeSinceMet = 0f;
  typicalMNE = mne;
  maxTime = maxT;
  needType = ty;
 }

 // Use this for initialization
 void Start ()
 {
 
 }
 
 // Update is called once per frame
 void Update ()
 {
 
 }

 public void IncreaseNeed(float timePassed)
 {
  if (!isBeingMet)
  {
   timeSinceMet += timePassed;
   severity = curve[timeSinceMet];
   //Debug.Log("Need increased to " + severity.ToString());
  }
 }

 public IEnumerator MeetNeed(MeetNeedEvent mne=new MeetNeedEvent())
 {
  //this is because the default parameter must be a constant at compile time
  //so if a value is not passed in, use the typical MeetNeedEvent for this need
  if (mne.eventLength <= 0)
  {
   mne = typicalMNE;
  }
  isBeingMet = true;
  float t = 0f;
  //Debug.Log("meeting need");
  //Debug.Log("mne length is" +mne.eventLength);
  //Debug.Log("typical mne length is" + typicalMNE.eventLength);
  while (t < mne.eventLength)
  {
   t += Time.deltaTime;
   //Debug.Log("value of t in MeetNeed is " + t);
   //Debug.Log("change in severity is " + (t / mne.eventLength) * mne.potency);
   //this value needs to be clamped!!!
   severity = Mathf.Clamp(severity - ((t / mne.eventLength) * mne.potency), 0f, 100f);
   //severity -= (t / mne.eventLength) * mne.potency;
   yield return null;
  }
  //Debug.Log("This should only be called when finished");
  isBeingMet = false;
  //Debug.Log("isBeingMet is now " + isBeingMet.ToString());
  timeSinceMet = Mathf.Clamp(maxTime-(maxTime*mne.potency/100f),0f,maxTime);
  //Debug.Log("Time since met is " + timeSinceMet);
 }
}

public struct MeetNeedEvent
{
 public float eventLength;
 [Range(0,100)]
 public float potency;

 public MeetNeedEvent(float el=-1f, float p =-100f)
 {
  eventLength = el;
  potency = p;
 }
}

public enum NeedType
{
 Food,
 Hydration,
 Rest,
 Sex,
 Comfort,
 Cleanliness,
 Shelter,
 Intimacy,
 Fun,
 Safety,
 Respect,
 MAX
}

public interface IBaseNeed
{
 //(get) accessor functions for:
 //severity
 //type
 NeedType Type
 { get; }
 //Multiplier
 float Multiplier
 { get; }

}

using UnityEngine;
using System;
using Gamelogic.Extensions.Algorithms;
using System.Collections.Generic;

public class Needs : MonoBehaviour
{
 const int numberOfNeeds = (int)NeedType.MAX;
 ////this holds the response curve for how each need will affect mood
 ////does this really belong here or should it go in mood?
 List < ResponseCurveFloat > moodResponseCurve = new List < ResponseCurveFloat > ();



 BaseNeed[] needs = new BaseNeed[numberOfNeeds];

 NPCState npcState;



 public delegate void NeedStateChangeHandler(object source, NeedEventArgs args);//set up delegate
 public event NeedStateChangeHandler NeedStateChanged;//define event based on event


 #region Getters and Setters

 public int NumberOfNeeds
 {
  get { return numberOfNeeds; }
  protected set { }
 }

 public ResponseCurveFloat MoodResponse(int i)
 {
  return moodResponseCurve[i];
 }

 public float Hunger
 {
  get { return needs[(int)NeedType.Food].Severity; }
  protected set { }
 }

 public float Tiredness
 {
  get { return needs[(int)NeedType.Rest].Severity; }
  protected set { }
 }

 public float Thirst
 {
  get { return needs[(int)NeedType.Hydration].Severity; }
  protected set { }
 }

 public float Lust
 {
  get { return needs[(int)NeedType.Sex].Severity; }
  protected set { }
 }

 public float Comfort
 {
  get { return needs[(int)NeedType.Comfort].Severity; }
  protected set { }
 }

 public float Cleanliness
 {
  get { return needs[(int)NeedType.Cleanliness].Severity; }
  protected set { }
 }

 public float Shelter
 {
  get { return needs[(int)NeedType.Shelter].Severity; }
  protected set { }
 }

 public float Intimacy
 {
  get { return needs[(int)NeedType.Intimacy].Severity; }
  protected set {; }
 }


 public float Fun
 {
  get { return needs[(int)NeedType.Fun].Severity; }
  protected set {; }
 }

 public float Safety
 {
  get { return needs[(int)NeedType.Safety].Severity; }
  protected set {; }
 }

 public float Respect
 {
  get { return needs[(int)NeedType.Respect].Severity; }
  protected set {; }
 }

 #endregion

 //the steepness, emults, and xMidpoints need to be adjusted for each emotional need
 void SetupNeeds()
 {

  double[] steepnesses = new double[numberOfNeeds] { 0.2f, 0.4f, 0.4f, 0.1f, 0.4f, 0.1f, 0.2f, 0.2f, 0.4f, 0.4f, 0.1f };
  double[] eMults = new double[numberOfNeeds] { 1f, 1f, 10f, 1f, 10f, 0.1f , 1f , 1f, 1f, 10f, 1f };
  double[] xMidpoints = new double[numberOfNeeds] { 24, 12, 16, 84, 10, 72, 24, 24, 12, 16, 84 };
  double yMax = 100;
  double yMaxforCalc = 99.99999f;

  for (int i = 0; i < needs.Length; i++)
  {
   //Debug.Log("need " + ((PhysicalNeedType)i).ToString());

   double maxX = -((System.Math.Log((yMax / yMaxforCalc) - 1) - System.Math.Log(eMults[i])) / steepnesses[i]) - xMidpoints[i];
   //Debug.Log("double max x is " + maxX);
   //Debug.Log("float max x is " + maxX);
   double dx = maxX / 10f;
   List < float > xVals = new List < float > ();
   List < float > yVals = new List < float > (); //use this as the input for the mood response curve
   float yv;
   float myv;
   List < float > moodYVals = new List < float > (); // use this as the output for the mood response curve
                //Debug.Log("need " + ((PhysicalNeedType)i).ToString());
   for (int xs = 0; xs < 10; xs++)
   {
    xVals.Add((float)(xs * dx));
    //Debug.Log(xs * dx);
    if (xs == 0)
    {
     yv = 0f;
    }
    else if (xs == 9)
    {
     yv = (float)yMax;
    }
    else
    {
     yv = (float)(yMax / (1 + eMults[i] * (System.Math.Pow(System.Math.E, -steepnesses[i] * ((xs * dx) - xMidpoints[i])))));
    }


    yVals.Add(yv);
    //Debug.Log(yMax / (1 + eMults[i] * (System.Math.Pow(System.Math.E, -steepnesses[i] * ((xs * dx) - xMidpoints[i])))));
    if (yv > = 50f)
    {
     //gives a penatly to mood
     //make sure to clamp this value
     myv = Mathf.Clamp(-(Mathf.Pow(yv - 50f, 3) / 1000f), -100, 100);
    }
    else
    {
     //gives a bonus to mood
     //make sure to clamp this value
     myv = Mathf.Clamp(-(Mathf.Pow(yv - 50f, 3) / 50000f) + 5f, -100, 100);
     //Debug.Log(-(Mathf.Pow(yv - 50f, 3) / 50000f) + 5f);
    }
    moodYVals.Add(myv);

   }

   moodResponseCurve.Add(new ResponseCurveFloat(yVals, moodYVals));

   float time = 10f;
   float potency = 100f;
   MeetNeedEvent mne = new MeetNeedEvent(time, potency);
   needs[i] = new BaseNeed((NeedType)i, 0f, new ResponseCurveFloat(xVals, yVals), (float)maxX, mne, 100f);
   //needs[i] = new PhysicalNeed(0f, 1f, 1000f, (PhysicalNeedType)i);
  }
  Debug.Log("Needs setup");
 }

 public void ChangeNeedState(NeedType ty, float amount)
 {
  switch (ty)
  {
   case NeedType.Food:
    //Debug.Log("Trying to increase food need");
    needs[(int)NeedType.Food].IncreaseNeed(amount);
    break;
   case NeedType.Hydration:
    //Debug.Log("Trying to increase hydration need");
    needs[(int)NeedType.Hydration].IncreaseNeed(amount);
    break;
   case NeedType.Rest:
    //Debug.Log("Trying to increase rest need");
    needs[(int)NeedType.Rest].IncreaseNeed(amount);
    break;
   case NeedType.Sex:
    //Debug.Log("Trying to increase sex need");
    needs[(int)NeedType.Sex].IncreaseNeed(amount);
    break;
   case NeedType.Comfort:
    //Debug.Log("Trying to increase comfort need");
    needs[(int)NeedType.Comfort].IncreaseNeed(amount);
    break;
   case NeedType.Cleanliness:
    //Debug.Log("Trying to increase cleanliness need");
    needs[(int)NeedType.Cleanliness].IncreaseNeed(amount);
    break;
   case NeedType.Shelter:
    needs[(int)NeedType.Shelter].IncreaseNeed(amount);
    break;
   case NeedType.Fun:
    needs[(int)NeedType.Fun].IncreaseNeed(amount);
    break;
   case NeedType.Intimacy:
    needs[(int)NeedType.Intimacy].IncreaseNeed(amount);
    break;
   case NeedType.Respect:
    needs[(int)NeedType.Respect].IncreaseNeed(amount);
    break;
   case NeedType.Safety:
    needs[(int)NeedType.Safety].IncreaseNeed(amount);
    break;
   default:
    break;
  }
  OnNeedStateChanged();
 }

 protected void OnNeedStateChanged()
 {
  if (NeedStateChanged != null)
  {
   //treating it like a function
   //this is used to notify subscribers to this event
   NeedEventArgs n = new NeedEventArgs();
   n.need = this;
   NeedStateChanged(this, n);
   //Debug.Log("Physical State changed");
  }
 }

 void OnNPCStateChanged(object source, StateEventArgs n)
 {
  switch (n.state.Body)
  {
   case BodyState.Resting:
    ChangeNeedState(NeedType.Cleanliness, Time.deltaTime);
    if (!needs[(int)NeedType.Rest].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Rest].MeetNeed());
    }
    ChangeNeedState(NeedType.Food, Time.deltaTime);
    ChangeNeedState(NeedType.Hydration, Time.deltaTime);
    if (!needs[(int)NeedType.Comfort].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Comfort].MeetNeed());
    }
    ChangeNeedState(NeedType.Sex, Time.deltaTime);
    break;
   case BodyState.Eating:
    ChangeNeedState(NeedType.Cleanliness, Time.deltaTime);
    if (!needs[(int)NeedType.Food].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Food].MeetNeed());
    }
    ChangeNeedState(NeedType.Rest, Time.deltaTime);
    ChangeNeedState(NeedType.Hydration, Time.deltaTime);
    ChangeNeedState(NeedType.Comfort, Time.deltaTime);
    ChangeNeedState(NeedType.Sex, Time.deltaTime);
    break;
   case BodyState.Drinking:
    ChangeNeedState(NeedType.Cleanliness, Time.deltaTime);
    if (!needs[(int)NeedType.Hydration].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Hydration].MeetNeed());
    }

    ChangeNeedState(NeedType.Rest, Time.deltaTime);
    ChangeNeedState(NeedType.Food, Time.deltaTime);
    ChangeNeedState(NeedType.Comfort, Time.deltaTime);
    ChangeNeedState(NeedType.Sex, Time.deltaTime);
    break;
   case BodyState.Sexing:
    ChangeNeedState(NeedType.Cleanliness, Time.deltaTime);
    if (!needs[(int)NeedType.Sex].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Sex].MeetNeed());
    }
    if (!needs[(int)NeedType.Comfort].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Comfort].MeetNeed());
    }
    ChangeNeedState(NeedType.Food, Time.deltaTime);
    ChangeNeedState(NeedType.Hydration, Time.deltaTime);
    ChangeNeedState(NeedType.Rest, Time.deltaTime);
    break;
   case BodyState.Bathing:
    if (!needs[(int)NeedType.Cleanliness].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Cleanliness].MeetNeed());
    }
    if (!needs[(int)NeedType.Comfort].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Comfort].MeetNeed());
    }
    ChangeNeedState(NeedType.Rest, Time.deltaTime);
    ChangeNeedState(NeedType.Food, Time.deltaTime);
    ChangeNeedState(NeedType.Hydration, Time.deltaTime);
    ChangeNeedState(NeedType.Sex, Time.deltaTime);
    break;
   case BodyState.Default:
    ChangeNeedState(NeedType.Rest, Time.deltaTime);
    ChangeNeedState(NeedType.Food, Time.deltaTime);
    ChangeNeedState(NeedType.Hydration, Time.deltaTime);
    ChangeNeedState(NeedType.Sex, Time.deltaTime);
    ChangeNeedState(NeedType.Comfort, Time.deltaTime);
    ChangeNeedState(NeedType.Cleanliness, Time.deltaTime);
    break;
   default:
    break;
  }

  switch (n.state.Feeling)
  {
   case EmotionalStateType.Socializing:
    if (!needs[(int)NeedType.Intimacy].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Intimacy].MeetNeed());
    }
    if (!needs[(int)NeedType.Fun].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Fun].MeetNeed());
    }
    ChangeNeedState(NeedType.Respect, Time.deltaTime);
    break;
   case EmotionalStateType.Playing:
    if (!needs[(int)NeedType.Fun].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Fun].MeetNeed());
    }
    ChangeNeedState(NeedType.Intimacy, Time.deltaTime);
    ChangeNeedState(NeedType.Respect, Time.deltaTime);
    break;
   case EmotionalStateType.Working:
    ChangeNeedState(NeedType.Fun, Time.deltaTime);
    break;
   case EmotionalStateType.Arguing:
    if (!needs[(int)NeedType.Intimacy].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Intimacy].MeetNeed());
    }
    ChangeNeedState(NeedType.Fun, Time.deltaTime);
    break;
   case EmotionalStateType.BeingRespected:
    if (!needs[(int)NeedType.Respect].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Respect].MeetNeed());
    }
    if (!needs[(int)NeedType.Intimacy].IsBeingMet)
    {
     StartCoroutine(needs[(int)NeedType.Intimacy].MeetNeed());
    }
    ChangeNeedState(NeedType.Fun, Time.deltaTime);
    break;
   case EmotionalStateType.Default:
    if (n.state.IsAlone)
    {
     ChangeNeedState(NeedType.Intimacy, Time.deltaTime);
     ChangeNeedState(NeedType.Respect, Time.deltaTime);
    }
    ChangeNeedState(NeedType.Fun, Time.deltaTime);
    
    //ChangeNeedState(NeedType.Safety, Time.deltaTime);
    break;
   default:
    break;
  }
  OnNeedStateChanged();
 }


 // Use this for initialization
 void Start()
 {
  SetupNeeds();
  npcState = FindObjectOfType < NPCState > ();
  npcState.StateChanged += OnNPCStateChanged;
 }

 // Update is called once per frame
 void Update()
 {

 }
}





public class NeedEventArgs : EventArgs
{
 public Needs need { get; set; }
}


Thursday, December 8, 2016

UI Analysis

hey all,

A little UI analysis from Total War: Warhammer this time. I've only put about 20 hours into this game over the last several weeks, but I have noticed some really amazing and (IMHO) really crappy UI design. On the plus side, there is the map UI. You can see a city and an army icon in the image below. The army is marked by the humanoid figure and the the flag, while the city is the group of buildings partially blocked behind him. The yellow outlines show how far the unit can move during a turn. Everything the player might want to know is shown clearly, or can be displayed with a single click: clicking on the city would display the upgrades it has and that are available, while clicking on the army would show the general in charge and the units, their health and experience levels.


 Should you wish to know more about the general, you can bring up the screen below. This shows the general's stats and battle bonuses and campaign bonuses to the far left. The center panel shows the items, location, traits, and followers. While functional, the inventory on the top half does not live up to any RPG inventory standard. Skyrim, Mount & and Blade: Warband, hell, even Deus Ex from 16 years ago is better looking. Functionally, the drop down menus do a good job of showing what item the general has equipped, either other items are available for the slot, and who has other equivalent items.


Should you wish to invest skill points in abilities, the player can use the menu below. Again, while functional and basically clear, please notice the arrow. I played the game for over 40 turns, that's about 12 hours, before I noticed those little spheres. It turns out that when they are uncolored you have not or cannot invest in the skill. The number of spheres shows the number of times you can invest in that skill. Maybe I am just not observant, but any pretty critical UI element that the player only discovers after 12 hours is not doing its job. Increasing the size of them, making them flash, using highlighted numbers, or breaking each button into sections which progressively become filled in would be improvements.


The next two shots show parts of the UI for generals and cities. The arrows point to elements that allow the player to view the next general or city. Similarly to the spheres for skills, I discovered these after a few hours of play. They blend in a little too well with the background and look so much like decorative elements that they are easy to ignore.



Back on the plus side, there are a large number of events: wars, diplomatic changes, construction project completion, research completion, and generals leveling up. Below the map, there is an event panel list which displays these events. By clicking on them, the player can get more information, and even go to the location of the event.


Last one. When you select a general from the map, you get this panel in the lower left corner. It shows a portrait, the current level and how much progress to the next level, the items currently equipped, and the general's stance. The last is in the lower right corner, and similar to other elements in the UI, I did not discover this until about 30 hours into the game. Granted, it has been quite some time since I played a strategy game, but the basic tutorials are really lacking a few elements.

Cheers,

Tuesday, December 6, 2016

Monday, December 5, 2016

Back to the Basics (Needs)

hey all,

I've been refactoring my code for needs over the last few days, and here are some of the changes I've made.


using UnityEngine;
using System.Collections;
using Gamelogic.Extensions.Algorithms;

public class Need
{
 [Range(0, 100)]
 public float severity;
 float maxTime;
 MeetNeedEvent typicalMNE;
 //public float changeRate;
 public ResponseCurveFloat curve;
 float timeSinceMet;
 public bool isBeingMet;

 //used for determining the effect during decision making
 public float multiplier;


These are the variables that my Need class contains. The severity just tracks the severity of the need, which can only be from 0 to a maximum of 100. For physical needs such as food and water, I'm planning on causing death to occur when it reaches the maximum. maxTime was the most difficult. If you recall from my previous post, I am using variations on the equation


to calculate how severe a need should be after x time has passed. The problem is that this is a logistic equation, and it has a horizontal asymptote at max_y, so you cannot just use




to try and find the x value when y = max_y, because that value does not exist. At the moment, I'm using a y value of 99.999999 and it seems to be working OK, although I do get some floating point errors every now and then.

In any case, I use the first equation to set up the response curve in the PhysicalNeeds and EmotionalNeeds classes, and also create a default MeedNeedsEvent.
 public Need(float sev, ResponseCurveFloat rc, float maxT, MeetNeedEvent mne ,float mult)
 {
  severity = sev;
  curve = rc;
  multiplier = mult;
  isBeingMet = false;
  timeSinceMet = 0f;
  typicalMNE = mne;
  maxTime = maxT;
 }

 // Use this for initialization
 void Start ()
 {
 
 }
 
 // Update is called once per frame
 void Update ()
 {
 
 }

 public void IncreaseNeed(float timePassed)
 {
  if (!isBeingMet)
  {
   timeSinceMet += timePassed;
   severity = curve[timeSinceMet];
   
  }
 }

This is another change from before. Instead of having those ugly incremental changes in an Update function, I'm now calling a coroutine that just ticks along by itself until the MeetNeedEvent is finished. I'm actually thinking that having the IncreaseNeed function be a coroutine might be a much better idea as well, and just use body states in the PhysicalNeeds class to start and stop the appropriate coroutines.
 public IEnumerator MeetNeed(MeetNeedEvent mne=new MeetNeedEvent())
 {
  //this is because the default parameter must be a constant at compile time
  //so if a value is not passed in, use the typical MeetNeedEvent for this need
  if (mne.eventLength <= 0)
  {
   mne = typicalMNE;
  }
  isBeingMet = true;
  float t = 0f;
  while (t < mne.eventLength)
  {
   t += Time.deltaTime;
   //this value needs to be clamped!!!
   severity = Mathf.Clamp(severity - (t / mne.eventLength) * mne.potency, 0f, 100f);
   yield return null;
  }
  isBeingMet = false;
  timeSinceMet = maxTime-(maxTime/100f*mne.potency);
 }
}


The point of having maxTime subtract a fraction of itself is that the potency of the event should affect the level of the need afterwards. If I have a snack, my hunger need will not be as satisfied as if I had had a hearty bowl of sweet and sour pork.

public struct MeetNeedEvent
{
 public float eventLength;
 [Range(0,100)]
 public float potency;

 public MeetNeedEvent(float el=-1f, float p =-100f)
 {
  eventLength = el;
  potency = p;
 }
}


So that's my base Needs class. PhysicalNeeds and EmotionalNeeds inherit from this class. I hope that I can start implementing how these needs affect mood.The current AI model is something like this:

Thursday, December 1, 2016

Ancient Water, Revamped and Refined

hey all,

I've gone through and done a bit of play testing for my Ancient Water game. As you can see from the picture, I've replaced the water slips and crop slips with colored glass beads. These pieces get moved around a lot, and the paper slips were just too hard to count quickly and move around smoothly, so they are gone. Also, I made some new smaller boxes that fit the size of the river much better.

Mechanically, here are the current rules.

  1. Setup
    • The board starts with the empty boxes on the river.
    • The player roles two six-sided dice to determine how much water goes in the top most box.
    • The player then decides how to distribute their population. The player starts with four people who they may distribute however they want. (This is for single player play. For two player or multiplayer, different colored pieces will be needed for each player. Plus an extra roll of the dice to figure out which player goes first, second, third, etc. Only one player may occupy a region at a time.)
  2. Each turn, there are seven actions that take place.
    1. Boxes are cycled down one, and the bottom most box is placed at the top. Roll dice to determine how much water goes in the top river box.
    2. If the player has four people in one area, the player may build an irrigation project. The next level of irrigation requires six people, and the final level nine people.
    3. Both six-sided dice are rolled to see if any one dies. If the total is a 3 or 4, someone dies.
    4. The player may decide to move their population around, but must have at least one person in an area in order to collect water and grow crops.
    5. Water is collected from the river box adjacent to the player's area. Without irrigation, only one unit of water may be collected, but each level of irrigation adds one to this:
      1. Level 1: two units of water
      2. Level 2: three units of water
      3. Level 3: four units of water
    6. Every two units of water collected may be converted in one crop. The people can survive two turns without crops, but if they do not have any crops after two complete turns, they will die.
    7. Lastly, every two units of crops can be converted into one person. It requires one crop to maintain between one to four people, so if the population increases to five, two crops must be saved.
That's it. I've been thinking of creating a short story, something like "You are the chief of the _____ people and it is your job to help them stay alive..." just to motivate the action. There are still no endgame conditions, but if the population reaches zero, of course the game is over. I still need to see about how long it takes to reach a population of ten, but I think being the first player to reach ten or 15 should be the winner.