btw, if you were not aware, i have a dev log section of my real website that i've actually been keeping updated with what i do every week: https://eev.ee/dev/
what are your thoughts on PEP 0498?
HOT DAMN
is there going to be a vaction day seven at some point?
ah, some things are... happening. i will have time to write about them in a few days i think
vacation day five
i wrote a few pages of a little story, and now actually know where it's going
i tried some character design whoa and drew a thing, with moderate success
wow those took a lot of time actually!
vacation day four
finished the patch for that doom map editor's obscure problem with handling moving lines around; it was merged already, woo
drew some beautiful artwork
wrote a little bit of a short story, then realized i hadn't yet figured out what happens next, sooo we'll see where that goes i guess
figured out how to fix floraverse's homepage in webkit, but didn't actually fix it yet
yeargh, where does the time go...
tomorrow i want to do more writing, get out some little stories and also figure out where triple monday is headed. i can do it, but it's hard for me to sit down and focus inwards like that i guess
vacation day three
oops, bit late
finished the prompt, which is now on floraverse, wahey
set out to do some doom mapping, but instead of doing that i fixed an awkward architecture bug in the doom map editor i use 8) there are like four major ones i'm aware of and i've been vaguely intending to fix them for ages now
did some doodling, mostly of another pokémon/move combo
more starbindery work: instead of hardcoding how to render tiles, i found that it's all described by declarative rules in the game assets, so i wrote a little interpreter for those, and now i render pipes and platforms correctly too. also i sped up the whole load/generate cycle by like 30 seconds, which is nice for me.
vacation day two
i put some effort into starbindery (an autogenerated starbound reference) in the form of a javascript implementation of material rendering
which basically means i did this
which is pretty cool
also i played with LMMS, a linux music studio thing, and figured out enough to recreate four chords. then i stopped because i didn't actually have any song ideas
i doodled a tiny bit but nothing really finished or presentable
i worked on the itchy itchy prompt for a while. most of the time went to cobbling together a file format (well, json format) for storing a cutscene. so far they've all been written in code, which is convenient for me, but not really data. the prompt will be just json, which is a huge step towards being able to write an editor for these damn things.
that's all i got! where does the time go wow
vacation day one
slow day.
i drew a vacationing eevee yesterday, and some shameful pornography today, which took a surprising chunk of the day. then i hung out with mel for a while, and then it was kind of late already
and i woke up early so now i'm drowsy and probably going to bed haha
vacation 2015
I'm off for the next two weeks!
I'm gonna make a proactive effort to actually write about the stuff I do every day, because maybe that's interesting or something.
Things I want to work on include:
- drawing
- writing a flora story or two
- making a cutscene editor
- improving floraverse.com
- starbindery
- triple monday
- flax
- blogging (owe Patreon two posts this month!)
- some veekun maybe?
Stay tuned for what all I'm up to...
What do you dislike the most about Python?
that 3 isn't garnering more interest yet :)
it's hard to say really; everything that immediately comes to mind is either an incredibly obscure nitpick or something sort of fundamental to the language
i wish pypy were further along, i wish it were easier to embed, i wish i could use it on the web (reliably)
i wish descriptors used within classes had access to the names they were bound to, i wish signature-preserving decorators were more possible, i wish there were namespaced interfaces
yeah hm i dunno
i made the entire unown alphabet with just CSS
only one tag per letter, no images, no javascript
i super slacked on this blog oops!
but here is the thing i worked on for yelp's hackathon last week: flax, my roguelike
i did a bunch of work on terrain generation and the UI, cleaned up some internals a teeny bit, messed up some different internals a teeny bit more, and made it possible to actually win the game \o/
if you are a super nerd you can play it but you need python 3 and not-windows and some other things.
hackin on quixe
which is a javascript interpreter for the glulx interactive fiction engine
what does that mean??? it doesn't matter don't worry here's all that matters
before: http://eblong.com/zarf/glulx/quixe/quixe/play-remote.html?story=http%3A%2F%2Fwww.eblong.com%2Fzarf%2Fglulx%2Fsensory.blb&enter=Play+it!
AFTER: http://stuff.veekun.com/quixe-demo/play-test.html
i added support for images and sound, and wrote a new stylesheet for it
i think this is pretty cool
i think i want an early area in flax to be foresty so i'm workin on that
i've been trying to make forest paths work for a couple days and finally got something i like! went through a lot of false starts but this is working pretty well
the rules were:
- paths should look vaguely natural
- if a human would expect two areas to be connected by a path, they should be
- if there are areas blocked off by trees, a path should cut through the trees
(note that atm only areas with short grass — the green dots — are considered, so in this screenshot there's an orphan area at the bottom)
i tried some A* and looked into some other graph-traversal algorithms for a while but eventually settled on something a bit different
the forest itself is generated with perlin noise, which is an algorithm for producing an n-dimensional "plasma" pattern, varying from low to high with distinct peaks and valleys. all i do is make a grid of noise, then treat low values as short grass, high values as trees, and medium values as long grass.
so what i did was flood the forest. not like a floodfill; like actually pouring water into the terrain, treating the noise values as a height.
- start with all the local minima — the tiles that are lower than all of their neighbors. fill each of these with "water", making some number of distinct puddles.
- find the lowest dry neighbor of a wet tile. raise the water level to cover this tile. remember which wet tile it was a neighbor of.
- if raising the water level joins two puddles, congratulations! you found a path. draw a dirt tile where they touched. you have two trails to two starting tiles, by following neighors backwards; draw dirt tiles along those trails too.
- repeat until all the puddles are joined into one big puddle. you're done!
upsides:
- it makes a lot of natural sense. if you consider the noise values to be a measurement of how rarely-traveled a tile is, then it makes perfect sense to have trees for high values, grass for low values, and forest trails along the lowest-valued paths.
- because the noise values aren't visible on the map itself, it just looks like a bunch of moderately chaotic lines. it's hard to guess at a glance how this map was generated. which is great.
- it'll only break through trees as a last resort; i don't have to do anything special to enforce that.
downsides:
- it will prefer the "long way around" to cutting through a single tree. but there are usually other clearings near the long path, so it usually works fine.
- i don't think it will ever draw triangles, since it won't try to draw a path between parts of a puddle that have already joined together.
- atm it sometimes infinite-loops, oops
next up: RIVERS
i've been making a point of keeping up my GitHub Streak™, which is just a count of how many days in a row i've done something — made a commit, filed a ticket, maybe something else idk.
the result is that flax has moved along incrementally every day for almost a month. and because the rules are flexible, i still do something even on days when i don't have time or energy to do anything significant — even merging someone else's pull request counts as committing. and when i have absolutely no ideas for what to do with flax, i do something with floraverse instead.
it's a pretty slick little reward system. only downside is that i've also been pretty eager to work on IF and flora stories and my programming book, and those don't count because i don't have them on github. but i'm fitting them in here and there.
unstoppablecarl answered your post: entity-component
I have tackled this same problem pretty thoroughly in my own roguelike project. If you want some help dm me on twitter @unstoppablecarl
i have the most elegant solution to your problem but this ask box is too small to contain it
re: entity-component
jamesnvc answered your post: entity-component
Reasonable to structure things in a pub-sub manner, so you fire an event on a tile & things can listen for events on that tile?
i'll pretty much have to have some form of pub-sub anyway for equipment and the like
but one thing i hate having to deal with is "remembering" to remove event listeners and effects and what-have-you when an object is destroyed or removed or otherwise disabled. (a running theme i've seen in nethack bug fixes is "poison resistance got confused when it came from two places at once".) and completely freeform pubsub tends to exacerbate that, since there are no rules about who can subscribe to what and when. so i'll probably end up with a fixed handful of "directions" an entity can subscribe to — the tile it's on, the creature it's equipped to, the creature whose inventory it's in, etc. then when the entity goes away, the listeners automatically go with it.
(originally i was just going to copy the DOM event model but i immediately discovered that something designed for a nested hierarchy doesn't work too well for, say, tiles)
entity-component
flax now has combat, whoa, amazing
allow me to ponder aloud for a moment here
as with my previous attempts at a roguelike, flax is built with an entity-component system. rather than having a rat's nest of classes inheriting from a zillion mixins, there are a couple layers
- there are component interfaces, like IPhysics, which just say "an entity might know how to do physics"
- then there are component classes that implement an interface, like Solid, which says "i make an entity unable to share space with other solid entities"
- entity types are instances of EntityType, and are passed a list of component classes. e.g. a creature currently looks something like EntityType(Solid, GenericAI, layer=Layer.creature).
- and finally, an entity is a really thin object that just holds an entity type and a bag of data. (the data is keyed to attributes on the interfaces, so it's a mapping like {ICombatant['health']: 10}.)
the interfaces also know how to adapt an entity to its appropriate component. so if you called IPhysics(player), you'd get a Solid object. it's a little inverted from how EC usually works but it plays more nicely with a dynamic language.
this might seem a bit astronauty, but there are good reasons! roguelikes are intricate complicated things, and i would like to avoid having interaction lint strewn all over the place, as is largely the case with nethack's source code. consider also that roguelikes tend to have extreme world-altering effects, like polymorph and polypile, which can change an entity into a completely different type of thing altogether. with the above setup, i can just switch out the type and i'm done.
anyway, so. this is all well and good so far.
i also have baby event handling. any action or instant effect is implemented as an event, sort of like in a browser. so when you try to take a step, that fires a Walk event at everything in the tile you're trying to move onto. anything with a Solid component has a Walk event handler that just cancels the event. if nothing intervenes, the event has a default_behavior() that actually moves you to the new tile.
so far so good still.
but now i'm doing combat and things are getting a little fuzzier. MeleeAttack is an event which fires at a creature. its default behavior is to fire Damage, which then ultimately inflicts the actual damage with ICombatant(creature).damage(amount).
so. there are now three places to put the actual implementation of an action: in a component, in an event handler on a component, or in an event's default behavior. so when does code go where, and why? i'm treating ICombatant.damage() as just a dumb method that should modify health, but should that all instead live in an event handler that handles Damage? it seems reasonable; what if a component wanted to treat damage completely differently? so then is there any reason to ever have default behavior for events, or should it all be implemented by the target's event handlers? does that mean all actual game behavior should live in event handlers, and components are primarily a way to bundle event handlers together?
another thought: what do events actually fire on? e.g. Walk right now fires at everything on a tile, but that seems weird; surely an event should only have a single target (in this case, i suppose, the tile itself). this'll get more complicated later, too, when there's equipment that wants to intervene on certain events on the wearer. so i suppose... entities should be able to register temporary event handlers on other entities, and unregister them when they leave (e.g. when equipment is taken off)? i guess that would make sense. tiles will probably still be a special case, since they're just part of the map implementation, not entities.
idk, thoughts??
NEW EXPERIMENT: i'm trying to make and push at least ONE COMMIT to SOMETHING every day. github shows a streak under your contribution graph, so. number to max out.
anyway over the last few days i've been tinkering with flax, a flora-themed roguelike. not a whole lot exists atm but i've been dicking around with map generation and well: https://twitter.com/eevee/status/478056263838752768
that's pretty basic too it's just perlin noise converted into a few types of terrain tile
i want to randomize eeeeverything and i'm excited
