Jump to content

  • Log In with Google      Sign In   
  • Create Account

C# Workshop - Some reedits.



C# Workshop – Project 2: Random Character Generator - Solutions

Posted by , in C# Workshop 27 October 2012 - - - - - - · 1,003 views

Post Full solutions here.


C# Workshop – Project 2: Random Character Generator - Questions

Posted by , in C# Workshop 27 October 2012 - - - - - - · 1,028 views

Ask questions here. No full solutions!


C# Workshop – Project 2: Random Character Generator

Posted by , in C# Workshop 27 October 2012 - - - - - - · 1,372 views

Introduction
Welcome to the second project of the C# Workshop. This project is designed to give you an opportunity to challenge your understanding of both the material we’ve already covered, as well as the material we will be covering over the next two weeks. For those with previous programming experience, this project won’t be overly difficult, but it will give you an opportunity to test your understanding of the programming syntax provided in C#. For those with no previous programming experience, this project will be a challenge. Not because it’s technically difficult or overly complex, but because 90% of being an adequate programmer is your ability to solve problems. Being able to logically break a project description down into discrete, manageable components is one of the most valuable skills any programmer can have. Unfortunately, this is not something that can be taught, it’s something that can only be learned with practice and the development of an analytic mind.

Topics Covered
As the second project is designed to correspond with the first 6 weeks of the workshop, it will test and exercise your understanding of the following topics:
  • The System.Console Class
  • Strings and Primitive Types
  • Expressions, Selection, Iteration, and Arrays
  • Classes, Structs, Methods, Fields, and Objects
  • Exception Handling and Properties
  • Inheritance and Polymorphism
Background Information
Long before there were video games man-kind found ways of allowing themselves to be more than they are. Through creative writing, board games, radio shows, and movies, people of all walks of life who share a common interest in the mysterious and the magnificent have put themselves in the roles of loyal knight, devious cutpurse, and even the feared magician. In modern times, those of us who are daring enough (read geeky enough) can bring to life our imaginations in the form of Role-Playing Games. Whether the game is played with Pen and Paper, over a web forum, or via an interactive video game, the basic ideas are the same.

Generally speaking, the primary focus of a Role-Playing Game (RPG) is around that of the player’s avatar or character. Depending on the genre or rule-system, it’s not uncommon for these characters to be of different races, with different professions, and each with their own unique blend of skills and abilities. As a player explores their world through the eyes of their character they amass fame, wealth, and experience – all of which makes them more powerful as time goes on. And, while there are a number of well-known systems dating back over 30 years or more, the most common system for RPG’s is the Dungeons and Dragons system. In its most recent edition (DnD 3.5ed) the basic rule system is based around rolling dice ranging from 3-sided to 100-sided (what they call % dice). The most frequently used die, however, is the 20-sided die, or the d20. This, is why it’s called the d20 Gaming System.

In the d20 system every player makes a character and the characters created usually have the following attributes: Name, Class & Level, Race, Size, Age, Gender, Height, Weight, Eye Color, Hair Color, Ability Scores, Hitpoints, Armor Class, Money, Saving Throws, Attack Bonuses, Equipment, Skills, Feats (optional), Abilities (optional), and Spells (optional). This is by no means an exhaustive list, but it gives you the basic idea. Some of these, such as Race, Class, Ability Scores, Equipment, Skills, Feats, Abilities, and Spells – are really just a collection of other attributes that helps to further define what a character is possible of doing, what their raw scores are in combat, and what they’re wearing about their person or in their bag pack. Once a character has been created the player can take him through enchanted forests, searing deserts, and dangerous dungeons. But…it all must begin with the creation of a character.

Feature Requirements / Use Cases
For this project we will be stepping away from the random maze generator for a short time, and instead creating a random character generator. The character generator will create characters with stats, skills, and abilities roughly equivalent to that which can be found in Dungeons & Dragons 3.5 Edition. And since D&D is a trademark/copyright of Wizards of the Coast, let me say that all content contained herein is subject to the Open Gaming License, and while I am encouraging people to implement a character generator and/or Interactive Game, I do NOT encourage them to distribute the software either for Free or for Profit. Such actions would likely be against WotC’s license agreement, and might get you sued. This exercise is strictly for learning purposes.

Also, to avoid duplicating a large amount of information already in print, I will instead provide links to documents on the Wizards of The Coast website which will contain the relevant information. Before I go further let me say Much of this project description is optional. I’ve tried to add in all the relevant data for a character in D&D 3.5ed, however only implement that which you feel comfortable with. I’ve specifically stated in the clarification sections below which are expressly optional. But, as I said, feel free to make all or none of this project description optional. Where the first project was technically simple, but logically difficult, this one is the exact opposite. This one is logically simple, but will require a large amount of code to develop any of the more optional or difficult character fields. Many of the earlier ones will only require 30 minutes to add, while some of the latter properties and fields may require a few days to add. Get as much done as you can, but don’t hesitate to ask questions about the more difficult stuff. CHALLENGE YOURSELF!

1. When the user first launches the program it will show them ASCII art similar to the screenshot at the very top of the project description. It need not be that exact image as any appropriate image will do. Just search the internet for “Dragon ASCII Art” and you will find quite a bit to work with. Decide which image you enjoy most, and make the character generator display the artwork.

1a. Beneath the displayed ASCII art it should immediately begin the process of creating a character. There are 5 pieces of information which the user will be required to input into the generator. All the rest will be randomly created. The first item to be input is a Name. A name can really be any name the character likes, however it must follow a few rules. First, the name can be no longer than 25 characters. Second, the name may only consist of letters, apostrophes (‘), and hyphens (-). Finally, if multiple hyphens, apostrophes, or spaces are entered in a row or separated by other spaces, hyphens or apostrophes, it should strip out the duplicates. This allows for names such as Jachom Death-Bringer, or Rand Al’Thor, but not names such as “The 133t 0n3”.

1b. If either the name is too long or contains invalid characters, the generator should notify the user of the error, and then request the name again. This should continue until a valid name is entered.

2.After the user successfully enters their character’s name, they will be prompted for the second piece of information required by the user – The character’s Gender. The user should be shown the available options which are either “Male” or “Female” – Case Insensitive.

2b. Entering a gender other than those provided will be considered invalid and the user will be repeatedly asked to enter the gender again until they enter a valid gender.

3. After the user successfully enters their character’s gender, they will be prompted for the third piece of information required by the user – The character’s Race. The user should be presented a list, perhaps in two or three columns, listing their available choices and they must pick which one they want to play by typing in the (case-insensitive) string.

3b. Entering a race other than those provided will be considered invalid and the user will be repeatedly asked to enter the race again until they enter a valid race.

4. After the user successfully selects one of the allowable races, they must then select their character’s Class. As with the races, a character should be presented a list of options – perhaps in two or three columns, and they will be repeatedly asked for a class until they correctly type in one from the list.

5. After the user successfully selects the class they wish to create, they must pick a level. Based on the non-epic rules of play, a character’s level must be an integer in the range of 1-20. Entering any non-numeric value, or entering a value which is not in the range of 1-20 will result in the user being notified of their mistake, and asked once again for their character’s level.

6. At this point enough information has been gathered from the user that a randomly generated character can be created. Do so, and then display to the user the information about his character. This should include all the information listed above, in any format desired by the programmer.

7. Finally, after displaying the character info, you should prompt the user to determine whether or not they would like to create another character. Available answers should be ‘yes’ ‘y’ ‘no’ and ‘n’. Obviously ‘yes’ and ‘y’ should perform the same action, while ‘no’ and ‘n’ also perform the same action. Any other response should let the user know you didn’t understand their response, and then repeat the question.

7a. If they answered with either ‘no’ or ‘n’, terminate execution of the application. If they say ‘yes’ or ‘y’, repeat the process outlined above, beginning with asking them to input a character’s name (There’s no reason to display the ASCII art again).

Creating the Character
Upon reaching use case 6 listed above, the generator should have enough information to generate a character. Generating a character consists of filling in all of the fields of the character object, including any subclasses which may be necessary. This can often times be more difficult than it seems, as data such as the Race or Class may effect more than just one field. For example, selecting “Dwarf” as the race, may not only identify this character as a Dwarf but it may have the following effects as well:
  • Dwarves receive +2 to their Constitution Score, while receiving -2 to their Charisma Score.
  • Dwarves are of Medium Size Dwarves receive a +2 racial skill bonus to Search Checks.
  • Dwarves receive a +2 racial skill bonus to Appraise checks
  • Dwarves may use Dwarven Waraxes and Dwarven Urgroshes without requiring the Exotic Weapon Feat.
The above is a small list of some of the racial abilities granted for Dwarves. When implementing classes and races, feel free to apply the effects of only that which you desire. But, you should at the very least apply any modifications to the 6 ability scores, note the race’s size, and any modifications to skill checks. For skill checks such as the Dwarven Search and Appraise which is limited to certain circumstances (such as when working with stone) treat it as though the bonus skill check is always in effect. In other words, there’s no reason to special case it to only stone objects – unless you want to. The remaining part of this Project specification will be in evaluating the specific properties of the character class, and what information should be taken into account. Ultimately, however, implement only as little or as much of the D&D 3.5ed rules for creating a character as you can. Treat this specification as a guideline. Remember, though, the more stuff you can add, the more your generator will shine.

Character Description – Age, Height, Weight, Eyes, and Hair
The first thing to explore more carefully when creating a character is the character’s physical description. Generally, this can be broken up into 5 different values: Age, Height, Weight, Eye Color, and Hair Color. When creating a randomly generated character, these values should be filled in based on the tables located in the SRD. Because the tables are exhaustive, I will not duplicate them here. However, I was unable to find in the SRD anything regarding hair color or eye color for the different races.

So, for the purpose of this project, all races can have hair color and eye colors that are one of the following. Note, if you feel like differentiating them, and only allowing elves certain hair colors, while giving humans other colors, that’s fine. Extra Credit for you. Eye Colors: Brown, Hazel, Amber, Green, Blue, Gray Hair Colors: Brown, Mahogany, Chocolate, Cinnamon, Chestnut, Black, Raven, Ebony, Charcoal, Blonde, Honey, Golden, Strawberry, Platinum, Red, Auburn, Russet, Scarlet, White, Gray, and Silver.

For the remaining fields, simply look up the character’s race in the SRD file listed below, and then find the range of values for Age, Height, and Weight and randomly generate a value within that range. For more information on the Character Description, see Alignment and Description .

Character Races
The second thing to explore more carefully when creating a character is the character’s race. There are 7 available races which the player can select from. Use as many or as few as you like, but try to use at least the first four listed. Although they are listed in full detail in the System Reference Documentation (SRD) I’ll list the 7 available races here. The available races are: Human, Dwarf, Elf, Gnome, Half-Elf, Half-Orc, and Halfling. As indicated above, when you select a character race, it effects not only the identifier which describes what race they are but also a number of other attributes. In specific, the race a player chooses frequently/always effects the following:
  • Character Size: Races can be about 5 different sizes, however all of the races described in the SRD for playable characters are either Small or Medium. This information should be recorded as it’s important for determining armor that can be worn, and also attack/defense bonuses in combat.
  • Feats & Skills: Although we’ve not discussed feats and skills yet, some races get bonuses to the number of feats and skill points which can be assigned at each level. This should be taken into account when selecting the character’s skills and feats.
  • Ability Scores: Many of the races, save for humans and half-elves, modify the character’s ability scores. That is, whatever is rolled for the character will be modified up or down for certain scores depending on the race. These should be taken into account and the modifications applied.
  • Weapon Proficiency/Familiarity: Many races can inherently use certain weapons which may not be otherwise allowed without proper feats or abilities. When picking equipment for characters, these proficiencies should be kept in mind. Sometimes it’s best to treat these proficiencies as though the character automatically receives certain feats.
  • Skill Bonuses: Frequently a race receives inherent bonuses to certain types of skill checks. According to the SRD, these skill check bonuses often only apply it certain circumstances, such as when the dwarves are working with stone, or when facing monsters of specific types and sizes. Feel free to use these qualifiers if you can, however for simplicity, feel free to blindly apply these skill bonuses in all circumstances.
  • Immunities: Some races are immune to certain effects or spells. These are important to note for combat. Perhaps create an immunities property, which stores all of the immunities a specific character has, then if such an ability were used against this character in combat, those effects could be checked against their list of immunities.
  • Spell-Like Abilities: These are the most interesting, and the most difficult to work with. Some races, such as the Gnomes, have special abilities granted to them by their race. These function almost identically to class abilities. Generally it grants them to act as though they are allowed to cast a specific spell a certain number of times per day. Include these spell-like abilities if you can, however it’s not required.
You may find though, that once you’ve created the possibility for classes to have special abilities, it’s not overly difficult for races to have special abilities as well. For more information on the Character Races, see Races.

Character Classes & Level
The third thing to explore, and by far the most difficult, is the character’s class. There are 11 available classes which the player can select from. Use as many or as few as you like, but try to use at least the bold ones listed below. Although they are listed in full detail in the System Reference Documentation (SRD) I’ll list the 11 available classes here. The available classes are: Barbarian, Bard, Cleric, Druid, Fighter, Monk, Paladin, Ranger, Rogue, Sorcerer, Wizard As indicated above, when you select a character class, it effects not only the identifier which describes what class they are but also a number of other attributes. In specific, the class a player chooses frequently effects the following:
  • Hit Dice: This is the size of the die that is rolled to determine the number of maximum hitpoints a character has. Generally, the character receives the maximum value possible at first level, and then that sized die is rolled for each level after that. For example: A Barbarian is a d12. This means that at level 1 they have a minimum of 12 hitpoints due to their class. Every level after that, they receive additional hitpoints in the range of 1-12, randomly generated. So a level 2 Barbarian has AT MOST 24 hitpoints due to their class. As we’ll discuss later, this can be different as a result of ability scores. But, these hit dice should be recorded, and used when generating characters a level higher than 1.
  • Class Skills: Every class has a set of skills which are compatible with their class. This is important as skills that are compatible with a class require fewer skills points to use in order to increase the skill by one rank. This should be taken into account when assigning skill points for the character.
  • Skill Points: Every class receives a specific number of skill points at the first level, and then more every level afterwards. The exact amount is based upon the class and their intelligence modifier. This should be taken into account when assigning skills based on character level.
  • Base Attack Bonus: Every class has a base attack bonus which is based on the character’s level. Saving Throws: Every class has a base value for the 3 saving throws based upon the character’s level Feats: Some classes receive additional feats at specific levels. These should be taken into account when assigning feats to the character.
  • Armor/Weapon Proficiency: Each class has specific proficiencies that allow them to use armor and weapons of specific types and sizes. These should be taken into account when assigning equipment and items to the character.
  • Special Abilities: Every few levels a character class grants the character special abilities or effects. These are the most difficult to implement. At the very least, a list should be made when creating the character identifying WHICH abilities he/she has. Some you may find are easier to implement than others. For example, some special abilities just grant the character higher ability scores at specific levels, while others allow the character to cast spell-like abilities a specific number of times per day. When working with special abilities, it’s up to you how complete you wish to implement them. My minimum requirement for this is that you at least list which special abilities the character has, depending upon his level.
  • Spells: Similar to Special Abilities, some class receive spells at different levels. Additionally, spell casters often can cast different numbers of spells each day from each spell level range depending upon their level. As with special abilities, it’s up to you whether you feel you can actually implement any spells. For this project, I only require that you make a list of which spells the character knows, and how many times they can cast each per day.
Note, this is different for different classes, so pay special attention to the description of the class you’re implementing. For more information on the Character Classes, see Character Classes I and Character Classes II.

Character Money
The fourth thing to explore more carefully when creating a character is the character’s money. Every character class has a specific amount of money they get as level 1 characters. This money should be randomly calculated, and the money awarded to the character. Of importance, money in Dungeons and Dragons is broken up into different types of metals – Specifically copper, silver, gold, and platinum. Each one is worth 10 of the previous type. Ie, 1 Gold is equal to 10 silver. It will be important to keep track of the amount of each type of metal the character has, and also the total value, divided up into the largest units possible. For example, if your character has 37 copper, that should be noted, but it should also be noted that the character has 3 silver, 7 copper – total money. (This screams Struct) Finally, with this character generator we’re assuming the ability to create characters after level 1. Although this is not a standard rule, assume the money that is earned each level is equal to the level number multiplied by the number of die used at level 1. So for example:
  • if a level 1 Bard gets 4d4x10 starting gold,
  • then he would get 8d4x10 at level 2 ( (2*4)d4 * 10 ).
  • At level 3 he would get an additional 12d4x10 ( (3*4)d4 * 10).

This pattern continues all the way up to level 20. Another way to look at it, a level 10 Bard would get ((1+2+3+4+5+6+7+8+9+10) * 4)d4 * 10. For example...the level 10 Bard has (55 *4)d4*10, or 220d4x10. This means to roll a d4 die 220 times – add up the total value, and THEN multiply that by 10. Here’s the list of starting goal per class, at level 1: Barbarian, Bard: 4d4 x10 Cleric, Rogue: 5d4 x10 Druid: 2d4 x10 Fighter, Paladin, Ranger: 6d4 x10 Monk: 5d4 Sorcerer, Wizard: 3d4 x10

Character Ability Scores
The fifth thing to explore more carefully when creating a character is the character’s ability scores. There are 6 ability scores, each which dominate a specific aspect of the character. Each ability score serves specific purposes, and these should be noted when creating the character. In general, it is not the ability score that matters, but rather the ability score modifier. That is, depending upon the ability score, a positive or negative modifier will be applied to all areas governed by that specific ability score.

As an example, the number of skill points a player receives on the first level and every level after that is effected by the character’s Intelligence Modifier. What the exact effect is, is based upon the class, but in ether case, the Intelligence modifier will have an impact. There is a table in the SRD which illustrates what the ability score modifiers are for each ability score, and how they are used however I’ll provide a quick formula here.

First, start with the value 10, and assign it the modifier 0. Then, every 2 points above 10, add +1 modifier. Every 2 points below 9 (starting with -1 at 9), subtract -1 Modifier. As an example, an Intelligence of 15 results in an intelligence modifier of +2. (+1 at 12, +1 at 14) Likewise, an intelligence of 7 results in an intelligence modifier of -2 (-1 at 9, -1 at 7) As to what the ability scores impact, some effect attack rolls, damage done, how successful you are with specific skills, what your armor class is, and even your saving throws. For exact information about what each ability score modifier modifies, check the SRD document listed below. For more information on the Character Ability Scores, see Basics and Ability Scores .

Character Hitpoints
The sixth thing to explore more carefully when creating a character is the character’s Hitpoints. As indicated above, the character’s hitpoints is based on the character’s class. At level 1 they receive the maximum possible value for their dice roll. Every level after that, from level 2 to 20, they receive a random amount in the range from 1 to whatever their die type is. Additionally, the amount of hitpoints received each level is effected by the character’s Constitution Modifier. See the Constitution section in the ability score document above for more information.

Character Saving Throws
The seventh thing to explore more carefully when creating a character is the character’s saving throws. Each character has 3 total saving throws, Fortitude, Reflex, and Will. These are to help you in combat in order to avoid certain tragic events. The value of your Saving throws is determined by adding up several other values, including a Base Save given to you by your class, an ability score modifier, racial modifiers, and sometimes feats as well. You should take these into account if you can when creating your character. For more information on the Character Saving Throws, see Basics and Ability Scores and Combat I (Basics)

Character Skills
The eighth thing to explore more carefully when creating a character is the character’s skills. There is a complete list of skills located in the SRD spread over two files. Ultimately, skills are just things which are checked against in order to determine if your character is successful at accomplishing a task. The calculation of a character’s skills are a combination of ability score modifiers and skill points spent each level in order to increase your character’s rank in those skills, and thus, increasing their chance to succeed in a task. It’s important to note that every class has “class skills” which increase rank at a rate of 1 per skill points, “cross-class skills” which increase at a rate of 2-points per rank, and then skills which they cannot learn. These should be taken into account when randomly generating the character’s skills.

Ultimately, you’ll want to determine the total number of skill points your character has for his level, and then distribute them across first the skills that he’s likely to use (class skills) and then perhaps spend a few points in cross-class skills for variety. It should be noted, however, there’s a maximum number of ranks which can be spent on a skill per level. This amount is different for class skills and cross class skills. See the documents below for more information. For more information on the Character’s skills, see Character Classes I, Character Classes II, Skills I, and Skills II

Character Equipment and Items
The ninth thing to explore more carefully when creating a character is the character’s equipment. After you’ve determined how much money your character has, you get to spend it on purchasing equipment. This includes, armor, weapons, goods, throwables, tools, spell scrolls, etc…You’ll notice that there are different types of items such as Armor, Weapon, Good, Tool, Scroll, etc…but ALL can be carried in the player’s inventory. You may consider inheritance here as a possible solution, since a Weapon IS-A Item. This is one of the most challenging parts of the character generator, next to the abilities.

My advice, would be if you’re interested in implementing this, to create a table for each type of items, such as a table of weapons, a table of armor, etc…In each table, indicate which classes can you the item, perhaps with a flag enum. Then, when it’s time to assign equipment, give the character some armor, weapons, etc…from the table he can use. Perhaps just roll a random index, and then iterate from there until you encounter something he/she can use.

Finally, there is more than just standard equipment. There are magical items, and characters of higher levels are more likely to have magical items. So you may consider taking a look at the magical items as well. For more information on the Character’s equipment, see Equipment. If you’re interested in providing magical items for higher level characters, you’ll want to download this zip file containing all Magical Items.

Character Armor Class
The 10th thing to explore more carefully when creating a character is the character’s armor class. Once you know a character’s equipped gear, you can calculate their AC. This is based upon a character’s natural armor (10) plus both the armor they wear, their size, and also on their dexterity ability score modifier. This is important because in combat, a character’s Armor Class is used to determine if their enemy successfully hit them. For more information on the Character’s Armor Class, see Combat I (Basics).

Character Attack Bonuses
The 11th thing to explore more carefully when creating a character is the character’s Attack Bonus. Your character is given a base attack value by his class, then, depending upon which weapon you use, what feats you have, and what your character’s ability score modifiers are, you will have a final attack bonus when attacking. This is compared against your enemies Armor Class to determine if you successfully struck them in combat. Use the information in the resource below for determining Attack Bonus. For more information on the Character’s Attack Bonus, see Combat I (Basics) .

Character Abilities (optional)
The 12th thing to explore more carefully when creating a character is the character’s Special Abilities. This section is optional, but highly recommended. Just as a character gets feats at level 1 and then every few levels after that, your character also receives special abilities. Unlike Feats where the character can choose them from a master list, assuming they meet the prerequisites, the character’s abilities are pre-determined, based upon the class definition. In this way, Special Abilities are more predictable, and a bit easier to implement, however WHAT they do can often be more difficult to implement.

As a result, should you decide to try and implement assignment of special abilities in the character creation process, you may first begin by just making a list of which Abilities the character currently has, based upon the level he was created at. Then, after that’s complete, pursue adding the effects of the special abilities. Should you decide to try and implement special abilities, one way or the other, use the following resources. For more information on the Character’s Special Abilities, see Character Classes I and Character Classes II .

Character Feats (optional)
The 13th thing to explore more carefully when creating a character is the character’s Feats. This section is optional, but highly recommended. Basically, every character has 1 or more feats that are gained at level 1, and then at specific levels after that. Feats can do anything from making a character faster, giving them more hit points, making their spells stronger, all the way to allowing them to get multiple strikes at a time, after killing an enemy.

And, although Feats are really one of the key aspects of D&D 3.5ed, this section is optional. Implement feats if you can and have time for it, but do not feel obligated. As well, it’s perfectly fine to decide you WANT to implement “feats”, and then only get a few feats implemented. Nothing says you have to support ALL feats listed in the SRD. As well, even if you cannot implement the feats, it may be worth it to you to at least randomly select the feats from a list, based on meeting the feats prerequisites, and then just store the feats the character has in a list, without actually applying the feat to the character’s stats. Should you decide to try and implement feats, one way or the other, use the following resource. For more information on the Character’s Feats, see Feats.

Character Spells (optional)
The 14th and final thing to explore more carefully when creating a character is the character’s Spells. Not every character can cast spells, but for those that can it’s a vital asset to their class. As with the previous two sections, randomly assigning spells to your generated characters is optional. Also as before, it may be a good idea to first randomly generate a list of which spells the character HAS, and then worry about implementing a spell class which might actually allow your characters to cast spells. For more information on the Character’s Spells, see Spell List I and Spell List II If you’re actually interested in attempting to implement spells, you’ll want to download the zip file containing all Spells.

Conclusion
Well, here were are at the conclusion of the project description for Project 2. I’ve tried to give you a reasonable overview of what is expected from you in this project. The main idea is to have fun. In general, we’re just randomly generating a character’s information based on a set of rules and tables from the Dungeons and Dragons 3.5ed System Reference Document. If there is any confusion about what you should and should not attempt to implement, please do not hesitate to ask. And, when in doubt, leave it off. The best thing you can do is start with the easily generated items, and then move on to the more difficult. With that in mind, here’s my suggestion for implementing this project….
  • 1. Define the types of data for each of the above fields. String for name, perhaps an enum for class, race, eye color, and hair color, ubyte’s for the ability scores, etc…
  • 2. Create a Character class which contains fields & properties for all of the above data.
  • 3. Create static classes for the different races and character classes to help you fill in relevant information for your character. (did someone mention inheritance, abstract class maybe?)
  • 4. Add a class to randomly generate a character, 1 property at a time. I’d recommend doing them in the following order (remember that name, class, level, gender, and race are assigned, not randomly generated:

  • Age (based on race)


  • Height, Weight (based on race)


  • Hair Color, Eye Color (based on list given above)


  • Money (Based on classes above)


  • Ability Scores (should be based on what the class utilizes, see class descriptions for more info)


  • Hitpoints (based on class die type and level)


  • Saving Throws (based on class, race, ability scores, and feats)


  • Attack Bonus (Based on class, ability scores, and equipment)


  • Skills (Based on Class)


  • Equipment (should be chosen somewhat based on class, proficiencies, and feats if included)


  • Armor Class (based on equipment, size, and modifiers)


  • Abilities (Based on class)


  • Feats (should be somewhat based on class, though there’s no direct connection)


  • Spells

5. Create a class which outputs all of a character’s information to the console window. If you have any questions about the logistics of the program, please feel free to post your questions here in the C# Workshop – Project 2 Forum. I do, however, request you not actually submit you entire source code until at least 1 week has passed. Though feel free to ask for help about sections you’re having a problem with. I encourage all people participating in the C# Workshop to complete this project, as you can be assured it will be used again in later projects. As before, I will try and provide hints every few days for the next week and a half or so, to help people keep moving. Feel free to use or not use my advice or hints, as they just provide insight into A WAY to implement this project, not necessarily THE WAY. Cheers and GOOD LUCK!




C# Workshop - Project 1: Maze Generator - Solutions

Posted by , in C# Workshop 27 October 2012 - - - - - - · 1,321 views

Post your solutions here!


C# Workshop - Project 1: Maze Generator - Questions

Posted by , in C# Workshop 27 October 2012 - - - - - - · 1,057 views

Ask questions here. No full solutions!


C# Workshop - Project 1: Maze Generator

Posted by , in C# Workshop 24 October 2012 - - - - - - · 2,049 views

(Note this project is originally from JWalsh's C# Workshop, that is found on GameDev.net)

Introduction
Welcome to Project 1 of the C# Workshop. This project is designed to give you an opportunity to challenge your understanding of both the material we’ve already covered, as well as the material we will be covering over the next two weeks. For those with previous programming experience, this project wont be overly difficult, but it will give you an opportunity to test your understanding of the programming syntax provided in C#. For those with no previous programming experience, this project will be a challenge. Not because it’s technically difficult or overly complex, but because 90% of being an adequate programmer is your ability to solve problems. Being able to logically break a project description down into discrete, manageable components is one of the most valuable skills any programmer can have. Unfortunately, this is not something that can be taught, it’s something that can only be learned with practice and the development of an analytic mind.

Topics Covered
As the first project is designed to correspond with the first 4 weeks of the workshop, it will test and exercise your understanding of the following topics:
  • The System.Console Class
  • Strings and Primitive Types
  • Expressions, Selection, Iteration, and Arrays
  • Classes, Structs, Methods, Fields, and Objects

Background Information
As early as 2000 BC Egyptians were recorded creating complex structures referred to as labyrinths, designed to bring awe to those who wandered the corridors, marveling at the architectural genius. Later, these labyrinths were brought outdoors - designed to confuse and trick those unfortunate enough to be caught within their bushy walls. Legends tell of The Minotaur and magnificent treasures hidden in the center of these maze-like prisons. Since the 1970’s and the so-called ‘maze craze’ book writers, television producers, and even game developers have used the mystery and intrigue inherent in mazes to add complex environment and situations to their audience. And as many of those reading this project description are aspiring game programmers, we too will use the concept of a maze to add an exciting element to our final project of the C# Workshop.

Before we do though, lets learn a bit more about mazes and their types. First, Mazes come in many different dimensions and tessellations - with many different routing methods. They can either be 2D, 3D (a multi-level 2D Maze), or even weaved together in which case there is a single 2D path which overlaps itself with tunnels and bridges. As for tessellation (the geometry the rooms are made of) there are orthogonal, which is the classic maze with passages intersecting in right angles, Theta Mazes, which consist of connected concentric circles in which the participant is trying to get either to or from the center, and Zeta Mazes, which consists of an Orthogonal maze that also includes 45 degree diagonal paths. More recently we’ve seen the advent of fractal mazes, which are recursive mazes, which themselves may contain multiple other mazes – each of potentially different tessellation. As for routing methods, there are 3 predominant types.

The first, and oldest, is the Unicursal. The Unicursal maze has no junction points is simply a single, longish path which winds around depending upon the tessellation type from the beginning to the end of the maze. This is the routing method of the oldest historic labyrinths.

The second type of maze is the Braid Maze. This type introduces the presence of choice, but without the existence of dead-ends. All paths lead to every other path within the maze and is created essentially by knocking down strategic walls between passages in a Unicursal maze. The difficulty introduced in a Braid Maze is that while you never encounter a dead-end, you can’t be sure if you’re going forward or backward. The traveler only becomes aware of their mistake when they end up somewhere they’ve already been – and if the maze is so designed, this itself can often be a difficult challenge.

The third type of maze is the so-called “Perfect Maze.” In the perfect maze there are no loops or closed circuits, no inaccessible areas, and from a more mathematical perspective, every single room or corridor in the maze has EXACTLY one path to any other point in the maze. As a result, there are nearly infinite starting and ending points. It is as difficult to get from the center of the maze to a single corner as it is to get from one corner to another.

Additionally, while the Braid Maze has loops, the Perfect Maze has dead ends. This can be aggravating as the traveler is forced to backtrack and return to a corridor they know they’ve already been to. From a difficulty perspective, however, a well made Braid Maze can easily become more difficult than a Perfect Maze.

Feature Requirements / Use Cases
For this workshop we will be implementing a console-based 2D, Orthogonal, Perfect Maze – Maze Generator. Phew, that’s a mouth full. This means, as stated above, that we’ll be generating 2D, rectangular grid mazes, which have exactly 1 path from any two points in the maze. Here’s how your program should work… When the user launches the executable they should immediately be shown welcome text. The text can say whatever you like, but in general, “Welcome to The C# Maze Generator Program” is just fine. At the same time, you should set the title of the Console window to say the same. Beneath the welcome message a few lines the program should prompt the user for how large a maze they want. This should be done in two steps.

First the program should ask the user how many rows (how tall) they want the maze. Once the user enters a value and presses enter, the program should check to make sure the number entered was between 2 and 50. If the value was NOT between 2 and 50 (inclusive), the program should ignore the value that was input, and repeat the question. Also, if the user enters in a letter, symbol, or something other than a valid number between 2 and 50, repeat the question.

If the value WAS between 2 and 50 (inclusive) continue forward by asking the user how many columns (how wide) the user wants the maze to be. As before, validate that the data that was entered was a valid number between 2 and 50 when the user presses enter. With the above done you should now have enough information to generate your random maze. The algorithm for how to do this will be explained in more detail below.

Once you’ve generated a random, perfect maze, which matches the user’s specifications, you should display it to the screen. This will require outputting ‘|’ and ‘_’ where vertical and horizontal lines should be. Additionally, before printing the maze to the screen you’re going to want to make sure the Console window’s buffer is large enough to accommodate the desired size maze. You can do this by using methods on the System.Console class.

Finally, after displaying the map, you should prompt the user to determine whether or not they would like to display another map. Available answers should be ‘yes’ ‘y’ ‘no’ and ‘n’. Obviously ‘yes’ and ‘y’ should perform the same action, while ‘no’ and ‘n’ also perform the same action. Any other response should let the user know you didn’t understand their response, and then repeat the question. If they answered with either ‘no’ or ‘n’, terminate execution of the application. If they say ‘yes’ or ‘y’, repeat the process outlined above, beginning with asking them to input the numbers of rows and columns they’d like the maze to be. Here’s a simple screenshot which shows the entire process, and a rough idea of what the output should look like. Feel free to use your own text and messages.

Knock-Down Algorithm Key Terms
First, when talking about an orthogonal maze it’s common to talk about it in terms of Rooms or cells. A room is simply a single grid element in an MxN grid. If I had a 10x10 maze, for example, I’m speaking of a maze which logically has 100 rooms, which are numbered from 0 to 99, with 0 being the top left, and 99 being the bottom right room. As you might have imagined, each room in the maze is separated by Walls. Technically, a room can be surrounded by 2 to 4 walls. The reason some rooms have 2 or 3 walls, is because, in general, we don’t consider the outer edge as being walls. That’s simply the outer edge. So if I take the room in the bottom left hand corner, for example, I’m speaking of a room that has two interior walls. One horizontal one above it, and one vertical one next to it.

Now, the thing that makes a Perfect Maze truly unique is that every room in the maze is connected to every other room in the maze by exactly 1 path. But how do I guarantee that? The answer is surprisingly simple. Before I tear down a wall, and make a new path between two rooms, I simply determine whether or not the two rooms already have a path between them. “Hold up, hold up…you mean I have to write a path finding algorithm?!? “ Uhh, no. Well, sorta…but it’s not as tricky as it sounds. Here, I’ll explain.

Knock-Down Algorithm Description
Lets assume for a moment that we’ve got a 3x3 maze (draw it out on paper if it helps), in which all 12 interior walls are “Up”. This means that no rooms are connected to any other rooms. So how many sets of rooms do we have?

Your first response might be 0, but the truth of the matter is that we have 9 (3x3) sets of rooms, which happen to only contain 1 room each. Now, lets assume I were to start in the top left corner (room 0) and knock down the vertical wall leading to the room to the right of it (room 1). Now how many sets of rooms do I have?

Well, there are really two possible answers to this. The first possible answer is 8. You see, by breaking down the wall between rooms 0 and 1, I now have a single set of rooms which contains 2 rooms, and I have 7 sets of rooms which still contain 1 room each. Another possible answer, however, is 9. By combining the two rooms into a single set, I’ve not really reduced the numbers of sets, I’ve merely reduced the number of ROOMS in each set. Specifically, Room Set 0 now contains 2 rooms, while Room Set 1, contains 0 rooms.

Moving on. Now lets break down some more walls. Lets break down the wall between room 1 and room 2. This is again the vertical wall to the right of room 1 and when I do, I now have 3 rooms which are in the same set of adjacent rooms. That is room 0, 1, and 2 are all connected, and there are no more vertical walls in the top row. How many sets do I have? Yup, you guessed it, I still have 9 Room Sets. How many rooms are in each set? Set 0 has 3 rooms, and Set 1 and 2 both have 0 rooms. Sets 3 through 9 all have 1 room in them. Still with me?

Good. Moving on. Now we’re going to knock down two more walls very quickly in order to advance the explanation. Lets knock down the horizontal wall that separates room 2 from room 5. I call this a “floor” wall because it looks like it’s the floor of room 2. After doing that we’re going to tear down the vertical wall between room 4 and 5. At this point, you should have a maze which looks sort of like a snake, moving back upon itself. Here’s where we get to the fun part. Rooms 0, 1, 2, 5, and 4….have all been connected by ‘knocking down walls’. And each time we knocked down a wall we took the new room we just discovered and we added it the set of the previous room. But what happens if we go to knock down a wall and the room on the other side is ALREADY in that set?

Continuing with our example lets say we now decide we’re going to attempt to knock down the wall between rooms 1 and 4. That’s the horizontal floor wall beneath room 1. Before we knock it down, lets check real quick what set each room is in. Room 1 is in set 0 and room 4 is ALSO in set 0. Now what do we do? Nothing. Both rooms being in the same set is an indication that somehow, somewhere, there is already a path between these two rooms. And since knocking this wall down would create two paths between these rooms…we cannot knock it down. Tada! By simply accumulating all of the rooms you explore into the same sets, you make it impossible for two rooms to ever have multiple paths between them.

Knock-Down Algorithm Walkthrough
Now that we know we can prevent rooms from having multiple paths between them, lets go through a complete working example. Again, as a 3x3. This time, rather than jumping from room to room as we did, lets process the walls sequentially. Imagine as we did before that the rooms are numbered from left to right, top to bottom. Beginning with room 0 in the top left, and room 8 in the bottom right. Now also assume that the WALLS are numbered from 0 to 11. Wall 0 is in the top left, and separates rooms 0 and 1. Wall 1 is between room 1 and 2. Wall 2 is between room 0 and 3. Get where I’m going with this. The walls are numbered horizontally from left to right, top to bottom just like the rooms are.

So going through a complete knock-down algorithm run we get the following…
Initial State Rooms: { 0, 1, 2, 3, 4, 5, 6, 7, 8 }
Walls Up: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }
RoomSets: { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8} }

Step 1:
Knock down Wall 0
This combines room 0 and 1 into the same set
Walls Up: { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }
RoomSets: { {0, 1}, {}, {2}, {3}, {4}, {5}, {6}, {7}, {8} }

Step 2:
Knock down Wall 1
This combines room 1 and 2, but since 1 is in the same set as 0, they all get combined
Walls Up: { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }
RoomSets: { {0, 1, 2}, {}, {}, {3}, {4}, {5}, {6}, {7}, {8} }

Step 3:
Knock down Wall 2
This combines room 0 and 3
Walls Up: { 3, 4, 5, 6, 7, 8, 9, 10, 11 }
RoomSets: { {0, 1, 2, 3}, {}, {}, {}, {4}, {5}, {6}, {7}, {8} }

Step 4:
Knock down Wall 3
This combines room 1 and 4
Walls Up: { 4, 5, 6, 7, 8, 9, 10, 11 }
RoomSets: { {0, 1, 2, 3, 4}, {}, {}, {}, {}, {5}, {6}, {7}, {8} }

Step 5:
Knock down Wall 4
This combines room 2 and 5
Walls Up: { 5, 6, 7, 8, 9, 10, 11 }
RoomSets: { {0, 1, 2, 3, 4, 5}, {}, {}, {}, {}, {}, {6}, {7}, {8} }

Step 6:
TRY and knock down Wall 5
This would combine rooms 3 and 4. However, observe that both rooms 3 and 4 are in the same set already
Skip the wall

Step 7: TRY and knock down Wall 6
This would combine rooms 4 and 5.
However, observe that both rooms 4 and 5 are in the same set already
Skip the wall

Step 8:
Knock down Wall 7
This combines room 3 and 6
Walls Up: { 5, 6, 8, 9, 10, 11 }
RoomSets: { {0, 1, 2, 3, 4, 5, 6}, {}, {}, {}, {}, {}, {}, {7}, {8} }

Step 9:
Knock down Wall 8
This combines room 4 and 7
Walls Up: { 5, 6, 9, 10, 11 }
RoomSets: { {0, 1, 2, 3, 4, 5, 6, 7}, {}, {}, {}, {}, {}, {}, {}, {8} }

Step 10:
Knock down Wall 9
This combines room 5 and 8
Walls Up: { 5, 6, 10, 11 }
RoomSets: { {0, 1, 2, 3, 4, 5, 6, 7, 8}, {}, {}, {}, {}, {}, {}, {}, {} }

Step 6:
TRY and knock down Wall 10
This would combine rooms 3 and 4. However, observe that both rooms 3 and 4 are in the same set already
Skip the wall

Step 7:
TRY and knock down Wall 11
This would combine rooms 4 and 5. However, observe that both rooms 4 and 5 are in the same set already
Skip the wall

With the 12 walls evaluated and either knocked down or not, you can see that all rooms are now in the same set, and thus there is a single path between each room, and there are 4 walls still standing – 5, 6, 10, and 11. If you were to draw this out on paper you’d see a map similar to this:
_____
|	 |
| | | |
|_|_|_|

Knock-Down Algorithm Random Permutation
Now, if you were paying attention to the algorithm you might have noticed there’s nothing random about it. Every time the algorithm is ran, it would generate the exact same maze as the one given above, for a 3x3 layout. So how do we create random mazes from this? Simple. What happens if we were to knock the walls down in a different order? Remember, whenever we knock down a wall, all we do is stop to determine whether or not the rooms on either side of the wall are in the same set. We don’t care what order the walls are knocked down. So incidentally, if we knock the walls down in a different order, we’d end up with a maze which looked different. To accomplish this, you can permutate the list of walls before beginning the knock-down process.

If you do, you’d get a list of walls that might looks something like this:
Initial State Rooms: { 0, 1, 2, 3, 4, 5, 6, 7, 8 }
Walls Up: { 0, 2, 3, 1, 6, 5, 4, 7, 11, 9, 10, 8 }
RoomSets: { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8} }


Conclusion
Well, here were are the conclusion of the project description for Project 1. Hopefully by the end of this you’ve determined exactly what
requirements are expected of you, and code you should use to generate a randomly created, perfect Maze. Feel free to use the Project 1
forum to post your questions regarding design and implementation of Project 1. I request you not actually submit you entire source code
until after the project 1 due date. Though feel free to ask for help about sections you’re having a problem with. Finally, I will try and provide hints every few days for the next week and a half or so, to help people keep moving. Feel free to use or not use my advice or hints, as they just provide insight into A WAY to implement this project, not necessarily THE WAY.

Cheers!








PARTNERS