This is a simple NPC generator for the Traveller RPG. It follows rules described in this article. I'll briefly describe the rules here.
Instead of randomly generating ability scores, this generator uses several standard arrays:
Citizen Category | Average Score | Characteristic Array |
---|---|---|
Below Average | 6 | 8, 7, 6, 6, 5, 4 |
Average | 7 | 9, 8, 7, 7, 6, 5 |
Above Average | 8 | 10, 9, 8, 8, 7, 6 |
Exceptional | 9 | 11, 10, 9, 9, 8, 7 |
According to the previous experience of the NPC, the generator will assign a number of skill points according to this table, "Average Skill Levels by Term":
Experience | Number of Skills by Skill Level | |||
---|---|---|---|---|
3 | 2 | 1 | 0 | |
Recruit | 0 | 0 | 0 | 4 |
Rookie | 0 | 0 | 2 | 4 |
Intermediate | 0 | 1 | 2 | 4 |
Regular | 0 | 2 | 2 | 5 |
Veteran | 0 | 3 | 2 | 5 |
Elite | 1 | 2 | 3 | 6 |
To build the project execute the following command:
make build
This will generate this binary out/generate-npc
.
To run the project execute the following command:
./out/generate-npc --help
These are the options for the command:
Option | Long Option | Description | Default |
---|---|---|---|
-c | --category | Citizen Category: 0-Below average, 1-Average, 2-Above Average, 3-Exceptional | 1 |
-e | --experience | Experience: 0-Recruit, 1-Rookie, 2-Intermediate, 3-Regular, 4-Veteran, 5-Elite | 3 |
-r | --role | Crew role in a starship: pilot, navigator , engineer , steward , medic , marine , gunner , scout , technician , leader , diplomat , entertainer , trader , thug | required |
-g | --gender | Gender of the NPC: female, male, unspecified | unspecified |
-d | --debug | Enable debug mode | false |
-h | --help | Show the help message |
You can also use this project as a library in your Go applications.
You can install it by running the following command:
go get github.com/carloscasalar/traveller-npc-generator
Here are some examples:
package main
import (
"fmt"
"github.com/carloscasalar/traveller-npc-generator/pkg/generator"
"os"
)
func main() {
npcGenerator, err := generator.NewNpcGeneratorBuilder().Build()
if err != nil {
fmt.Printf("Error creating NPC: %v", err)
os.Exit(1)
}
request := generator.NewGenerateCharacterRequestBuilder().
CitizenCategory(generator.CitizenCategoryAboveAverage).
Experience(generator.ExperienceRookie).
Role(generator.RolePilot).
Gender(generator.GenderUnspecified).
Build()
character, err := npcGenerator.Generate(*request)
if err != nil {
fmt.Printf("Error generating character: %v", err)
os.Exit(1)
}
fmt.Println("Generated Character:", character)
}
The library uses a very simple name generator. You can provide your own name generator by implementing the NameGenerator
interface.
package main
import (
"fmt"
"github.com/carloscasalar/traveller-npc-generator/pkg/generator"
"os"
)
func main() {
npcGenerator, err := generator.NewNpcGeneratorBuilder().
NameGenerator(new(CustomNameGenerator)).
Build()
if err != nil {
fmt.Printf("Error creating NPC: %v", err)
os.Exit(1)
}
for _, gender := range generator.GenderValues() {
request := generator.NewGenerateCharacterRequestBuilder().
CitizenCategory(generator.CitizenCategoryExceptional).
Experience(generator.ExperienceVeteran).
Role(generator.RoleLeader).
Gender(gender).
Build()
character, err := npcGenerator.Generate(*request)
if err != nil {
fmt.Printf("Error generating character: %v", err)
os.Exit(1)
}
fmt.Printf("Generated Character: %v\n", character)
}
}
type CustomNameGenerator struct {
}
func (c CustomNameGenerator) Generate(gender generator.Gender) (firstName, surname string) {
switch gender {
case generator.GenderMale:
return "Dwayne", "Hicks"
case generator.GenderFemale:
return "Hellen", "Ripley"
default:
return "Forge", "Jynxori"
}
}
This library comes with a name generator that uses a catalog of names and surnames. You can use it by creating a new instance of CatalogNameGenerator
.
package main
import (
"fmt"
"github.com/carloscasalar/traveller-npc-generator/pkg/generator"
"math/rand/v2"
"os"
)
func main() {
femaleNames := []string{"Hellen", "Jane", "Alice"}
maleNames := []string{"Dwayne", "John", "Bob"}
nonBinaryNames := []string{"Forge", "Jynxori", "Alex"}
surnames := []string{"Hicks", "Doe", "Smith"}
catalogNameGenerator, err := generator.NewCatalogSourcedNameGenerator(surnames, nonBinaryNames, femaleNames, maleNames)
if err != nil {
fmt.Printf("Error creating catalog sourced name generator: %v", err)
os.Exit(1)
}
npcGenerator, err := generator.NewNpcGeneratorBuilder().NameGenerator(catalogNameGenerator).Build()
if err != nil {
fmt.Printf("Error creating NPC generator: %v", err)
os.Exit(1)
}
for _, gender := range generator.GenderValues() {
category := pickRandomItem(generator.CitizenCategoryValues())
experience := pickRandomItem(generator.ExperienceValues())
role := pickRandomItem(generator.RoleValues())
request := generator.NewGenerateCharacterRequestBuilder().
CitizenCategory(category).
Experience(experience).
Role(role).
Gender(gender).
Build()
character, err := npcGenerator.Generate(*request)
if err != nil {
fmt.Printf("Error generating character: %v", err)
os.Exit(1)
}
fmt.Printf("Generated character: %v\n", character)
}
}
func pickRandomItem[T any](items []T) T {
itemIndex := rand.IntN(len(items) - 1)
return items[itemIndex]
}