moria-rcc
This document describes the race & class compiler (rcc). In more precise terms, this is a code-generation tool that is used to create files called race_class_tables.c and race_class_constant.h in gmoria. It reads in a single human-readable file that completely describes all of the races and classes in the game, and it generates code that can be compiled into the game. rcc issues warnings and errors when things don’t quite make sense. This document describes how to use rcc, and the format of the definition file.
The audience for this tool is a person who wants to add new races or classes to moria in a safe way. Although it’s easy to add new races or classes, the definition file only goes so far; for example it doesn’t allow the adding of new spells, or prayers. There is a hard-coded limit in the game that allows a maximum of 32 classes. There are issues with displaying more than the current number of races in the character creation screen. The limiting factor on the number of races is character creation interface, there is currently space to add 2 more races. When the syntax of the definition file is insufficient, the next step is to change actual C code. Beware that adding new classes and races to the game breaks save-game compatibility with other versions of gmoria.
Some attributes are stored in unsigned 8-bit integers, and others are in unsigned or signed 16-bit integers. Special care needs to be taken to prevent integer overflow in the values of attributes. This document states the allowed values for each attribute.
The definition file describes all of the races and classes in the game. A race is something like a human, or dwarf; while a class is an occupation, like warrior, or mage. rcc reads in this definition file to create the race_class_tables.c and race_class_constant.h files. It is meant to be human-readable, easily understood and modified by non-programmers.
The definition file is comprised of blocks. A block looks something like this:
race "Dwarf" { ... };
The block starts with a keyword denoting the kind of block (a race
block). Following that there’s a name for the block ("Dwarf"
), and then there are a set of braces, followed by a semicolon. The attributes of the dwarf race go inside of the braces (instead of ...
).
The definition file has one race
block for every race in the game, and one class
block for every class in the game. There is also an experience_levels
block that defines the number of experience points required to reach a given level. Lastly there are two blocks that map the spell and prayer keywords to their displayed names (spell_names
, and prayer_names
.)
The top-level structure of the definition file looks like this:
race "Human" { ... }; . . . class "Warrior" { ... }; . . . experience_levels { ... }; . . . spell_names { ... }; . . . prayer_names { ... };
The race & class compiler will stop processing the definition file when a semi-colon is missing or a required block is forgotten. If an attribute is missing, the compiler will emit a warning. The consistency check option performs extra checking on the races and classes.
The race
block defines the humans, elves, dwarves (etc), that a character can be in the game. It consists of a series of attributes and some other blocks. The structure of the race
block looks like this:
race "foo" { attribute: value; . . . classes { ... }; store_price_adjust_by_race { . . . }; shopkeep "name" "race" "store" { . . . }; . . . backgrounds { . . . }; };
There are about 20 different required attributes. The classes
block defines which classes this race can be. The shopkeep
blocks declare the characteristics of the store owners of this race. Store owners change their prices based on what race the character is. The adjust_price_by_race
block contains these adjustments. Lastly, the backgrounds
block declares a series of sentence fragments that comprise the social history of the character. e.g. ‘you were the black sheep of the family’, etc.
Most of these attributes are added to a same-named attribute in the class
block (all attributes except age, weights, heights, and infra-vision).
rcc
will complain if any of these attributes are missing.
When characters begin the game they need an age. The age
attribute specifies the base age (in years), and a modifier value of a random delta. The maximum value for both halves of the value is 255
.
age: 100|20; # race's age is between 101 and 120.
Some races can see farther into the darkness than others. The infra_vision
attribute specifies how far away (in tiles) the character can sense a warm-blooded creature. The maximum value for this attribute is 255
.
infra_vision: 3; # race can sense warm-blooded creatures 3 tiles away.
When male characters begin the game they need a height, but some races are taller than others. The male_height
attribute specifies the base height (in inches), and a modifier value of a random delta. The maximum value for both halves of this attribute is 255
.
male_height: 62|6; # males in this race are 63 to 69 inches tall.
When male characters begin the game they need a weight, but some races are heavier than others. The male_height
attribute specifies the base weight (in pounds), and a modifier value of a random delta. The maximum value for both halves of this attribute is 255
.
male_weight: 190|10; # males in this race weigh 191 to 200 lbs.
Just like male_height
but for females in the race.
Just like male_weight
but for females in the race.
When characters begin a game they need a starting amount of hitpoints, but some races can take more damage than others. This attribute has a maximum value of 255
.
hit_points: 10; # the race starts out with a base amount of 10 hp.
When characters begin the game they have a base chance of disarming traps. The calculation to disarm a trap takes a lot of different factors into account, and this attribute is one of them. The unit of measurement of disarming
is unknown, but 200
will disarm the vast majority of traps, and 0
will seldomly disarm traps. The attribute is stored in a 16-bit unsigned integer.
disarming: 1; #this race has a small chance of disarming a trap.
When characters begin the game they have a base chance of finding hidden doors and traps. The maximum value for this attribute is 200
.
search_chance: 10; # has a 5% chance at finding a hidden door or trap.
When a monster seemingly doesn’t care that the character is walking past them in the dungeon, that’s the stealth factor at work. The maximum value for this attribute is 18
. A higher value means more stealth.
stealth_factor: 18; # a very stealthy race.
Some races are better at melee fighting than others. The base_to_hit
attribute is the base chance of hitting a foe. The maximum value for this attribute is 200
.
base_to_hit: 100; #has an innate ability to hit a foe 50% of the time.
Just like base_to_hit
, but for ranged weapons.
Some races have an innate ability to avoid getting hit. The saving_throw
attribute is the base chance of avoiding an attack. The unit of measurement for this attribute is unknown, but a value of 100
will probably always avoid an attack.
saving_throw: 1; # a small innate ability to avoid attacks.
Some races are stronger than others when characters are created. The strength_modifier
typically ranges from 1
to 18
, but a low value is sensible because this value is added to a die roll. Negative values are also allowed.
To understand what the strength attribute is for (or any of the other main stats), see the Character Stats section of the game manual.
strength_modifier: -1; #race has an initial strength penalty.
Like strength_modifier
but for intelligence.
Like strength_modifier
but for wisdom.
Like strength_modifier
but for dexterity.
Like strength_modifier
but for constitution.
Like strength_modifier
but for charisma.
Gaining levels in the game means acruing experience points. The experience levels are not the same per race because of the experience_factor
attribute, Experience levels can be raised or lowered according to this factor. A value of 0
would break the game, making all experience levels happen at zero experience points. A value of 100
means the levels are the standard levels as described in the experience_levels
block. A value of 200
means that the experience levels for this race are doubled the standard.
Take care when setting this value, because the experience_factor
attribute is one of the greatest determiners of game balance.
experience_factor: 105; # race finds it more difficult to level-up.
The store_price_adjust_by_race
block specifies how store owners (shopkeeps) raise or lower their prices for characters of a given race. Yes it’s true, the Half-Troll gives higher prices, and the Halfling might even give a bit of a break if the player’s character is also a Halfling.
The store_price_adjust_by_race
block requires one line for every race specified in the definition file. The structure of the block is:
store_price_adjust_by_race { "race-name" : price; . . . };
When the value of a price is 100
, it means that the price is neither raised or lowered. When the value of a price is 50
it means the shopkeep of that race will sell things at half off to the given race. For example:
store_price_adjust_by_race { "Human" : 100; "Dwarf" : 105; "Elf" : 95; };
If this store_price_adjust_by_race
block is inside a race "Human"
block, and we go to a store with an Elven shopkeep, as a member of the Human race we will get a %5 deal on everything sold in that store. The dwarf will make us pay more.
Whenever a new race is added to, or removed from the definition file, all of the store_price_adjust_by_race
blocks need to be updated.
Shopkeeps are the owners of stores who buy and sell items. These quirky characters behave differently according to their attributes specified in a shopkeep
block. Each of the six stores needs at least one shopkeep. The game will randomly select shopkeeps when a character is created.
Here is a sample shopkeep
block:
shopkeep "Erick the Honest" "Human" "General Store" { store: "1"; haggle_per: 4; inflate: 108|67; max_insults: 12; max_cost: 250; };
The first three chunks of text before the opening brace are used to create the top line that is seen in the store; so there are limits to the width of these chunks of text. The name chunk should be 22 characters or less; the class chunk should be 11 characters or less, and the store name chunk should be 14 characters or less. Although it might seem like the class name should align with the text seen in class
blocks, it is not the case. One shopkeep in the game has a class specified here as "Human?".
There are 5 attributes in the shopkeep
block:
The store attribute species which store the shopkeep occupies. "1" means the general store. All stores must be covered by at least one shopkeep
block somewhere in the definition file.
store: "1"; # the shopkeep occupies the general store.
Some shopkeeps haggle more intensely than others. The haggle_per
sets the minimum haggling percent between the prices the player offers before the shopkeep gets insulted. A maximum haggling percent is 3 times haggle_per
, where the shopkeep will try to offer a fairer price. The maximum value for haggle_per
attribute is 33
, but values much lower than this make more sense.
haggle_per: 4; #allow 4% diff. in haggling offers before being insulted.
Shopkeeps will ban characters forever if they insults them too many times by giving outrageous offers while haggling. max_insults
is the number of times a shopkeep can be insulted before the shop-doors are closed forever. This value is per-game, not per-visit to the store. Players would definitely be surprised if the shopkeep only allowed one insult! Values of 10
to 20
make more sense. The max_insults
attribute has a maxmimum value of 255
, and a minimum value of 1
.
max_insults: 12; # can receive 12 insults before refusing service.
When shopkeeps start haggling they haggle the price between a set of goalposts. The inflate
attribute sets these goalposts, as a percent. The first number is the minimum haggling percent, and the second number is added to the minimum to make the maximum haggling percent. The maximum value for both numbers added together is 255
.
inflate: 108|67; #haggles between 108-175 percent of real price.
Some shopkeeps won’t sell items that are above a certain price. The max_cost
attribute sets that price in gold pieces. It is also the amount of money the shopkeep has on hand to pay out when purchasing an item from the character, which means that there are some items that are just too expensive for the shopkeep to purchase from the character. The maximum value for this attribute is 65535
.
max_cost: 250; #can't buy or sell items worth more than 250gp.
The backgrounds
block has two purposes: to assist in setting the initial social class of a character (which affects how many gold pieces is started with), and also to assist in setting the history blurb of the character. The history blurb is the randomized ‘you were a well liked child, with black hair’ text that appears in the character creation screen.
The backgrounds
block is the most confusing block in the definition file, because it consists of a non-linear chain of background
blocks like so:
backgrounds { background 1 2 { . . . }, background 2 3 { . . . }, background 3 0 { . . . } };
Where the first background (background 1
) points to the second, and the second points to the third and the third background
block points to nothing which ends the chain.
Note that the background
blocks are separated by commas, not semi-colons like other blocks.
These background
blocks can be chained across race
blocks.
The user-interface of the game can support a history blurb of about 250 characters, or approximately 50 words, over a maximum of 4 lines.
A background
block defines a set of random history blurbs that form a sentence or part of a sentence. The structure of a background
block is:
background id next-id { fragment "foo" { . . . }, fragment "bar" { . . . }, fragment "baz" { . . . } },
The id
variable is a unique numeric identifier for this background
block among all other blocks. The next-id
variable represents which background
block this block is tied, or chained to.
The central purpose of the background
block is to randomly select one of the contained fragments, and then move on to the next background block, unless the next-id
is 0
.
This partial example shows a background that defines a set of eye colours:
background 1 2 { fragment "You have blue eyes." { . . . }, fragment "You have green eyes." { . . . }, fragment "You have hazel eyes." { . . . } },
The id
of the background has a maximum value of 255
and cannot be 0
. The next-id
can be 0
(the value that ends the chain of background blocks), and can also have a maximum value of 255
.
Each fragment contains a sentence or a part of a sentence to be randomly selected according to some simple rules.
fragment "foo" { roll: 50; social_class_bonus: 49; }, fragment "bar" { roll: 100; social_class_bonus: 51; },
In this example, the bar
fragment is randomly selected half of the time, and adds one (not 51
) from the character’s social class. The foo
fragment is also selected randomly half of the time, and it subtracts one from the character’s social class.
The fragment
block starts off with a chunk of text before the opening brace. Sometimes these chunks of text are whole sentences, and sometimes they are just portions of a sentence. These chunks of text often end in spaces because they will be joined with other fragments.
There are two attributes in the fragment
block:
The roll
attribute is a number between 1
and 100
that represents the chance interval of this fragment being randomly selected. When a fragment is being selected, a random number between 1
and 100
is selected. The first fragment with a roll
value of more than the random number is selected.
The social_class_bonus
attribute is how much to add to the character’s social class if this fragment is randomly selected. A value of 50
is the break-even value – it represents adding zero to the character’s social class. 49
means subtract 1
from the character’s social class.
The maximum value for this attribute is 255
.
Each set of fragment
blocks must contain a roll
of 100
to guarntee that one of the fragments is randomly selected.
When creating backgrounds, it is important to note that the character’s social class has a maximum value of 100
, and a minimum value of 1
.
The class
block defines the warriors, mages, rogues (etc), that a character can be in the game. It consists of a series of attributes and some other blocks. The structure of the class
block looks like this:
class "Rogue" { attribute: value; . . . adjust_per_one_third_level { . . . }; titles { . . . }; spells { . . . }; prayers { . . . }; };
A class can have a spells
block or a prayers
block (or neither), but a class cannot have both.
The attributes of the class
block all have their equivalents in the race
block. At the beginning of the game when a player selects a race and a class, these same-named attributes are added together. The attributes are:
hit_points: 6; strength_modifier: 2; disarming: 45; intelligence_modifier: 1; search_chance: 32; wisdom_modifier: -2; stealth_factor: 5; dexterity_modifier: 3; frequency_of_search: 16; constitution_modifier: 1; base_to_hit: 60; charisma_modifier: -1; base_to_hit_with_bows: 66; experience_factor: 0; saving_throw: 30;
The class is the main driver of these attributes. The ethos behind this is: what the character does is more important than what the character was born as. Some of these attributes are modified again according to the character’s level in the adjust_per_one_third_level
block. The race modifies the values set in this block. For information on what these attributes mean, see Race Attributes.
The attributes on the left are all unsigned 8-bit integers (unlike their same-named race counterparts which are 16-bit signed integers). The attributes on the right are all signed 16-bit integers.
Some of the class’ abilities are improved as the character gains experience. The adjust_per_one_third_level
block is what controls this effect. Here is a sample of the block:
adjust_per_one_third_level { adjust_base_to_hit: 3; adjust_base_to_hit_with_bows: 4; adjust_use_device: 3; adjust_disarming: 4; adjust_saving_throw: 3; };
The idea behind this block is that the character just naturally improves in these attributes during the game. The effect is meant to be subtle because only one third of the characters’ levels are considered in the calculation. For example, if the character has attained the 31st experience level, the base_to_hit_with_bows
attribute is adjusted by +41 points (31 / 3 * 4).
Every experience level has a new "title", or name. A first level mage is a ‘Novice’. A 38th level rogue is an ‘Assassin’. The titles
block sets all of the names of the experience levels for the class
that contains it. There must be one title for every level specified in the experience_levels
block. For example if there are only 5 experience levels, a title block for a fictional "Mechanic" class might look like:
titles { "Grease Monkey", "Oil Changer", "Journeyman Mechanic", "Engine Specialist", "Master Mechanic" };
The titles
block is one way that the game reveals itself slowly over time. Seeing a new title is a reward for attaining a new level, so create them with that in mind (e.g. try not to make boring titles). This can be a difficult task because there are usually 40 titles per class.
Titles are limited to a maximum length of 13 characters on the main game screen.
Some classes can cast spells and some can’t. When classes can cast spells, the class has a spells
block which defines which spells the class can cast. The spells
block has this structure:
spells { spell cure_light_wounds { . . . }, spell lightning_bolt { . . . } };
It is important to note that subsequent spell
blocks are separated by commas, and not semi-colons.
A spell-casting class can cast the following spells:
magic_missile | detect_monsters | ||
phase_door | light_area | ||
cure_light_wounds | stinking_cloud | ||
find_hidden_traps_and_doors | confusion | ||
lightning_bolt | trap_and_door_destruction | ||
sleep_i | cure_poison | ||
teleport_self | remove_curse | ||
frost_bolt | turn_stone_to_mud | ||
create_food | recharge_item_i | ||
sleep_ii | polymorph_other | ||
identify | sleep_iii | ||
fire_bolt | slow_monster | ||
frost_ball | recharge_item_ii | ||
teleport_other | haste_self | ||
fire_ball | word_of_destruction | ||
genocide | resist_poison_gas |
For a short description about what these spells do, see the Treasure Compiler manual.
Each spell
block declares when the spell becomes available to cast to the character, how much mana it takes to cast, how often it fails, and how many experience points are gained when the spell is cast for the first time.
The spell
block has the following structure:
spell magic_missile { level: 1; mana: 1; fail: 22; exp: 1; },
The spell
block contains the following attributes:
The level
attribute is the experience level that the spell can be cast at, if the character has the correct book. This attribute is stored in an 8-bit unsigned integer; so the maximum value is 255
.
The mana
attribute is the number of mana points required to cast to spell. After the casting, this many mana points is subtracted from the players’ mana. This attribute is stored as an 8-bit unsigned integer; so the maximum value is 255
. The minimum value for this attribute is 1
.
The fail
attribute is the percent chance that the spell cannot be cast. The player’s chance of failure takes other factors into account other than just this attribute – so it is properly thought of as a base chance.
The maximum value of this attribute is 100
, but even that is too high in a practical sense.
The exp
attribute represents the number of experience points that are gained when the spell is successfully cast for the first time.
The actual value of experience points gained is the given value bit-shifted two bits to the left. A value of 1
becomes 4
; a value of 32
becomes 128
, and a value of 128
becomes 512
experience points. The maximum value for the exp
attribute is 255
(which results in 1020
experience points).
The prayers
block is just like the spells
block but it contains prayer
blocks instead of spell
blocks. The following prayers can be prayed:
detect_evil | cure_light_wounds | ||
bless | remove_fear | ||
call_light | find_traps | ||
detect_doors_and_stairs | slow_poison | ||
blind_creature | portal | ||
cure_medium_wounds | chant | ||
sanctuary | create_food | ||
remove_curse | resist_heat_and_cold | ||
neutralize_poison | orb_of_draining | ||
cure_serious_wounds | sense_invisible | ||
protection_from_evil | earthquake | ||
sense_surroundings | cure_critical_wounds | ||
turn_undead | pray_prayer | ||
dispel_undead | heal | ||
dispel_evil | glyph_of_warding | ||
holy_word | resist_poision_gas |
For a short description about what these prayers do, see the Treasure Compiler manual.
The experience_levels
block defines the number of experience levels in the game, and what number of experience points is required to attain each level.
These levels are augmented for each race and class combination, as seen in the experience_factor
attribute of the race
and class
blocks.
The experience_levels
block looks like:
experience_levels { 10, 100, 1000, 1000 };
The first experience level is at 10 points, the second is at 100 points and so on. The numbers must always increase.
Take care when setting the values in this block, because it is one of the greatest determiners of game balance.
When a spell or prayer is casted, or listed on screen it has a name. The spell_names
block lists the names of spells in the game, and the prayer_names
block lists the names of prayers in the game.
The ordering of the spells or prayers in these blocks does not matter. The true ordering of spells is set by the ordering of spells in the Mage and Priest classes.
There must be a name given for every possible spell or prayer. For a list of spells see Spells Block, for prayers see Prayers Block.
The name block looks like this:
spell_names { magic_missile: "Magic Missile"; };
Let’s take this definition file as an example; one race and one class is define.:
race "Istari" { experience_factor: 100; age: 114|30; infra_vision: 2; male_height: 72|6; male_weight: 180|25; female_height: 72|6; female_weight: 180|25; hit_points: 14; intelligence_modifier: 2; wisdom_modifier: 2; dexterity_modifier: 2; classes { "Magic-User" }; store_price_adjust_by_race { "Istari": 100; }; shopkeep "Hundar the Blue " "Wizard" "Ye Olde Magic Shoppe" { store: "1"; haggle_per: 4; inflate: 108|67; max_insults: 12; max_cost: 250; }; backgrounds { background 1 2 { fragment "You are affiliated with water spirits, " { roll: 44; social_class_bonus: 35; }, fragment "You are affiliated with fire spirits, " { roll: 100; social_class_bonus: 50; } }, background 2 0 { fragment "and remember some of the song of creation." { roll: 35; social_class_bonus: 80; }, fragment "and remember most of the song of creation." { roll: 80; social_class_bonus: 90; }, fragment "and remember the entire song of creation." { roll: 100; social_class_bonus: 105; } } }; }; class "Magic-User" { experience_factor: 30; disarming: 30; search_chance: 16; stealth_factor: 2; frequency_of_search: 20; base_to_hit: 34; base_to_hit_with_bows: 20; saving_throw: 36; strength_modifier: -5; intelligence_modifier: 3; dexterity_modifier: 1; constitution_modifier: -2; charisma_modifier: 1; adjust_per_one_third_level { adjust_saving_throw: 3; adjust_base_to_hit: 2; adjust_base_to_hit_with_bows: 2; adjust_use_device: 4; adjust_disarming: 3; }; titles { "Wizard (1st)", "Wizard (2nd)", "Wizard (3rd)", "Wizard (4th)", "Wizard (5th)", "Wizard (6th)", "Wizard (7th)", "Wizard (8th)" }; spells { spell magic_missile { level: 1; mana: 1; fail: 22; exp: 1; }, spell lightning_bolt { level: 10; mana: 4; fail: 30; exp: 6; } }; }; experience_levels { 100, 500, 1800, 4400, 10200, 35000, 150000, 500000 }; spell_names { magic_missile: "Magic Missile"; lightning_bolt: "Lightning Bolt"; };
The resulting file that rcc outputs looks like this:
/* The following was generated by the gmoria race & class compiler */ #include "constant.h" #include "types.h" /* Store owners have different characteristics for pricing and haggling*/ owner_type owners[MAX_OWNERS] = { {"Hundar the Blue (Wizard) Ye Olde Magic Shoppe", 250, 175, 108, 4, 0, 12, 0}, }; /* Buying and selling adjustments for character race VS store */ /* owner race */ int8u rgold_adj[MAX_RACES][MAX_RACES] = { /* Ist */ /*Istari */ {100} }; /* Class titles for different levels */ char *player_title[MAX_CLASS][MAX_PLAYER_LEVEL] = { /* Magic-User */ {"Wizard (1st)", "Wizard (2nd)", "Wizard (3rd)", "Wizard (4th)", "Wizard (5th)", "Wizard (6th)", "Wizard (7th)", "Wizard (8th)"}, }; /* Base experience levels, may be adjusted up for race and/or class*/ int32u player_exp[MAX_PLAYER_LEVEL] = { 100, 500, 1800, 4400, 10200, 35000L, 150000L, 500000L, }; /* Race STR,INT,WIS,DEX,CON,CHR, Ages, heights, and weights (male then female) Racial Bases for: dis,srh,stl,fos,bth,bthb,bsav,hitdie, infra, exp base, choice-classes */ race_type race[MAX_RACES] = { {"Istari", 0, 2, 2, 2, 0, 0, 114, 30, 72, 6, 180, 25, 72, 6, 180, 25, 0, 0, 0, 0, 0, 0, 0, 14, 2, 100, 0x01, }, }; /* Classes. */ class_type class[MAX_CLASS] = { /* HP Dis Src Stl Fos bth btb sve S I W D Co Ch Spell Exp spl */ {"Magic-User", 0, 30, 16, 2, 20, 34, 20, 36,-5, 3, 0, 1,-2, 1,MAGE, 30, 1} }; /* making it 16 bits wastes a little space, but saves much signed/unsigned headaches in its use */ /* CLA_MISC_HIT is identical to CLA_SAVE, which takes advantage of the fact that the save values are independent of the class */ int16 class_level_adj[MAX_CLASS][MAX_LEV_ADJ] = { /* bth bthb devices disarm save/misc hit */ /* Magic-User */ { 2, 2, 4, 3, 3} }; /* Background information */ int background_start[MAX_RACES] = { /* starting .chart not index */ 1, /* Istari */ }; background_type background[MAX_BACKGROUND] = { {"You are affiliated with water spirits, ", 44, 1, 2, 35}, {"You are affiliated with fire spirits, ", 100, 1, 2, 50}, {"and remember some of the song of creation.", 35, 2, 0, 80}, {"and remember most of the song of creation.", 80, 2, 0, 90}, {"and remember the entire song of creation.", 100, 2, 0, 105} }; spell_type magic_spell[MAX_CLASS][31] = { { /* Magic-User */ {1, 1, 22, 1}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {10, 4, 30, 6}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0}, {MAX_SPELLS, MAX_SPELLS, 0, 0} } }; char *spell_names[2][MAX_SPELLS] = { { /* Mage Spells */ "Magic Missile", "", "", "", "", "", "", "", "Lightning Bolt", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { /* Priest Prayers */ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" } };
moria-rcc
This is the output of the command ‘rcc --help’:
Usage: moria-rcc [OPTION...] FILE Generate gmoria's race_class_tables.c from FILE. -c, --consistency-check check for consistency errors -C, --constants generate constants instead of tables. -o, --outfile=FILE put generated code into FILE -?, --help give this help list --usage give a short usage message -V, --version print program version By default the race_class_tables.c file goes to the standard output unless the -o option is used. For complete documentation, visit: <http://sv.nongnu.org/p/gmoria/> Report bugs to gmoria@nym.hush.com.
FILE
is the defintion file to "compile". If it is "-", then it will be read from the standard input.
rcc
supports the following options:
-o
--outputfile
Put generated code into FILE. This option puts the generated race_class_tables.c file into the given FILE. If FILE is "-", then it will go to the standard output. This is the default.
-c
--consistency-check
Check for consistency errors. A loose set of rules is applied the definition file.
-C
--constants
Generate constants instead of tables.
This option makes moria-rcc
generate the race_class_constant.h file instead of the race_class_tables.c file.
moria-mc
will typically be used in this fashion:
moria-rcc
on the new definition file
moria-rcc
with the –constants option and the same defintion file.
The following persons have contributed to this software:
If you find a bug in moria-rcc
, please send electronic mail to
gmoria@nym.hush.com. Include the version number, which you can find by
running ‘rcc --version’. Also include in your message the
output that the program produced and the output you expected.
If you have other questions, comments or suggestions about
moria-rcc
, contact the author via electronic mail to
gmoria@nym.hush.com.