Angband Forums

Angband Forums (http://angband.oook.cz/forum/index.php)
-   Variants (http://angband.oook.cz/forum/forumdisplay.php?f=4)
-   -   Pyrel dev log, part 2 (http://angband.oook.cz/forum/showthread.php?t=5607)

Derakon July 25, 2012 02:38

Pyrel dev log, part 2
 
In deference to Magnate's insistence on using the threaded forum display, which no longer handles the old thread properly, here's a new dev log. I managed to grab some spare time during my vacation to hammer out new level generation. This includes basic item allocation (scaling appropriately with dungeon level), preservation of persistent objects across levels, and a rudimentary system of rooms and corridors:

http://derakon.dyndns.org/~chriswei/...l/dungeon1.png

At this point, I think I can plausibly open up Pyrel for other people to hammer on. It is absolutely not bug-free, though I've tried to fix bugs as I find them. It's also not really a "game" yet, so unless you want to work on the code I don't really recommend downloading it. Speaking of downloading, have a download link for a gzipped tarball of the source code.

Of course, distributing the source via tarball downloads isn't really a good long-term solution. I know most Angband development is on GitHub right now, but any thoughts on using Google Code instead? It provides some nice project-management stuff (bug tracking and a wiki, for example) -- you can see some of what's doable on my old Jetblade project page. Also, I tend to favor Mercurial over Git (mostly because Git's mnemonics for commands make no goddamn sense), though I recognize that most of y'all probably have zero interest in learning another basically-equivalent-to-Git version control system. Making a Google Code project would also require me to select an open-source license to start out (with everything added to the project automatically being stuck under that license). GPL v2 or GPL v3 would seem to be the obvious options; you can see them all here.

Thoughts?

I can't guarantee I'll be online much through the next weekend -- vacation and all that.

Nick July 25, 2012 11:22

Sangband uses Google Code.

ekolis July 25, 2012 16:21

Bitbucket doesn't require you to choose a license... :)

Magnate July 25, 2012 23:23

Oh nooo!

Congrats on releasing it - really glad it got this far.

Curse you for opening up a project management debate! But I'll use whatever you decide on. It's not like it's crucial that it can share github code with angband anyway!

Derakon July 28, 2012 03:42

The main concern with GitHub vs. something more centrally controlled is how "interior" project development would be handled. I'm going to consult with some of my more knowledgeable friends about this before making a decision one way or the other.

In the meantime, I've done some work on creature allocation on new levels. Creatures have a "rarity" field in their records (same as in Angband). The larger the value, the more common the creature. What I'm doing right now is dividing that number by 2 for each level out of depth they are (i.e. monsters native to level 40 are half as common at level 39 as they are at level 40), and subtracting 1 for each level too deep they are (i.e. a monster that gets 100 slots and is native to level 40 gets 100 slots at level 40 and 99 slots at level 41). In other words, exponential decay on the "hard" side, linear decay on the "easy" side. Of course the divisor, and the addend, can both be tweaked for balance purposes.

I've no idea how Angband is currently handling this, for what it's worth. This seemed simple and was easy to implement though.

Now, I need to add some filters to the code. Specifically, I need two things:

* a "never allocate" rule for the Player record.
* a "only allocate once at a time" rule for creatures with the UNIQUE flag.

I can see doing this two main ways:

1) Have special flags for these records (c.f. UNIQUE), check for those flags in the code, and behave differently depending on their presence.

2) Allow records to have "allocation filter" entries, which refer to functions that must be called when we try to add the corresponding creature to an allocation table. If the function returns false, then the attempt fails.

The latter case is obviously more flexible, and of course there could be other filters (a drop filter for item allocation is an obvious example). Filters would presumably be implemented somewhat like procs, except that the functions called would have meaningful return values. However, this approach would be rather more work, at least at the outset. Thoughts? Am I missing a third alternative approach?

Nick July 28, 2012 04:00

Quote:

Originally Posted by Derakon (Post 71343)
2) Allow records to have "allocation filter" entries, which refer to functions that must be called when we try to add the corresponding creature to an allocation table. If the function returns false, then the attempt fails.

The latter case is obviously more flexible, and of course there could be other filters (a drop filter for item allocation is an obvious example). Filters would presumably be implemented somewhat like procs, except that the functions called would have meaningful return values. However, this approach would be rather more work, at least at the outset. Thoughts? Am I missing a third alternative approach?

I think this is an excellent approach. I already have a hackish version of this in FA, where probabilities are modified or exclusions are made during get_mon_num - but on monster selection from the table rather than before building the table.

I like your approach much better, and will implement it in Beleriand, where monster allocation was going to need a big rewrite anyway, and eventually in FA.

Derakon July 28, 2012 05:41

I should note that one big drawback to the generic filter-function approach is that the creature records may get somewhat repetitively verbose. For example, if UNIQUE is implemented as an allocation filter*, then we'd see this in the record for every unique creature:
Code:

{
    ...
    "filters": [
        {
            "trigger": "onAllocation",
            "function": "onlyAllocateOnce"
        }
    ]

It seems reasonable that common patterns should be moved from the data files to the main code so that they can be readily referred to by shorthand in the list of creature flags. Hm...or perhaps the list of filters could be polymorphic -- accepting both dictionaries and strings, with the strings assumed to refer to previously-templated functions. Parameterizing those functions would be more difficult, but I expect in many cases (as in this one) there would not be much need.

* And I just thought of a problem -- Pyrel allocators are currently generate-once, use-multiple things, i.e. a single allocator is made at the start of level generation and is used to make all creatures on the level. This is obviously incompatible with unique monsters, so either I need some trigger to invalidate the current allocator, or I need a second pass to prevent generation of creatures even if they're in the allocator table, which sounds like what Nick was complaining about.

EDIT: I've made some more changes, not reflected in the tarball:

* Creatures can (and are) allocated on level creation. Trying to allocate the player will print a harmless error message; "unique" monsters can be multiply allocated.
* Added display information for all monsters who have special characters in their name. Apparently the code I wrote to convert Angband monster records to Pyrel creature records barfed on those in a rather specific way.
* Changed the message window so instead of capturing stdout it requires you to call a specific messaging function; thus, stdout can be used for debugging even if the UI is hung.
* Minor code refactoring and removal of some deadwood.

The codebase is currently 3338 lines long, of which 787 have comments and 559 are whitespace.

other July 28, 2012 13:13

Would it be reasonable to add fields to the monster record for "Max_at_once" and "Max_ever"? A Unique would then be a special case with both those at 1, while something like RingWraiths might have both fields at 9, and a monster that avoids others of its kind (Great Wyrms?) might have Max_at_once = 1, but unlimited total population.

You would then need to keep track of the number of live instances of a given monster, as well as the number killed; the allocation routine would have to check that creating a monster would not violate either limit.

Derakon July 29, 2012 06:18

other: such functionality would be handled as part of the filter definition in the monster record, yes. You could come up with any kind of filter you like, for example that Black Orcs and Uruk-Hai would not show up on the level simultaneously (because of rivalry between Sauron and Saruman, hypothetically-speaking). It'd just have to be coded up.

I went ahead and created a project on Bitbucket for Pyrel. Bitbucket is, more or less, Github but for Mercurial instead of Git. It has a similar pull-request functionality, as well as a wiki and issue tracker, so I think it should be all that's needed for now. Please let me know if you encounter issues trying to use it. Of course, that particular project is under my username for now; I should probably sort out how to make an "official" (i.e. unattached to a user) project. But it's not a high priority.

And Pyrel is now backed up to someone else's hardware, so there's a bit of peace of mind.

Nick July 30, 2012 12:31

Actually, having read the post properly, I'm not going to do 2. I'm going to do a kind of a hybrid, I think, where I read flags from the record and then have a filter function (same for all monsters but depending on flags) prior to table allocation. I think approach 2 in C would probably suck. But thanks for making me think about how to improve it.


All times are GMT +1. The time now is 15:11.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2017, vBulletin Solutions, Inc.