Skip to the main content
Skip to the entry’s beginning
First published on .

rangifer’s diary: pt. lxxii

Taxonomising odd jobs, pt. v: Hypergraphing. §2

In the previous section (§1) of this part (pt. v), I discussed a bit about what hypergraphs are, and how they could be useful for taxonomising odd jobs. I also explicitly constructed a hypergraph by hand, by listing some 37 or so hyperedges (and commenting on their inclusion). Then, bearing in mind that we want to use our hypergraph programmatically, I gave some of my initial thoughts about representing hypergraphs using data structures.

One of the things that I mentioned when talking about how hypergraphs might be useful — if we think of each odd job in our universe as a vertex — is the possibility of visualisation. In particular, we have — to my knowledge — essentially two options: Euler diagrams and rainbow boxes. I was leaning more towards the rainbow box approach. With so many vertices and hyperedges, an Euler diagram would probably take a lot of clever hand-picked placements. On the other hand, rainbow boxes are at least systematic; Euler diagrams can be made systematic by restricting them to be Venn diagrams (which are just a special kind of Euler diagram), but that requires essentially 2𝑛 distinct spatial regions, where 𝑛 is the number of hyperedges. So yeah, not really doable for 𝑛 > 6 (and it’s already pretty gnarly once you get to 𝑛 > 3).

Rainbow boxes have some of their own issues (as we’ll see here), but, inspired by the example rainbow box given by Wikimedia Commons, I set out to write a program that would generate these rainbow boxes for me. Software already exists for programmatically generating diagrams, of course — but making a rainbow box of this kind, in a reproducible way, was going to mean more than some lines of Mermaid or throwing around a couple rectangles in Inkscape. But I did it anyways, because trying absolutely way too hard is definitely in the spirit of this series. So I want to talk a little about how I wrote a program to do this, before showing some of the results.

The program is very bad

I wanted to get this done really quick and dirty, so that’s what I did. As a result, the code is smelly and bad. If I ever feel like it, I might go back and clean it up so that it’s not a pile of hot garbage, but the time is not now.

So, you know, if you get eye cancer from reading the source code, don’t say that I didn’t warn you.

Data structures

I did decide to construct an adjacency matrix, as mentioned in the previous section (§1), to represent the hypergraph. It comes along with a hyperedge list, which I lazily deserialise (from the input RON file) as a HashMap<String, HashSet<String>> and then pretty much keep it like that, with the exception of duplicating it as a Vec<(String, HashSet<String>)>. It works well enough, I guess, although I didn’t bother to actually optimise… almost anything. So it’s all implemented very poorly, with the only hard limitation being that I make sure never to do anything that could induce superpolynomial behaviour, for obvious reasons.

I sometimes represent vertices by their IDs, and sometimes by their names, and I don’t really keep them very separate. Again, not very optimised. But, in order to go between these two representations, I actually just use an array — the array simply holds a single copy of each vertex name, in ascending lexicographic order. Then, to get from an ID to a name, you just index into the array with the ID as the index. To get from a name to an ID, you perform a binary search. This makes going in either direction take sublinear[1] time (Θ⁡(1) and Θ⁡(𝗅𝗈𝗀⁡ |𝑉|), respectively), which is Good Enough™.

Footnotes for “Data structures”

  1. [↑] “Sublinear” meaning: 𝑜⁡(𝑛).

Ordering the vertices

One thing about rainbow boxes is that each vertex gets its own column, and the order of those columns makes a big difference in how the diagram looks. If you put the columns in any arbitrary order, chances are you’ll have a bunch of unnecessary gaps in your hyperedges (rows). In fact, we can define this as an optimisation problem:

Given a hypergraph 𝐻 ≝ (𝑉, 𝐸), find the permutation 𝑃 of 𝑉 that minimises 𝑒 𝑖 𝐸 𝓒 ( 𝑃 , 𝑒 𝑖 ) .

𝓒⁡(𝑃, 𝑋) is defined for any permutation 𝑃 of a set 𝑆, and any 𝑋  𝑆. 𝓒⁡(𝑃, 𝑋) counts the minimum number of substrings of 𝑃 necessary to make every element of 𝑋 also an element of one of the substrings, while also making each substring only contain elements of 𝑋. For example, given 𝑃 ≔ ⟨a, b, c, d, e⟩ and 𝑋 ≔ {a, b, d, e}, 𝓒⁡(𝑃, 𝑋) = 2, because 𝑃 becomes ⟨1, 1, 0, 1, 1⟩ when checking for membership in 𝑋 — “1” indicates that the element is a member of 𝑋, and “0” otherwise. ⟨1, 1, 0, 1, 1⟩ can, at best, be split up into ⟨⟨1, 1⟩, ⟨0⟩, ⟨1, 1⟩⟩, so we need at least 2 substrings of contiguous “1”s, if we want to cover all “1”s with our substrings while not covering any “0”s.

Actually, because our rainbow box “wraps around”, we’re looking at cyclic orders, not permutations. Think of it like this: we could define four seasons of the Northern year like so:

The nice thing about each of these four sets is that they can be made totally contiguous; you can go through an entire season without any “gaps”. If “winter” were instead defined as {January, November, February}, you would have no choice but to start winter in November, then stop winter so that you could have December (which is now, presumably, not a part of any season at all), and then start winter again for the next two months of January and February. That’s no good. If someone scrambles up the definitions of the seasons (who would do such a horrible thing?), the optimisation problem asks how we can reorder the months (e.g. swapping November and December — making them the 12th and 11th months, respectively — might help in this case) so that we minimise the number of annoying gaps we get that break up the seasons.

The issue is that I, uhm, have literally no clue how to solve this problem. The naïve approach, obviously, is to brute force it. There’s just one slight issue with that: the number of possible values of 𝑃 is |𝑉|!, which is — to use a highly technical phrase ­— very extremely bad. More specifically, I think a straight-ahead brute-force method ends up taking 𝑂⁡(|𝐸|⋅|𝑉|⋅|𝑉|!) time, or something like that. The point is that it’s definitely Ω⁡(|𝑉|!). So instead, I used a heuristic method…

The idea here is to rank each pair of vertices (all ½⁢|𝑉|⁢(|𝑉| − 1) of them) by their “shared degree”, that is, the number of hyperedges that are incident to both vertices. We start with the empty sequence ⟨⟩, then go through the ranking (in descending order of shared degree), adding the pairs to the sequence as we go. Each time we “add a pair”, we don’t necessarily add two new elements to the sequence; we do that only if both elements of the pair aren’t already elements of the sequence. If one is already in the sequence, but the other one isn’t, we add the latter one to the sequence, either directly preceding the former, or directly succeeding it (so that they are adjacent to each other). If both are already in the sequence, we do nothing. If neither are already in the sequence, then we append both to the end of the sequence (again, so that they are adjacent to each other).

You can see my crappy implementation of this algorithm in order.rs, but here’s some nifty pseudocode anyways:

define heuristic_permutation(M : adjacency matrix) → permutation of V:
    pair_ranking := ⟨⟩

    for each i of ⟨0, 1, …, Dim(M) - 1⟩:
        for each j of ⟨i + 1, i + 2, …, Dim(M) - 1⟩:
            pair_ranking ← (i, j, |M[i, j]|)

    sort pair_ranking in descending order by the last element of each triple

    P := ⟨⟩
    for each i, j, _ of pair_ranking:
        if |P| = Dim(M):
            break

        if i ∈ P and j ∉ P:
            insert j into P, immediately after i’s position
        else if i ∉ P and j ∈ P:
            insert i into P, immediately before j’s position
        else if i ∉ P and j ∉ P:
            P ← i
            P ← j

    return P

Does this actually produce good results? I mean, it’s probably better, on average, than picking a permutation at random. Maybe…? Aaaand that’s about as far as we’re gonna go here.

Colours

We are making a rainbow box here, after all. We’re going to need a lot of colours. What is a colour, anyways? As it turns out, you can write (and many have written) nearly countless tomes on such a subject — it’s quite complicated! But I’m no expert, so I did a little bit of digging around the WWW for a cheap hack that would let me generate a rainbow of some kind.

I found one suggestion that seemed appealing, although the author didn’t go into any detail, merely suggesting that the sine function be used to modulate colour channels. So, I thought about it a little bit, and tested the first thing that came to mind. First, I would map the index of each column (each column on the diagram, that is; each corresponding to a single element of 𝑉) to the unit interval by dividing it by |𝑉|. Call it 𝑥 ∈ [0, 1]. Then, I would map 𝑥 into an RGB colour space like so:

Rainbow ( 𝑥 ) : ℝ𝔾𝔹 𝖱𝖦𝖡 ( 𝗌𝗂𝗇 ( 𝑥 ) + 1 2 , 𝗌𝗂𝗇 ( 𝑥 + 2 π 3 ) + 1 2 , 𝗌𝗂𝗇 ( 𝑥 + 4 π 3 ) + 1 2 )

The purpose of adding 1 and dividing by 2 is to scale each component (red, green, blue) to the unit interval. The image of the sine function is [−1, 1], so adding 1 brings that to [0, 2], and then dividing by 2 takes it to the desired [0, 1]. In order to have the components spread out from one another, their angles (the arguments to the sine functions) are separated by ⅔⁢π radians — in other words, one third of a rotation. So they’re nice and evenly spaced, since we have three components.

This achieved the desired effect, although of course “rainbow” is a bit of a misnomer — actual rainbows display some section of the visible spectrum, which only includes colours that can be produced by a single wavelength of light. Our Rainbow⁡(𝑥) function, on the other hand, produces plenty of colours that require multiple wavelengths of light, and thus are “not part of the rainbow”. But that’s okay; it looks just fine. We didn’t really want a rainbow per se anyways.

But then, there comes a time when we must put overlay text onto our coloured polygons. I want to either put black text, or white text, but the issue is that some colours are brighter than others. Like I said, I am no colour expert. But it seems that luminance-related terminology looks roughly something like:

Because we’re working with digital media here, this last term (luma) is what we’re looking for. That being said, I wasn’t really sure how gamma compression interacts with colours that we specify (e.g. in CSS, or in our case, SVG) using simple RGB values like #FF0000 for red. So, instead, I took the easy way out and just pretended that gamma compression isn’t even real. If I get it wrong, the worst thing that can happen is that I get a relative luminance value, right? Seems fine…?

So I took the W3C’s advice and used the coefficients defined by ITU-R Recommendation BT.601:

𝑌′601 ≝ 0.299⁢𝑅′ + 0.587⁢𝐺′ + 0.114⁢𝐵′.

A prime symbol (′) means that the value is gamma-compressed.

Then, to determine whether to use white or black text, I checked whether or not the background colour was “dark”. I simply defined “dark” as 𝑌′ < ½ (or is it 𝑌 < ½​…?). And it looks just fine!

Oh, and then I had to figure out how to colour the hyperedges, as well. I decided to mix together the colours of all vertices that are in the hyperedge, to come up with the colour for the hyperedge. So, great. Now I have to figure out how colour mixing works… Luckily for me, additive colour mixing is relatively simple to implement in a basic way. To get one of the colour components of the result (e.g. green), you simply take the root mean square (rms) of the same component (green) from the colours that you’re mixing.

Dealing with plotters

As I mentioned in the previous section, my first instinct was to reach for plotters as my library of choice to power my program. Not because I had any experience with plotters, or really with much data visualisation software at all, but rather because I don’t have experience with such things. So, because Rust tends to be my language of choice these days (largely just so that I can satisfy my unhealthy compulsion to optimise, or at least be capable of optimising, the living shite out of anything that I write), plotters became the natural choice. As the name implies, plotters is focused on plotting data, and features built-in facilities for two-dimensional and three-dimensional data plotting, including usual function and scatter plots, as well as candlestick charts, histograms, etc.

Unfortunately, none of the built-in functionality was actually going to help here. So in reality, I was just using plotters to render a few polygons (almost entirely rectangles) and some text to an SVG output. If I knew that I was going to be rendering to SVG anyways, was this really going to be faster than just hand-writing it? I’m not sure, although I didn’t know my way around the SVG (1.1) specification, so I just went with using plotters anyways… Plus, if I use plotters, I get a bunch of backends for free: not just SVG, but also bitmap images, the HTML5 <canvas> element, and cairo (which means GTK and FLTK support). Not too shabby, I guess.

In the end, as I said, my code is obviously not representative of what good plotters code should look like, at all. I just got it to the point where it works. The one real pain point is text, where I knew I was going to have some trouble writing text into the main bit of the image, where the hyperedges are displayed. This is necessary for labelling the hyperedges with their names, but there are some cases where text overflow is unavoidable. In the end, I did kind of a hacky workaround that doesn’t look amazing, but makes it (hopefully) readable enough. The end result is a bunch of rectangles and some text, with the occasional triangle here and there (to make the gaps look nicer and a bit easier to read).

Optimising with SVGO

The resulting SVG files were a bit large (doable, but still large), so I thought I’d have a go at optimising them. Luckily for me, there’s a program that will just do this for me: SVGO (SVG Optimiser). I optimised each image with the following command-line options:

…And ended up shrinking each file by a factor of about five, on average! Very nice!! The last two arguments are not really necessary, but I figured that it may as well be somewhat readable if someone looks at the plain text.

The results

Like with the odd job universe, I encoded each hypergraph as a RON file. I put together three such hypergraphs:

Below, you can see the rainbow boxes that are generated by my program for each one. Bear in mind that these are vector graphics, so you can view them at full fidelity from any zoom level; if you need to zoom in, try opening one in its own browser tab and inspecting it from there:

Small hypergraph rainbow box

Small hypergraph rainbow box

Medium hypergraph rainbow box

Medium hypergraph rainbow box

Large hypergraph rainbow box

Large hypergraph rainbow box

Cool, right? Maybe?? Please say “yes”……

woosa finishing up (almost) all of her 4th-job quests

My darksterity knight rusa has had just a few fourth-job skill quests lingering, waiting to be completed.

One of these is the Power Stance quest, which I largely haven’t completed because the party quest (PQ) that you do to complete it, El Nath Party Quest (ENPQ), is also the source of numerous skillbooks that cannot be obtained elsewhere. But, if you complete the PQ and get Power Stance, you can never enter the PQ ever again. So a “stanceless 4th-job warrior” is required to even obtain such skills. I’ve already gotten two such skills for myself: Dragon’s Breath for my woodsmaster capreolina, and Infinity for my pure STR bishop cervid. But there are some other people who I want to get skillbooks for, as well.

On the other hand, I still had some skill quests that I could complete: to raise the maximum (master) level of Aura of the Beholder, and to do the same for Hex of the Beholder. I hadn’t finished these earlier because, well, these skills just aren’t important; it’s unlikely that I’ll ever even spend SP on either of them, and I at least got access to them by doing the initial quests to defeat Thanatos and Gatekeeper. Plus, the quests are a tad unexciting; they’re just ETC collection quests. But, I figured I’d complete them at some point, and that point was now.

So, I headed to Deep Ludi to fight some MDTs in Lost Time:

rusa vs. MDTs

Ooooh, snazzy… a card…

Master Death Teddy card get!

Once I had collected enough Binding Bridles to finish off the 500 that I needed for the final part of the questline, I maxed out my master level for Aura of the Beholder:

rusa finishes the Aura of the Beholder questline

Transcription of the above image

Mr. Bouffon: You gathered 500 Binding Bridle 500. [sic] I’ll awaken all of Beholder’s power now.

REWARD!!: Aura of the Beholder;
150000 exp

The EXP for these quests is… okay. I mean, the monsters that you’re fighting are reasonably high-level and give some halfway-decent EXP, so it’s not too horrible, EPH-wise.

With that, I started the questline to improve the master level of Hex of the Beholder, which meant heading to WPoT4 for Spirit Vikings:

rusa vs. Spirit Vikings

And this time, I was here long enough to actually finish the card set! Nice!!:

Spirit Viking card get!

I also found a mastery book for Dragon Strike level 20. As it turns out, Spirit Vikings are one of only two sources of this mastery book, the other being Pianus (L)!:

Dragon Strike 20 get!

I later responded to a smega from an extremely unfortunate buccaneer who had already managed to fail a preposterous number of these exact mastery books (like 8 or 9? Maybe more?? I don’t remember…), and was looking for another one to try. I gave them my book, and it passed!! Yay!!! Congrats! [:

With 200 Viking Sails collected, I finished the first mastery increase:

200 Viking Sails down

Transcription of the above image

Flo: You got 200 Viking Sail. This will stimulate Beholder’s memories.

REWARD!!: Hex of the Beholder;
100000 exp

And I went back to Spirit Vikings for the 500 sails, as well. But, once I had 5⧸5 Spirit Viking cards, and was over halfway to 500 sails, I stopped there and simply transferred some sails from capreolina to rusa, to finish the last bit. So that’s done!

Some special OPQs

I was invited to OPQ with fellow Suboptimal members Battlesage (Permanovice, Dreamscapes, Hanger) the gish, kookietann (kookiechan, kurisuwu; not actually a member of Suboptimal, anyways, but Battlesage’s partner and a member of GangGang), partyrock (xX17Xx, drainer, attackattack, breakcore, maebee, strainer, raving, technopagan), trishaa, and Lvl1Crook (xXCrookXx, Sangatsu, Level1Crook)! Together, we made a fearsome party of six… I didn’t have any characters that were capable of OPQing, so I took my OPQ mule (and DEXless assassin) sets, who is one of only two of my characters not in Suboptimal — she’s in GangGang as well. Here we are, fighting Father Pixel himself:

sets, Battlesage, kookietann, partyrock, trishaa, & Lvl1Crook vs. Papa Pixie

We had a lot of fun in these PQs!! It took us a few PQs to, uhm, get the whole “do the lounge and the storage concurrently” thing quite right, but otherwise the runs were quite smooth. I admit, I don’t play my OPQ mule much (I continually regret not making her a swashbuckler…), but these PQs were a ton of fun! sets already does pretty ridiculously high damage (being rather optimally built as she is), but even so, I am a bit excited to see just how quickly she could mow down Father Pixel as a fully mature (i.e. level 70) OPQ mule…

A lil bossin’

I was fortunate enough to log on just in time for a chance to fight Ravana on my woodsmaster capreolina! I’ve mostly only been logging on to capre for the purpose of boss-fighting (and to fail more pet HP 60%s — maybe one day, I will manage to pass one…), as I suppose I’ve found it more productive and inspiring to grind on other characters, leaving capre’s EXP gain up to the bosses. I’ll probably get around to grinding on capre sooner or later, even if only to test various training spots and compare them to CDs. In any case, I joined a party with xBowtjuhNL, Gruzz, Harlez, and Bipp to fight this Hindu villain:

capre, xBowtjuhNL, Gruzz, Harlez, & Bipp vs. Rav

Later, while I was doing the Deep Ludi skill quests on my darksterity knight rusa, I was invited to do some Papus by xBowtjuhNL, so we decided to duo it:

rusa & xBowtjuhNL duo Papu

These Papu fights were pretty exciting for me, not just because they got me the Papulatus Certificate that I needed for the Certificate of the Dragon Squad quest (which I now just need the Zakum Certificate for), but because I was actually able to Zerk throughout the entirety of both Papulatus Clock fights!! Unfortunately, I was not set up to Zerk efficiently through the fights with Papulatus proper, but that’s okay; it barely has any HP anyways, and I was probably still zerked like 40% of the time there. It was really cool to be able to zerk against A Real Boss™, without really worrying about dying, even with all of the dispels and 1⧸1s! Here’s a @dpm test that I did during one of these fights, with my usual buffs (including Cider), plus xBowtjuhNL’s SE (which helps a lot, thanks to Crusher dealing damage across three 170% damage lines, and thanks to Zerk’s damage bonus being an aftermodifier[1]):

rusa @dpm test @ Papu (w/ SE)

Transcription of the above image

[system message]: rusa — Lv.127 Dark Knight — Total Damage: 748,659
Damage Per Hour: 22,459,740 — Damage Per Minute: 374,329

22.5M DPH against Papulatus Clock! Cool!! Not as much as capre is capable of, but still extremely impressive.

Oh, and we were so fortunate as to get Soul Teddy Chair drops from both runs!!:

rusa & xBowtjuhNL both got Papu chairs!

Cozy!!!

Footnotes for “A lil bossin’”

  1. [↑] Editor’s note: See the “Zerk + SE = ???” section of pt. ci of this diary.

More MPQ, with panolia

That’s right — it’s time for more em peek ‘U’s with my permarogue, panolia! Speaking of panolia, did you know that Panolia isn’t even a real genus?? Eld’s deer (Rucervus eldii) was named Panolia eldii by English zoologist John Edward Gray at least as early as 1850[1], but at the time (and for over a century to come), the genus Cervus would include members of what are now considered to be other genera, including Axis, Dama, Rusa, etc., and most importantly, Rucervus. Even today, these genera are somewhat controversial, but part of the consensus (that there is) seems to basically be that Panolia and Rucervus are not distinct, but Cervus and Rucervus are. Searching for “Panolia” within the ITIS yields no results whatsoever; the species in question can be found there as Rucervus eldii. It can also be found on the ITIS as an “invalid name” under Cervus eldi and Cervus eldii, with the former as a “misspelling” and the latter as the “original name/combination” (dating from 1842).

Oh, right. MPQ. Well, I was joined by I/L mage StormSpirit and F/P mage HeartNetNing (with whom I also MPQ’d in a previous entry), as well as STRginner Daddyo! Here we are, fighting Fanky:

StormSpirit, HeartNetNing, panolia, & Daddyo vs. Fanky

Our PQs went smoothly, with the exception of one where poor HeartNetNing got disconnected before making it to the boss stage. :( On the bright side, Daddyo seemed to be having a pretty fun time of it, which contrasts favourably with the experiences I’ve been told of by other permabeginners…

And, at long last, I finished enough MPQs to get panolia’s not first, not second, but third Horus’ Eye! Here’s hoping I can finally get that fabled 5 LUK clean one:

panolia’s third Horus’ Eye

Transcription of the above image

Horus’ Eye

Untradeable

  • Req lev: 70
  • Category: pendant
  • STR: +4
  • DEX: +5
  • INT: +4
  • LUK: +3
  • HP: +106
  • Weapon def.: 59
  • Magic def.: 60
  • Avoidability: +15
  • Number of upgrades available: 3

Alright, well, I don’t know what I expected. I’ll just have to scroll one of my below-average ones…

Footnotes for “More MPQ, with panolia”

  1. [↑] J. E. Gray; “Panolia, Gray”; Catalogue of the specimens of Mammalia in the collection of the British Museum, vol. 3, pp. 202〜203; London, England: British Museum Nat. Hist. order of the Trustees; 1850. Available: https://archive.org/details/cataloguemammalia03britrich/page/202/mode/2up

I’m back on my old shit. The sadsadgrind.

Indeed, ’tis time for the grind — but not just any old grind: the sadsadgrind. The grind in which my pure STR bishop cervid and my darksterity knight rusa join forces to lay waste to countless CDs. Because the only thing more sad than solo grinding, is duo grinding with yourself…

cervid was reasonably close to the next level, so she was actually the first to level up — to level 125!!:

cervid hits level 125~!

But, if you think that’s all, you’d be deeply mistaken. I did lots of sadsadgrinding. L o t s . rusa got to level 128~!:

rusa hits level 128~!

Oh, and cervid levelled up again‽ I wasn’t lying when I said that I did a whole lot of grinding:

cervid hits level 126~!

And, finally, rusa is now level 129 o_o:

rusa hits level 129~!

Only one more level for that sweet, sweet maxed Zerk… :)

The adventures of ozotoceros

Alright, enough of that outlander nonsense. Let’s get back to the real shit: mucking about on Maple Island. With my DEXlander, ozotoceros!

To start, I found myself a nice hat (finally):

9 WDEF White Bandana get!

Transcription of the above image

White Bandana

  • Req lev: 10
  • Category: hat
  • Weapon def.: 9
  • Number of upgrades available: 7

That’s right: a perfect clean White Bandana. I found a helm WDEF 60%, as well, so I passed that on the first slot!:

The White Bandana is 11 WDEF now!!

Transcription of the above image

White Bandana (+1)

  • Req lev: 10
  • Category: hat
  • Weapon def.: 11
  • Magic def.: 1
  • Number of upgrades available: 6

Nice. 11 WDEF is pretty killer, although I noticed that the item description for the scroll falsely claims that it grants +2 MDEF when it passes. Not that it matters for a Maple Islander, of course. I managed to find another three of these scrolls, actually, and failed them all! Wow. Fantastic.

For the first time, I had a chat with Casey (master of minigames; not to be confused with Casey) of Amherst to try my hand at a little minigame crafting. Along with a set of match cards, I also made an omok set!:

Omok Table get!

And, in other news, I completed the entire Monster Book!:

ozotoceros completes the Monster Book

Nice. As it turns out, Stumps tend to be the hardest set to get here. There’s just no good map for them (I got all of mine at Dangerous Forest; The Field East of Amherst technically has slightly more spawns, but that map just kinda sucks in general), and their card drop rate is nothing to write home about.

I also made my most epic item so far:

ozotoceros passes a shoe JUMP 10%!

Transcription of the above image

White Gomushin (+1)

  • Req lev: 11
  • Category: shoes
  • DEX: +3
  • Weapon def.: 4
  • Speed: +4
  • Jump: +5
  • Number of upgrades available: 1

[system message]: The scroll lights up, and then its mysterious power is transferred to the item.

ozotoceros: HOLY moly guacamole
i just passed a shoe jump 10 on a 3 speed gomushin

That’s right. I passed a shoe JUMP 10% on a 3 SPEED White Gomushin!!! Definitely the coolest item that I have, hands down.

And I met a fellow islander: tewoo!:

ozotoceros meets tewoo

We met at the Pigs map, and decided to do the islander quest together. Here we are, grinding some piggos:

ozotoceros & tewoo grinding @ piggos

And, after we finished off the rest of the species that we needed, and finished the quest, we had a bit of a chat and played a friendly game of omok:

tewoo & ozotoceros play omok

Transcription of the chatlog in the above image

tewoo: i think u wanna connect 5 in a row?

ozotoceros: i had the etcs
so i figured i may as well craft with em

tewoo: true!

While I was doing the islander quest, I was hunting some Slimes and, after literally thousands of Slime kills, I found my first GSB (at least, the first GSB that I’ve actually seen drop; the one that kurisuwu gifted to me notwithstanding):

ozotoceros finds a GSB…

Wow. Aaaand it’s trash:

ozotoceros’s new GSB sux.

Transcription of the above image

Gold Surfboard

  • Req lev: 15
  • Category: pole arm
  • Attack speed: fast [5]
  • Weapon attack: 35
  • Jump: +5
  • Number of upgrades available: 7

Ouf. Well, not to worry — I found another after just a few hundred more Slime kills! Just kidding, that one’s 35 WATK as well. Heh.

And, at long last, ozotoceros hit the big level 30!!!:

ozotoceros hits level 30~!

Transcription of the chatlog in the above image

[system message]: ⟨Party⟩ ozotoceros has reached Lv.30.
⟨Guild⟩ ozotoceros has reached Lv.30.

[serverwide announcement]: [Congrats] ozotoceros has reached Level 30 as a Beginner!

Yayyy! Second-job islander!! :D

Not too long after, I encountered the dreaded moment in which my ETC inventory filled up for good:

ozotoceros maxes out her ETC inventory…

Transcription of the above image

ozotoceros: ah shit
i cant buy any more etc expansions
im maxed out

Lvl1Crook: time to delete your islander

ozotoceros: fuc
this is so sad
is it bad if im seriously considering making an islander mule just
to hold ETCs

Lvl1Crook: yes

ozotoceros: :(

Lvl1Crook: u should be ashamed of yourself

;~; Well, it seems that my true hoarding days are over…

Speaking of hoarding, let’s take a look at ozotoceros’s stuff. Like the equipment items that I’ve kept:

ozotoceros’s equipment inventory

I NPC any equipment that isn’t equippable by beginners, but I try to keep around at least one of everything else. Some things that I deem more worthwhile, I keep multiple copies of (as you can see, I have quite a few Amethyst Earrings, as they are the only earrings available on-island, barring events). Obviously, although these things are equippable by beginners, not all of them are actually useful, per se. But, you know, you never know when you might need to help someone complete their stylish outfit, or something.

My USE inventory, on the other hand, I have refused to expand at all. It filled up quite early on, with Red Potions. You’ll see 1.3k such potions below, but I would have much more than that if I actually looted them all:

ozotoceros’s USE inventory

And, of course, the ETC inventory:

ozotoceros’s ETC inventory

So, you know, if you ever need some ETCs on Maple Island… You know who to pay a visit to…

I’m filthy rich, too:

ozotoceros’s 598 808 mesos

All of that is pet food money. All of it. bezoarticus is gonna be eatin’ good.

And, while we’re at it, let’s take a look at ozotoceros’s character stats. Here they are, with the Broomstick and Stolen Fence equipped:

ozotoceros’s character stats (53〜59 damage range), with Broom + Stolen Fence

Aaaand with the GSB:

ozotoceros’s character stats (70〜80 damage range), with GSB

Of course, you can see that my minimum and maximum range are quite a bit higher with the GSB; but my SPEED and my WDEF suffer, so — particularly for the SPEED — I actually use my Broomstick more often. That should change in later levels, when I start to be capable of one-shotting higher-level monsters (Pigs, Orange Mushrooms) with the GSB.

<3