rangifer’s diary: pt. l
Hooray for the 50th installment of rangifer’s diary :)
This 50th installment coincides with another one of MapleLegends’s infamous patch maintenances, so there won’t be anything in here about gameplay. Instead, I want to take this time to reflect on the diary itself, talk about a few MapleStory-related mini-projects that I work on or have worked on, and start a new expository series that will be replacing the “R>1 pog ___ for ___ run” series that I concluded in the previous entry.
A reflection on rangifer’s diary
Back when I very first started this diary, I had the itch to start a new character. For a little while, I held off from doing this — I already had, by this point, my STR priest cervid, my woodswoman capreolina, my I/L magelet cervine, and my swashbuckler hydropotina. I also technically had my besinner hashishi, although I hadn’t started playing her (yet). So I was hesitant to add another to this list, but eventually did it anyways (lol). I actually held a small online poll where people could vote for what character I made next: either a DEX spearwoman (who I would later end up making anyways, by the name of rusa), or a pugilist. And the pugilist won, and so rangifer was destined to be born.
At around this same time, I had started a forum specifically for the Oddjobs guild, and not too long afterwards, started the Odd Jobs Community Thread on the MapleLegends forums. So, at this point, both the Oddjobs forums and the Odd Jobs Community Thread were pretty barren. I was inspired by kuromii’s journal, which I found after getting to know kuromii in-game, and had the idea to try my hand at a diary of my own. And so, since almost everything that I was doing had to do with odd jobs anyways, I decided to start posting my experimental diary on the Oddjobs forums and on the Odd Jobs Community Thread.
Earlier entries in the diary are more clearly influenced by kuromii’s journal; rather than making use of colour variations within the text and the use of smilies/emotes to highlight parts of the text and add eye candy, I was able to do this in plain text through the use of emojis (particularly, only those approved as part of Unicode). Also, in these earlier entries, I tried to make the entries daily! So I aimed to make each entry after a day of Mapling, and the entries were thus shorter, and made it easier for me to remember what I had done.
Eventually, these characteristics of the early diary entries were shed. The emojis were something that I was always a little iffy on; I quickly started to think that they might just be distracting and unnecessary. Furthermore, the MapleLegends forums (which are based on XenForo) do not accept Unicode codepoints that cannot be stored in a single UTF-16 code unit (so basically, no surrogate pairs), which thus excludes almost all emojis. So there was some nasty breakage when posting on the MapleLegends forums (although the Oddjobs forums and the Markdown renderings on Codeberg were just fine). And trying to post a single diary entry after each day of Mapling grew too cumbersome, so I gradually became more and more lazy until my diary posts were simply sporadic. As a result, although this is a special edition of rangifer’s diary, there isn’t really a significance to it being the 50th entry. More of the entries are concentrated in the earlier days of the diary, with them being more sparse (but larger and more time-consuming) as time has gone on.
With these changes away from the original model of the diary, a few thigns have also happened:
- Each diary entry has become more elaborate, and more time-consuming to make. Sometimes I think that I spend too long on these things, but the benefit of being able to reflect back on my thoughts and adventures in the Maple world is great, and I have continually been encouraged by those who do read my diary. I never expected my diary to have much of an audience at all, and if you’re a reader of this diary, I want to personally thank you very much for reading and supporting my Mapleventures!! <3
- The narrative portions of the diary entries are much more image-directed. What I mean here is that I have to take screenshots of the stuff that I do. If I don’t, chances are that I will forget almost all of it, and the diary entries could not be nearly as detailed as they are now. Even now, I will inevitably forget to take screenshots sometimes, and so there are some things omitted from my diary entries that would be in there if I had just managed to snap a shot! And, as a result, my diary entries have become more dense with images, which can be a bad thing, although I suppose the extra eye candy is nice. :)
- rangifer has, ironically, become my only real “failed” character so far. I’ve never really addressed it within the diary itself, because it’s normal for me to not play at least a few of my (approximately) 129078409236784 characters, in which case they simply don’t feature in the diary. But rangifer, in particular, has become somewhat of an abandoned project for me. She still exists, but for a whole host of reasons, I decided that I don’t enjoy playing her anymore. That being said, I did have an absolute blast playing her for the time that I did. Some have suggested (although, not before I thought of it myself) renaming the diary. The diary no longer focusses on rangifer, as it did in the earliest entries, and in fact, it doesn’t feature her anymore at all. So, seemingly, a better title would just be “deer’s diary”. But, rather than renaming the diary entirely, I want to retain its original title, as it is still correct — rangifer was the originator of the diary, and so it remains in her name, even post-mortem — and I also don’t want to break any URLs. :P
And, just to wrap this section up real quick, I want to ask the question of where this diary is going in the future. The answer is, of course: nowhere, and anywhere! I plan to continue sporadically adding new entries, as usual, in the usual style. And the Maple fates will guide me on my Maple journey. :) So thank you for reading!!!
Taxonomising odd jobs, pt. i: What even is an odd job, tho? §1
Preface
So, the next big expository series that I want for this diary is about taxonomising odd jobs. Lot of things are taxonomised: genres (of video games, music, comedy, film, literary works, etc.), stars, chemicals, computer architectures (and their instructions), formal languages / abstract machines, numbers, foods, and so on and so forth. It seems that the human capacity for taxonomisation (which we might also call typification, or categorisation) is unlimited. Taxonomies are perhaps born of human psychological necessity — so much so, that anthropologists often study humans in terms of their folk taxonomies (see also: ethnotaxonomy), which are deeply reflected by the humans’ use of natural language.
When it comes to the word “taxonomy” in particular, the most common use is in the context of biological taxonomy. Like all taxonomy, biological taxonomy is based on the use of mathematical sets. Certain individuals (in this case, individual biological organisms) may (or may not) be a member of a particular set, and it is this membership relation which defines where the individual lies within the taxonomy, and ultimately, defines what the structure of the taxonomy looks like. Some individuals may be members of more than one set, either because one set is a subset of the other, or simply because the sets have some nonempty intersection with one another. But the structure of modern biological taxonomy is special, in some ways. The sets that fundamentally make up biological taxonomy are called, appropriately, taxa (singular: taxon), and each taxa is generally assigned a particular rank; this makes biological taxonomy hierarchical. And, furthermore, the structure of biological taxonomy is phylogenetic; particularly, a given taxon is almost(!) always a proper clade, which includes a species (known as a “common ancestor”), in addition to all decendants of that species. This makes the structure of biological taxonomy somewhat more “objective” than a taxonomy that is built on the basis of, say, the practical use of its members, or on the basis of the common names used for its members. But this also imposes another relationship onto the taxonomy: that of decendancy. In order to have a “tidy” biological taxonomy, we have to properly define what decendancy even means, and we also have to figure out how we would, at least in principle, detect its presence.
But before we get into something as deep as decendancy, we have a more fundamental problem on our hands: defining the universe. No, not the universe in general, but the set-theoretic universe of our taxonomy. This means answering the question: “What even is an odd job, tho?”. You might think that this question is pretty straightforward for the biological taxonomy case; after all, only species of organisms that are made of biological cells (either prokaryotic or eukaryotic) are living biological organisms, right? But actually, acellular life is now generally recognised (although remains controversial), the most prominent example being viruses. The issue for us, however, is that deciding what is (and therefore, what is not) an “odd job” is probably even more difficult than in the biological case.
So, first things first, I need to give some disclaimers and some caveats:
- The views that I express in this series are my own. Obviously. As a result, you may reasonably disagree with what I have to say here.
- I may revise the views that I express in this series, over time. This is particularly true due to the next item on this list.
- I do not have the contents of this entire “Taxonomising odd jobs” series already written or planned out. This is in my diary (serialised as sections, with one section per diary entry) because of the informal, stream-of-consciousness nature of the series.
Primitive definitions
Oh, and also, unfortunately we have to do some basic definitions first. Normally, we use terms like “job”, “class”, “build”, etc. are used in a flimsy way that works well enough when we are imprecisely talking about MapleStory characters in a specialised context. Here, we want to talk about these things abstractly and precisely, so I’m going to be making some definitions (some of which may inevitably sound weird).
- Build: The way in which a MapleStory character is designed (intentionally, or unintentionally; planned in advance, or not), which encompasses all of (and only) the following:
- What class progression the character takes.
- How the character allocates their AP.
- How the character allocates their SP.
- What equipment the character uses (this can be in terms of general categories, like “bows”, “two-handed swords”, “overalls”, etc., and/or it can be in terms of individual items that have individual item IDs).
- What skills the character does and does not use.
- The location of the character (some characters are restricted, by their build alone, in their ability to enter certain maps).
- Class: The class of a character is in one-to-one correspondence with the label given by the game, to the character. From a first-person perspective, this is in the bottom-left corner of the screen, and from a third-person perspective, it can be viewed by double-clicking the character and inspecting the window that pops up. The class is also viewable in other ways, like guild listings, party listings, alliance listings, rankings on a given server’s website, etc.
- Examples: Magician, beginner, F/P mage, F/P archmage, paladin, page, outlaw, hermit.
- Class progression: The chronological progression of classes taken by a character, expressed as a finite ordered list which contains no duplicates.
- Examples: Beginner → magician → F/P wizard → F/P mage → F/P archmage, beginner → pirate → gunslinger → outlaw → corsair, beginner, beginner → rogue.
- Grade: The grade of a class is one less than the length of the shortest class progression that contains it.
- Examples: Beginner is grade 0, magician is grade 1, gunslinger is grade 2, white knight is grade 3, bowmaster is grade 4.
- Throughclass: If the highest grade attainable in the game is 𝑔, then a throughclass is a set of classes, which consists of a class 𝑐 that is of grade 𝑔, along with all other classes 𝑏 s.t. a level ∞ character of class 𝑏 who takes all class advancements available to them will necessarily be of class 𝑐.
- Examples: {F/P wizard, F/P mage, F/P archmage}, {bowmaster, ranger, hunter}, {page, paladin, white knight}.
- Job: A job is a kind of build (all jobs are builds, but not all builds are jobs) that serves as the analogue of “species” for our purposes. A given job has an identifiable playstyle that differs significantly, simply, and meaningfully from other jobs, while also not being defined so narrowly as to exactly specify every aspect of what makes a build. Note that this definition is more nebulous than previous definitions; a lot of our taxonomising efforts will be focussed on this nebulousness.
- Examples: “DEX-based archer/hunter/ranger/bowmaster” is a job, although we do not split it out into separate jobs on the basis of, say, whether they max Focus or Soul Arrow first. “DEX warrior/page/white knight/paladin” is a job, although we do not split it out into separate jobs on the basis of, say, whether they use blunt weapons or swords.
- Subjob: A subjob forms the analogue of “subspecies” for our purposes. Members of a subjob are sometimes practically distinguishable from other members of their job, and furthermore, their distinction from other members of their job can be defined simply, succinctly, and meaningfully.
- Hybrid: A build that is a hybridisation of two or more builds (usually, jobs and/or subjobs), that combines the builds by taking key aspects from each build and permanently combining them.
- Examples: Blood dagger fighter, claw-punching besinner, gishlet.
A broad taxonomy for MapleStory builds in general
I first want to break down all MapleStory character builds into a few sets, the union of which is the set of all MapleStory character builds:
- Optimal builds.
- Suboptimal builds.
- Aesthetic builds.
- Odd jobs.
These sets are not pairwise disjoint; that is, the above four sets do not form a partition. Before we talk about which sets are subsets of others, and which sets are disjoint from which other sets, let’s define our terminology (and give a small number of examples) here:
- Optimal builds are not necessarily mainstream builds. I originally had sets for “mainstream builds” and “experimental builds”, but I realised that defining either one of these sets relies on a notion of “the mainstream”, which is just a popularity contest. The popularity contest aspect doesn’t reflect very well on the material reality of the build itself (i.e. how it actually works gameplay-wise), and furthermore, it has the issue of changing depending on the calendar date, what server you’re playing on, the phase of the moon, etc. So instead, we are defining certain builds as “optimal” (or trivially different from “optimal”). An optimal build is associated with a particular throughclass, because optimal builds always achieve — or at least, strive to achieve — the highest possible grade. Then, they are considered “optimal”, given the throughclass that they take. As a result, optimal builds almost always play the game as their throughclass design (as designed by the game developers) suggests, and tailor everything around the most powerful capabilities that their throughclass bestows upon them.
- Examples: STR paladin, INT I/L archmage, STR buccaneer.
- Suboptimal builds are the complement of optimal builds.
- Aesthetic builds are builds that are based exclusively, or almost exclusively, on their aesthetic and archetypical appeal. Aesthetic builds, because they don’t focus quite as much on gameplay, tend to also be suboptimal builds, but are not necessarily suboptimal. Aesthetic builds have no particular relation to other sets of builds, and can intersect partially with just about any set.
- Examples: Any build based around a fixed outfit (and little or no NX equipment to cover it up), any “NPC look-a-like” build.
- Odd jobs are what we’re trying to define here!
- Examples: See https://oddjobs.codeberg.page/odd-jobs.html.
And I think that’s about enough for this entry. See you in the next instalment! :)
…And other things
I’d like to use this final section to just briefly mention some of the little side projects (mostly odd-job-related) that I have. :)
Damage calculator
This one isn’t new, but I have a pre-BB MapleStory damage calculator that is web-based (written in TypeScript) and specifically designed to be as flexible as possible, to handle all the weird (or odd, as the case may be…) edge-cases and combinations. I use this calculator a lot, for personal use, and also for when I was writing the “R>1 pog ___ for ___ run” series! You can check out the calculator itself here:
https://oddjobs.codeberg.page/dmg-calc/
And the source code is in the same repository as the rest of the Oddjobs website:
https://codeberg.org/oddjobs/pages/src/branch/master/dmg-calc
Odd jobs list
Readers of this diary already know about this list, as I link to it frequently in my diary entries, but I do actively maintain an informative (but of course, not exhaustive) list of odd jobs that can be found rendered on the Oddjobs website:
https://oddjobs.codeberg.page/odd-jobs.html
The associated git repository can be found here:
https://codeberg.org/oddjobs/odd_jobs
As you can see, the data is just stored in odd_jobs.json. I have a HTML renderer that is in the Oddjobs website repo, which is responsible for the version you see on the Oddjobs website, and also a simple renderer to Markdown, which is responsible for the rendered version that you can see within the odd_jobs repo itself.
The most recent addition to the list has been the armed brawler, due to the General List of Experimental Classes (which is actually from early 2010), which calls this job “non-knuckle brawler”. To avoid confusion with other brawlers who do not use knuckles (e.g. bullet bucc, pugilist), I invented the name “armed brawler”.
Also somewhat recently, I added a way to rename jobs (particularly, renaming what their primary name is) without breaking URLs that pointed to old versions of that job’s entry. This allowed me to rename:
- STR Assassin → LUKless Assassin.
- Permabeginner → STR Beginner.
- LUK Mage → Magelet.
- LUK Gish → Gishlet.
…All of which should help to avoid confusion!
And I continue to maintain this list actively; if you have a job that should be on here, but isn’t, or have corrections/additions/nitpicks about existing entries, just let me know! In particluar, anyone can file issues against the repo, as well as PRs. Or you can just personally let me know, and I’ll get around to it. :)
The scroll strategist
I have a program that can completely optimise scrolling strategies, using dynamic programming techniques, to help scrollers make informed decisions about their scrolling. Currently, there is only one optimisation mode: this mode absolutely maximises (yes, really; all possible strategies are considered) the probability of meeting and/or exceeding a given array of desired stats. Success is defined as: each one of the item’s final stats (i.e. the stats when the item is reduced to 0 slots) is greater than or equal to the corresponding stat in the goal array. In the case of ties (more than one strategy maximises the probability of success), whichever strategy has the lowest expected cost (only considering the cost of scrolls) wins. I will be considering other kinds of goals in the future, but for now, you can check out this program here:
https://codeberg.org/deer/scroll_strategist
And, right now, there is only one actual application that makes use of the scroll_strategist library:
https://codeberg.org/deer/scroll_strategist_cli
scroll_strategist_cli is a small CLI app that can be used to interface with scroll_strategist. Currently, it supports interactively entering the relevant data (item stats, item slots, what scrolls are available, and the goal stats), and also supports (via -j
/--json
) entering the relevant data by reading it from a JSON file (see example.json for an example). The output can be given non-interactively (with -n
/--noninteractive
), in which case, only the following data is emitted:
- Probability of success,
- Expected cost (scrolls only), and
- The next scroll to be used.
Or, if the -n
/--noninteractive
flag is not supplied, scroll_strategist_cli will interactively walk you through the scrolling process. It will ask you, for each scroll, whether it succeeds, fails (in the sense of: neither booming nor succeeding), or booms. You then get updated info about the probability of success and the expected scroll-only cost.
At some point, I may try to make a web-based (similar to the damage calculator) interface to this. :)
The unofficial “odd-jobbed rankings”
I maintain an informal rankings for odd-jobbed, off-island[1], MapleLegends characters. You can find it here:
https://oddjobs.codeberg.page/rankings/
And the relevant repository is here:
https://codeberg.org/oddjobs/odd-jobbed_rankings
This goes along with all the caveats you can see on the rankings: the rankings are super unofficial, almost certainly contain errors and omissions, etc. New entries (and the removal of entries) has to be done manually, although there is a script for automatic updates (which just scrapes the HTML of the MapleLegends rankings):
https://codeberg.org/oddjobs/odd-jobbed_rankings/src/branch/master/update.py[2]
And a script to verify that the guild listed for each character is correct (which works by a similar strategy):
https://codeberg.org/oddjobs/odd-jobbed_rankings/src/branch/master/guild_check.py[2]
The original impetus for this rankings was to make organising runs easier; particularly, PQs and boss runs. It’s for this reason (and also for purposes of maintainability…) that the rankings only start at level 45+, and that all islanders and campers are excluded[1].
Footnotes for “The unofficial ‘odd-jobbed rankings’”
- [↑] The rankings were later updated to include islanders and campers.
- [↑] Later scrapped and replaced with https://codeberg.org/oddjobs/odd-jobbed_rankings/src/branch/master/src/main.rs.
The odd-jobbed archive
I maintain an archive of MapleStory (both pre-BB and post-BB) odd-job-related content, which can be found on the Oddjobs website:
https://oddjobs.codeberg.page/archive/
And the relevant repository can be found here:
https://codeberg.org/oddjobs/odd-jobbed_archive
This one, as you can see, is rendered from a TOML file (entries.toml). Again, feel free to submit issues and PRs!
Gish AP calculator
⚠️ NOTE: MACC is extremely poorly understood, and this calculator needs to understand MACC to give useful outputs. Thus, I recommend treating the calculator as mostly theoretical at this point in time. ⚠️
I did some work to help make the gish AP calculator possible — the original code was written in MATLAB by Cortical:
https://oddjobs.codeberg.page/gish-ap-calc/
This calculator allocates AP for you, and exists to try to “solve” — or rather, try to ameliorate — what we call “the gish problem”. Gishes are, as we know now, extremely complex, and creating an effective one (at least, to the standards of what we expect a gish to be) is nearly impossible. This program is designed to make AP allocation a little easier, although for any given run of AP allocations, it has to assume a certain set of gear, set of buffs, skill being used to magically attack, and target monster.
The relevant repository can be found here:
https://codeberg.org/oddjobs/project_gish
Odd job guides
I’ve written some guides on how to build/play certain odd jobs (so far, four such guides), which you can find here (all written in Markdown):
https://codeberg.org/oddjobs/odd_job_guides
Or, rendered as HTML on the Oddjobs website:
https://oddjobs.codeberg.page/guides/
Right now, 3 of these 4 guides can also be found in the “Guides” subforum of the MapleLegends forums. The other one, which cannot be found on the MapleLegends forums (at least, not yet), is Guns To Scabbards, Swords To Holsters: The Swashbuckler.