Structuring the NPC Generator

This time around I would like to deliver on my earlier promise to get into the details of building FindFamiliar. The site is still a long ways from ready, but I’ve shifted my focus this week more towards the actual project because I really want to get a prototype version published so I can finally have something to show for all of this work. I was hoping to make some solid gains on both this week, but I’ve lost a few days to personal issues and it has put me behind schedule. I’m hoping to make up some ground this weekend, but in the meantime, the publishing must continue! So, let’s get into it.

Overall Focus

My focus on FindFamiliar has been in two major areas: 1. Getting all of the data I need represented in database models and creating fixtures to populate the database with, and 2. Figuring out how exactly I want to implement the NPC generator and getting the code written for it.

The first of these is a solid mixture of the mundane and interesting and comes from the fact that there is a fair amount of static data that needs to represented for FindFamiliar. In essence, I need all of the details of the rulebooks available for the character generator, and there’s no good way to get it there other than manual entry for a lot of it. Granted, there are opportunities for scripting, and I’m trying to leverage these as much as I can, but the bulk of the data isn’t like that.

A good example of a scripting opportunity I took advantage of recently would be the progression of a characters base attack bonus and their saving throw bonuses. What these represent is an abstraction of a character’s martial prowess as well as their resilience to various ill-effects opponents might try to hit them with. All classes have a mixture of strength in four categories: Base Attack Bonus (BAB), as well as Fortitude, Reflex and Will saving throws. While each class has a mix and match of aptitude in these four things, each of the stats has a few progressions they follow. For BAB there is a slow, medium and fast progression, and for the saving throws there is a slow and fast progression. This means that I can write a simple script that is a lookup table of a classes progression for these four things, and then know what the bonus should be for each character class at each level, which can then be used to generate a database table containing the bonuses in these things. Nice and easy, and easily extensible. As an example, a Barbarian has a fast BAB, fast Fortitude, slow Reflex and Will. Knowing that I can crank out an entry for each of the 20 levels a character could take in Barbarian and have a nice simple lookup for each level. I’ll know that a 20th level Barbarian has a +20 BAB, +12 Fortitude, +6 Reflex and +6 Will.

A good example of the kind of thing I have to enter manually would be Feats. There are hundreds of the damned things, and they do everything from something as simple as adding static bonuses to a particular skill check to changing the way rules work. For example, metamagic feats allow characters to alter the effects of spells at the expense of making use of more of the caster’s daily spell-casting resources. Worse yet, some will add bonuses for specific circumstances, such as using a particular weapon, which would need to be accounted for on the character sheet when outfitting the NPC. It’s a PITA. But the worst thing about it is that there is no logic to it. While feats chain together, there’s no programmatic way to know what one feat will do based on it’s predecessor, at least, not in a way that you can write a script for. Short of writing a script that goes and replicates all of the details of each feat; an obviously bad idea. So instead, I get to manually fill out some of these fixtures by hand. The nice thing is that the Django Admin functionality makes it easy to fire up a test server and use that to populate the various fields for all the feats (and other models I need to create data for). But it’s a manual data entry task that is an hours long undertaking. Michael has mentioned trying to outsource it, and I’m tempted, but I also figure I’m still going to have to go through and proof-read it all, and I just don’t have a lot of confidence I’ll get decent work out of some random stranger. He could be right though, and maybe we should just cough up a little money.

At any rate, all of this is taking up a lot of time. I find it very satisfying to write a script to generate all the entries I need (I’ve got some pretty cool ones that created fixtures for weapon and armor enchantments), but am not so enthusiastic about the data entry stuff. Here’s hoping it will all be worth it some day.

On to the second part of where I’ve been putting my attention: designing the actual NPC generation. This has been an interesting puzzle to solve. It is my hope that I can write a generator that is perfectly generic, and doesn’t require a lot of if/else clauses to deal with class specific carve outs. At first glance, there is a lot of stuff that seems to be class specific. They often get bonus feats that allow them to select from specific choices, they get special abilities that other classes don’t get and which often change the way the rules function and many of them get spells, spells which have availability limited by the character class. Additionally, there are a lot of choices that all characters get to make, but which are informed by the classes they’ve taken levels in. A martial character might want to increase their strength, while a caster might go for intelligence or charisma. At first, this makes it seem like there is a ton of class specific logic, and my initial idea was to create an abstract base class that would define the API for a character generator. Then I would write a character generator for each of the classes that would inherit all of the methods of the base class and implement them with class specific logic. This seemed like a decent idea, but was going to require me to write at least 10 classes all with very similar logic, but different decisions.

I would prefer to avoid violating DRY principles here, and so instead, I’m trying to find a way to make all of my logic generic. I think I can get it to work for a large portion of the generation tool. It does involve having if/else  logic to check for all of the classes, but I’ve tried to put those decisions into helper functions to obscure it some in the primary code base. The trouble still though is the class powers that accrue as a character gains levels. These are a pain, because they sometimes change bonuses, require decisions, and inform other decisions (like feat selection). At the moment I’m planning on writing a class power utility for each of the classes. Not my favorite, but there doesn’t yet seem to be a way around it. It will have the advantage of grouping all of the common decisions together in one area and making it much easier to edit / maintain in the future. It still doesn’t feel right though. I want it to be perfectly generic if possible.

That said, I feel the seed of an idea forming. I’m hoping I can write logic that will parse all of this stuff and database models that will essentially inform the decisions the logic makes based on the character class in question. I don’t have anything substantive yet, but my goal would be to be able to just add some new entries to the database to add new character classes or sourcebooks rather than have to go and edit the code later on. It should also make maintainability a lot better. Lastly, it should speed development way up if I can pull this off. I can feel like I’m getting close, but the details haven’t quite come to me yet. I’ll be sure to share once I get there.

 

Using Pycharm With Django

The IDE I’m using for development on this project is Pycharm, published by JetBrains. They publish a community version of the application and it’s a really nice IDE. I’d highly recommend it for anyone looking for a nice Python IDE.

One sticking point I have though, is that the community edition doesn’t really support Django. This is pretty easily gotten around by using their configuration editor to set it up though. In my case, I’m using the Django test framework, so I had to set up a configuration that would invoke ‘manage.py’ (a really useful utility script supplied by Django) and run my test suite. It’s pretty easy. Basically just make sure you’re pointing to the right working directory, you’ve told Pycharm to run manage.py and you pass the correct parameters to the script. In this case, test with the directory of the app I’m developing as the working directory. You can of course do this through the shell, but I like Pycharm’s debugging tools, and using this method lets me continue using them.

Concerns about Python & Django

One concern I have for this project is that, as Michael pointed out, this is a fairly processing heavy application compared to many web apps. We’re not just fetching news articles and displaying them for the user, as was the original use case for Django, but are doing a fair bit of decision making each time a person creates a character. I’ll have to get it all set up and under load before I can make any conclusions, but I’m worried that the app might get bogged down if a lot of people are all creating characters.

Still, that would be a good problem to have, and we can look at making changes to it if needs be. For now, I’m going to forge ahead. Hopefully soon I’ll have my database all set up and my perfectly generic logic written.

Deploying WordPress

Having managed to successfully upload a new, albeit simple, home page for my freshly purchased website, I decided it was time to aim a little higher, and get a real site published. My initial thought was that I would throw something together in Django, not because it was the fastest path to putting up a site, but just to continue working with the platform. Frankly, publishing a blog / mostly static site is a much easier task than the NPC generator, and it would be nice to have something I can display publicly to support my claims.

Sadly, this was not to be. Long story short, Namecheap does not have Django installed on their shared hosting servers. My options were to either move to a more expensive plan (I’d rather not right now) or to follow the instructions posted here to install it myself using virtualenv. I was tempted, but for the fact that Namecheap doesn’t make any promises about it working, and it was starting to look like I might be wading into a quagmire.

Instead, I chose to go with the practical decision, and Michael’s advice, and just install WordPress. The goal, after all, is to put up a personal website as a combination resume & place to write my thoughts. It turns out just shrugging and installing WordPress is stupidly easy. Using the control panel supplied by Namecheap it was just a matter of changing the PHP version to 7.0 (again, Michael’s advice) and then installing the latest version of WordPress, again through the control panel. All told it probably took me like five minutes. You could probably do it faster if you didn’t bother to read anything.

Once WordPress was deployed, I started poking around. Say this for WordPress, you can figure out most of the basic stuff just by clicking around and paying attention. It wasn’t long before I had figured out how to add / remove pages, edit content and post blog entries. I havne’t tried doing anything to the overall style of the site yet, but I did purge the images of food (lest someone mistake me for a hipster) and replace them with pictures of our dog and digital sweet nothings for the GF. Again, a man takes his brownie points where he can get them. And who wouldn’t want to see huge pictures of our beagle? Put your hand down.

All told, getting all this up and running was pretty easy and fun. The same goes for setting up my email accounts (except it was especially fun). The last outstanding thing I need to take care of are my site certificates, and I should probably switch to https. I keep getting complaints that the certificates are invalid, so I need to look into setting all of that up. I’m hoping there’s just a configuration option or something I need to turn on with Namecheap.

Once that’s solved, it’s a matter of designing the site to serve its purpose (though I’m tempted to squirrel the current version away somewhere for posterity’s sake). Then I can start linking to it and spamming it around. Fun!

Lastly, a word about the Python / Django project. I’m still working on it, rest assured. It’s currently in a phase where I’m doing a lot of work setting up the database. This is mostly just data entry. So far as I know, there isn’t any good digital copy of all the bits and pieces that I can parse through to sift out what I need. Boy don’t I wish there was. Granted, the d20PFSRD is (or was?) a thing, but it feels dirty to do something like lift their database for my own use. I guess I could ask if they’d mind, but at this point, I’m so far into doing the way I have been, I may as well finish (textbook sunk cost fallacy!).

At any rate, I’m getting to the point where I can shift from the DB to developing the API for the front end to call into and the site can start producing actual effects that would make it worth publishing. I think I’m going to curtail some of my original targets for the sake of getting a prototype out there sooner, and I’ll talk about that some at a later point. Basically, there should be something coming…soon.

So You Wanna Deploy A Website?

Okay, so here it goes. I’ve decided I’m going to put up a website. While I’ve got quite a bit of work done for my original project idea, there’s still quite a bit left to do. There’s also a lot left to learn, much of which can be done in tandem with the core work I’m doing on the project.

So, here’s the plan for now: I’ve got a decent handle on Django, but I’m still missing knowledge of some pretty key issues that I’m going to need to figure out. And I mean basic stuff.

Today’s problem: How do I actually put something on the Internet so that people other than me can view it in their browser (and without compromising my home network)? If you’re reading this, we can all safely assume I’ve succeeded.

The Setup: So, I’ve gone ahead and purchased hosting from Namecheap. I bought my domain names from them and they seem nice enough, so what the hell. There are probably better choices, but in this case I’m just putting up a simple personal site, and if Namecheap can’t handle that then I’d be shocked. I bought the domain name for the site (where you’re reading this) as well, and the total was something like $20 for the year. Not too shabby.

The first step was to just upload a simple html file that would resolve when navigating to my freshly purchased domain: www.richard-smart.com. Looking at the documentation from Namecheap, they recommend using an FTP server, though they provide several other options. I’ve used FTP before, so I figured I’d just go with that, and installed Filezilla. I had to set up an FTP account using cPanel (this seems to be the hosting tool provided by Namecheap, but I’m not really sure, and haven’t bothered to look into it yet).

Some things that jumped out at me during the process of setting up an FTP account: Namecheap automatically creates default FTP accounts that you can’t delete (but that I could have used). I found this mildly irritating because 1. They didn’t mention that in the linked guide and 2. they provide you a username and password which it doesn’t look like I change. I hope I’m wrong about it, because I don’t love being emailed account credentials and then being unable to change those credentials. As I type it, it occurs to me that I must be able to change them. It’s madness otherwise.

Anyway, the process of setting the account up is simple enough, though a touch vague. Anything I want to appear publicly has to go into the ‘public_html’ folder, but it’s a little unclear when I create the FTP account if I have to give access to that folder specifically or something above it. I have a lot of questions, like: Do I even need to do this? (I don’t think so), what directory should I give the account access to? (I mirrored the admin account) and can I change the account’s access if I get it wrong? (I think so). But I’ve got a mission to accomplish, and refuse to be sidetracked. Beyond the bevy of questions, setting things up is easy enough and Filezilla is quite easy to use. Flush with victory I upload my newly created ‘index.html’ with a loving message to my girlfriend and go back to my browser to refresh the page.

I hit F5, and waited with bated breath. Moments later, up comes…Namecheap’s default landing page. I had assumed ‘index.html’ would be the default, and quickly verify that should be true. A few minutes of reading, and I find myself on a page explaining how to change some configuration files, which looks easy enough, but lucky for me, some helpful commenter pointed out that this is usually because of browser caching, and deleting my browser history will fix the problem.

I give it a shot, and presto chango! My professed undying love is displayed for all the world to see. Naturally I email the link to my girlfriend (I paid good money for that site, you’re damn right I’m going to get some brownie points out of it!), and kick back in my chair.

I’m happy that I managed to get it all working. I’ve taken the first step, and an important one! But already my mind has turned to the next task: How do I get it to run a process…

The Beginning

Welcome to the inaugural post of my new blog. In short, this post, and all that follows will be about programming. Well, mostly that I think. More specifically, it will be about learning new programming skills. Even more specifically, it will be about learning how to build a RESTful web app and working with the Django web framework for Python. At least at first. I’m sure I’ll move on to new topics soon enough. I’m usually studying several different subjects at once, and I’m sure I’ll want to write about some of them at some point.

I’m not new to programming, but I have never done anything for the web. As an electrical engineer, most of the tools I work with are low level, or at best, for the desktop. Mostly we concern ourselves with making LEDs blink. Publishing things to the web is just not something that lands on my plate often. But I want to get better at it, and delve into it more.

There are already a lot of blogs, a lot of really great blogs, covering everything about programming and Python, and they are a great source of information. I am not aiming to add much to that pool of knowledge; how could I? Instead, I’m looking to offer a source of commiseration. I’m going to do my best to update my progress and thoughts on my learning and project every week in the hopes that somebody out there finds a kindred spirit or a touch of relief in finding out that they’re not the only one. And maybe, just maybe, one day I’ll write a post that teaches somebody something. But let’s not get ahead of ourselves.

I also need to add that this post was written some time ago, and just recently revised before being published. I started working with Django some time ago and would chip away at it here and there. I would take vacation days and just work on it. But, as so often happens to side projects, it started to languish. I would resurrect it from time to time and work on it more, but it was mostly back-burnered. The project has taken a lot longer than I expected largely due to getting caught up in other hobbies, as well as having a hard time working all day and coming home and working some more. I love programming, but I have a lot of other activities I enjoy, so tacking on two more hours of development at the end of the day was a struggle for me a lot of the time.

Anyway, I’ve tried to revise this post, but if the tone seems a little weird, now you have some idea why. I promise I’ll be more coherent in the future.

About my project

So, the best way to learn is by doing. Sometimes. And so, I’m working with my friend Michael (who’s name was changed from Michael to protect him) on building a SaaS project. In brief, the project is intended to be a marriage between my love of tabletop RPGs and technical projects (in this case web development).

One sentence summary: We are building a web app that will provide a number of tools and random generators that will reduce the prep time for all the overworked gamemasters in the world significantly each week. In return, they will give us money. All their money! Muahahaha…wait no. Michael informs me it will only be some money. Color me disappointed.

So that’s the dream anyway.

To begin with, we’re looking at creating an NPC (Non Player Character) generator for the Pathfinder roleplaying system. These are the various supporting characters a person running a game might use to flesh out their stories, and sometimes they need stats for those characters. The problem? Making those characters can become a major pain. It can be time consuming and complicated, and as the game gets more advanced, the work to create those characters grows.

Our goal is to remove that pain point. The idea is that while the characters will be randomly generated, the character creation algorithm will make coherent decisions so that while the generated characters might be odd, and poorly optimized, they won’t be useless and should be both unique and interesting.

The difficulty in building this is that making characters in Pathfinder is based around a set of rules that are then bent, broken or ignored as the characters advance in power. Basically, it’s a system defined by exceptions to the rules. This makes it a pain to try and write generalized algorithms that aren’t full of conditionals and carve-outs.

Why Python and Django?

I’ll keep this pretty short. We chose Python because it is a language I wanted to learn, and it has a lot of general usefulness for me professionally, and frankly, is just a great language. While the project has languished some over time, I have been using Python at work routinely for various things, like task automation and testing, and have pretty much fallen in love with it.

Once the decision to use Python was made it was pretty much a choice between Django and Flask. A good case can be made for either, so we elected to go with the one with a cooler name (sorry Flask, good but not good enough). In all seriousness, Django has a strong community, good release cycle, a lot of built in functionality and good online docs. But I won’t pretend it wasn’t a fairly arbitrary decision. We were both noobs as far as Python is concerned when the project was first started, and we had to pick one, so we did.

There’s also a bunch of other stuff we’re using that I know nothing about. That’s Michael’s domain. I should probably mention that he’s a web developer already, of the PHP persuasion. One of my short term project goals is to get up to speed with what he’s been doing. Once I get there, I’ll talk more about that portion of the technology stack.

About me

I guess it’s probably a good idea to share some information about myself. Out here, on the the Internet. For all of you lovely people.

Let’s start at the beginning. I was born in a small city by the name of Portland, Maine and…Nah, just kidding. But a little bit about me for context: I’m an electrical engineer with a minor in computer science. I also hold a writing degree (well, Media Studies with a writing concentration if you’re nitpicking), and am a native, and recent expatriate, of Maine, or the least known province of Canada as far as most are probably concerned. I moved to Raleigh a few weeks ago, as of the time I’ve published this, and have been settling in to my new (much warmer!) city.

In Maine, I worked at a semiconductor company and an industrial automation company. Both were old guard companies where I got to work with some great people and work on some interesting projects, but ultimately neither of them was quite what I was looking for.  The same goes for the employment climate in Maine.

Now I’m in Raleigh. I’m still looking for work, and while I’ve got the freedom that comes with being unemployed, I figure it’s time to start working on my project again and bring some of these ideas to fruition, including putting up this site. Writing is a long lost love of mine, and I’d love to make it part of my weekly (though probably not daily) routine again.

Getting a little personal: I feel like I’m at another one of those crossroads you come to in life. There are a lot of ways to jump, and the easy one is rarely the one you should take. There are opportunities for electrical engineers in my new home city, but there are a lot of opportunities for software developers, and if I’m being honest, I find software to be far more interesting work. Engineering is great, but it also comes with a lot of tedious tasks. I don’t know that I’ve ever enjoyed doing layout reviews or Bill of Materials reviews. But they’re so crucially important that you can’t afford to give them anything other than your full attention.

I’d like to shift course in my career at this point, but so far I’ve been having a bit of a tough time. There’s more competition in this market, I don’t have a social network yet and on paper there are a lot more people who look better than me. I think I’ve got good programming chops, but the challenge right now is just getting people to talk to me. So I need to prove myself, and I can’t think of a better way than having something to show.

So here I am, living in a new city, looking for a job and no other major demands on my time. I need a way to convince people I’m worth talking to, and I’ve got what I think is a good project idea. There’s nothing for it but to begin…again.

Here we go.