dariusk / NaNoGenMo-2015

National Novel Generation Month, 2015 edition.
340 stars 21 forks source link

Compiler pipeline + writers' techniques = a "proper novel" ::blink:: #11

Open cpressey opened 8 years ago

cpressey commented 8 years ago

Novel: A Time for Destiny: The Illustrious Career of Serenity Starlight Warhammer O'James during her First Three Years in the Space Fighters Code: on Bitbucket Write-ups: Overview of a "Story Compiler"


Observation: It is very difficult for the average person to read a typical NaNoGenMo-generated novel in its entirety, from beginning to end.

It's because the brain begins to tire, right? It gets all "I see what you did there" and balks at facing yet more unpredictable stuff.

Goal: To write a generator that generates a novel that does not succumb to this effect.

You still might not be able to read the resulting novel to the end, but, if you stop reading after the first 2 chapters, it should be because the novel is just plain bad, not because its aura of generativeness is burning a hole in your attention span.

Downloading an existing novel from Project Gutenberg, or similarly trivial approaches, don't count.

This is, of course, a completely unrealistic goal. But one must have some goal, mustn't one?

ikarth commented 8 years ago

@TheCommieDuck I suspect that the art of designing a narrative simulation is to work out what you can leave out. Your simulated people will be unlikely to be complete psychological models, but perhaps there are bits of Maslow's hierarchy that can be elided for the particular effect you are attempting in one particular work.

That said, I don't know where that line is. Dwarf Fortress does the kitchen sink approach, which at least dazzles with its specificity. Though it also uses stereotypes of its fantasy races (or newly invented ones) to simplify some aspects and turn their simplicity into virtues - all dwarves drink, all elves would rather commit cannibalism rather than harm a tree, etc. It strikes me that choosing the specific aspects to simulate or ignore can itself be a powerful rhetorical statement.

enkiv2 commented 8 years ago

The extreme kitchen-sink kind of simulation, combined with absurd attributes, can be more entertaining than more realistic descriptions. I would rather read a dry description of a day in the life of a Dwarf Fortress dwarf than a day in the life of a character in The Sims, because The Sims is too realistic and reality is boring. In this sense, simulation bugs are literally features.

On Fri, Nov 6, 2015 at 2:10 PM Isaac Karth notifications@github.com wrote:

@TheCommieDuck https://github.com/TheCommieDuck I suspect that the art of designing a narrative simulation is to work out what you can leave out. Your simulated people will be unlikely to be complete psychological models, but perhaps there are bits of Maslow's hierarchy that can be elided for the particular effect you are attempting in one particular work.

That said, I don't know where that line is. Dwarf Fortress does the kitchen sink approach, which at least dazzles with its specificity. Though it also uses stereotypes of its fantasy races (or newly invented ones) to simplify some aspects and turn their simplicity into virtues - all dwarves drink, all elves would rather commit cannibalism rather than harm a tree, etc. It strikes me that choosing the specific aspects to simulate or ignore can itself be a powerful rhetorical statement.

— Reply to this email directly or view it on GitHub https://github.com/dariusk/NaNoGenMo-2015/issues/11#issuecomment-154503865 .

tra38 commented 8 years ago

@cpressey So I went ahead and actually implemented a program that will show the history of a McGuffin as it is being passed from person to person. Note that this program is not a simulation, but the output would be virtually indistinguishable from a simulation.

Source Code: https://gist.github.com/tra38/0064c227a298d7f51c11 Story: https://gist.github.com/tra38/f96a02f65f816a61ebfc

Not going to be an entry of NaNoGenMo because I don't really like the code. I wrote it though to make a point that simulations may seem neat but that there are other ways of accomplishing the same task.

ikarth commented 8 years ago

I sort of disagree, and sort of agree. I think it (perhaps appropriately for NaNoGenMo) comes down to the Tale-Spin effect - simulations that don't properly explain enough of what is going on under the hood create the illusion that the simulation is simpler than it actually is.

MichaelPaulukonis commented 8 years ago

Once you have the simulation, then you can tweak the language-generator to explain what is going on better. That's the impression I got with the epithet Tale-Spin effect in Expressive Processing (which I'm still reading). Waldrip-Fruin seemed somewhat annoyed that there was so much richness to the simulation and "just one day" given to the text-generator side of the application, and thus the app (and, by extension, computational narratology as a whole) given short shrift by many.

ikarth commented 8 years ago

That matches my impression. With the addendum from my (artistic application) perspective that it can also be aided by choosing a design where the surface matches the underlying process.

I was inspired by his discussion of the SimCity effect (among other things) to try to formulate a better definition of the relationship between agency and erdoic cybertext. Slightly off topic here, but I think the general principle applies: one of the things we seek when reading a novel is to understand the patterns the author placed there, either consciously or unconsciously, which can only happen if enough of the hidden pattern of the idea can be detected in the material presentation.

greg-kennedy commented 8 years ago

I'd like to shamelessly plug my "real" attempt for the year, which does exactly what was talked about midway up this thread: generate an insanely large amount of events, then pass the whole log to an editor that selects interesting portions to form chapters. Certain events may be considered to have a higher "gravity" than others - e.g. looking at something is less interesting than converting a Character to a Dead Body using the Revolver - and I'd have to manually assign such weights. The editor simply needs to follow an item, character or place for the duration of a chapter in which some interesting event occurs.

I also want my characters to have overarching aspirations and sub-goals, which help direct them to accomplish things. The resulting "story" will probably be constructed so those aspirations end in a compelling narrative.

In theory, anyway. I may get 500 words in and then pad the rest out with "meow".

cpressey commented 8 years ago

Update: I was lucky to get a fair chunk of time to spend on my generator over the weekend.

For Goal 1, it can generate a semi-coherent story of 800 words. My milestone this week is to double that number.

For Goal 2, I implemented 2 writers' techniques, one of which was a little trickier (or at least, more tedious) than I thought it would be, and the other -- the one I really wanted to implement, since like months ago -- was a little easier than I thought it would be. My milestone for this week is to either add a third, or do the one I really wanted to do in a more sophisticated way.

I'd write more about it, but apparently what people want to talk about on this issue is simulations (rather than writers' techniques or compiler architecture, as the title of the issue might reasonably suggest.) Fine, OK. I'm not using simulation techniques here, so I'll just keep quiet about my generator until I've made more progress.

cpressey commented 8 years ago

@tra38

Creating a simulation of an entire city just to trace the history of a coin seems absurd.

Indeed, I basically stand by what I said here: identifying interesting situations (inside a simulation) is probably as hard or harder than fabricating them (instead of simulating them). That's one reason I didn't actually follow up on my idea back in January to simulate a city. That, and, narrative methods are much more unexplored territory for me, and interesting for that reason.

Actually I think the snippet you posted would be a fine NaNoGenMo entry (with more situations and a few paragraph breaks, perhaps) -- does it really matter if the code is a bit distasteful? Well, maybe it does, depends on your goals I suppose. And I could understand if you don't want to spend any more time going down that avenue.

rngwrldngnr commented 8 years ago

Regarding story compiler architecture, I think the first-draft-to-finished-story section you mentioned in one of your earlier posts could be very fruitful. I can think of several tasks that would be relatively simple to operate on a draft where text (or a near text intermediate representation) would be both input and output.

You could count word frequencies and replace a portion of anything way above the Zipf curve with synonyms. You could combine or split apart sentences to get more variety in length. You could manage pronoun ambiguity by making sure that a persons real name is given every few sentences and at least once per paragraph. You could switch passive voice to active voice (or the reverse, if that's what you want stylistically).

Most of these could probably be built straight into the earlier stages of the story compiler, and some of them might even be easier to implement there, but I think that would depend heavily on your implementation, where as operating on plain text makes the layers machine independent. It also allows you to switch the order of any of the layers and toggle them on and off as required.

I'm not sure, but I feel like the Draft Revision layers also give you the possibility to harness techniques that real writers use to get around some of the problems that often plague them and story generators. If you look at output from BRUTUS1 or AUTHOR, they look a lot closer to human-written stories than most of the story generators, but they still can feel off, and iirc a couple of contests suggested that Brutus in particular, even when mistaken for human, came off as low quality. I know from participating in peer review of stories that first drafts often give off this feel, and I wonder if by trying to internalize all of the ideas about how stories should look and feel, what good English sentences look like, and so on, we might be missing that it really is just easier to apply a lot of the changes on the 'final' text.

This approach could also be generalized to other stages in the story compiler. If you did create intermediate representations, there could, at least in theory, be a similar architectural layer at each stage that contains many minor revisions that get applied cumulatively to that intermediate representation before the transformative step that takes you to the next intermediate representation. I'm tempted to refer to these as story optimizations, as I think those are the only steps a compiler takes without switching representation, but I don't think that makes much sense as compiler terminology.

cpressey commented 8 years ago

@rngwrldngnr What do you have in mind for a "near text intermediate representation"? My position is that parsing arbitrary English text is difficult and painful, and if it's non-arbitrary it might as well be a data structure.

I don't have any pipeline stages that take text as input right now, and I don't plan on having any this month, because that's a can of worms I'd like to avoid opening if possible.

The pipeline I do have right now works on what are basically trees with lists of properties on each node (until the very end, when it spits out text). And yes, most of the stages in the pipeline try to do one job and one job only, and there are many stages... at a guess, about a dozen right now. It would not to be wildly inaccurate to call the stages at the end story optimizations, since they do things like (attempt to) choose pronouns to use instead of nouns when the referent is apparent.

greg-kennedy commented 8 years ago

I'd write more about it, but apparently what people want to talk about on this issue is simulations (rather than writers' techniques or compiler architecture, as the title of the issue might reasonably suggest.) Fine, OK.

Well SORRY for dragging our dirty simulator feet on your otherwise pristine issue :P

cpressey commented 8 years ago

I apologise if my eye-rolling yesterday irritated anyone.

NaNoGenMo's supposed to be fun, and I'm having a lot of fun writing my generator, but I'm finding the discussions this year not much fun at all. It feels like there's a lot more talking than there is listening, and that it's really heavy on the jargon and reference-dropping, and it's tiring.

Consider how many participants are completely new to programming, or NLP, or generative art (or, or, or...) If it's tiring for me, I'm sure they're mostly not even bothering to read it.

If the only way to get away from it is to not discuss then I'll just not discuss, that's all.

My generator can make a semi-coherent story of about 1000 words in length now. Watch this space. If you care. Or don't, if you don't.

ikarth commented 8 years ago

Fair enough. And I'm afraid I'm as guilty as anyone of leaning on the jargon. I'd certainly prefer to introduce new people to the fun, though after the third go-round I'm maybe slightly out of touch with the needs of a beginner.

1000 semi-coherent words isn't anything to sneeze at. What approaches are you using in your current generator? What does a story compiler look like?

cpressey commented 8 years ago

What does a story compiler look like?

First, I should note: the reason I haven't released any code or samples is because I feel they would be kind of a spoiler. I think this will be most entertaining if I get it to a good point and release it all at once; everything after that might be a bit anti-climactic.

But knowing the basics of the underlying architecture is probably not much of a spoiler, and since it has solidified* now, I can probably write up something on it. Maybe as a blog post instead of a comment here, if it gets long. I'll see what I can do, hopefully in the next day or two.


*This is a lie. It would be more fair to say it's gotten risky to make any more significant changes to it. The last thing I want to do is introduce an obscure bug that will take a long time to track down. So I'll just manage with it as it is.

MichaelPaulukonis commented 8 years ago

The last thing I want to do is introduce an obscure bug that will take a long time to track down.

wouldn't your unit-tests catch that pretty quickly? he asked, innocently.

hugovk commented 8 years ago

The last thing I want to do is introduce an obscure bug that will take a long time to track down.

wouldn't your unit-tests catch that pretty quickly? he asked, innocently.

And it's easy to roll back from source control, naturally.

greg-kennedy commented 8 years ago

The last thing I want to do is introduce an obscure bug that will take a long time to track down.

wouldn't your unit-tests catch that pretty quickly? he asked, innocently.

And it's easy to roll back from source control, naturally.

Especially since you left such helpful comments on everything you did.

cpressey commented 8 years ago

The last thing I want to do is introduce an obscure bug that will take a long time to track down.

wouldn't your unit-tests catch that pretty quickly? he asked, innocently.

And it's easy to roll back from source control, naturally.

Especially since you left such helpful comments on everything you did.

And at the very least, the programming language will stop me from doing anything too stupid, right?

Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> True = False
>>> print True
False
>>> print False
False
>>> print (True == False)
True
>>> 

YAY SOFTWARE

cpressey commented 8 years ago

What does a story compiler look like?

OK, I have written this thing. It's a bit long (maybe 10 or 15 minutes to read?), so I put it in a gist.

https://gist.github.com/cpressey/6324fff6ef0dfdf69b96

I don't know how well I've succeeded, but I've tried to write it for a general intermediate-programmer audience, not assuming any knowledge of compilers or any advanced programming knowledge. You can also skip over the first and last sections without really missing anything.

ikarth commented 8 years ago

The story compiler approach seems amenable to incorporating some of what you might call low-level plotting techniques: writer's approaches to how things individual scenes get constructed.

Like the bit about structuring the story from conflict here, or Jim Butcher's Scenes and Sequels technique. Or, on a larger level, things like this note card technique to structure the novel's chapters.

cpressey commented 8 years ago

The story compiler approach seems amenable to incorporating some of what you might call low-level plotting techniques: writer's approaches to how things individual scenes get constructed.

Yes! Which is exactly what I'm doing with Goal 2 -- trying to automate some of those techniques. Progress in that area has only been modest so far though.

Thanks for the links, it will be interesting to compare the methods they describe with what I've got so far.

cpressey commented 8 years ago

The peals of the half-time gong echoing in the distance, the month trundles along into its third week!

Update: not so lucky with the time allocation this past weekend.

Goal 1: semi-coherent story length is about 1500 words, with caveats.

I also have a few ideas about how one could make the novel more readable (or rather, less unreadable) at 50K-word scale. They're gimmicky cheap ideas and I don't necessarily like them, but having stated Goal 1 the way I did, I guess I'm obligated to pursue them.

Needing to choose my battles, I deem Goal 2 completed. I implemented the one writers' technique that I really wanted to implement, even if I didn't end up applying it in a particularly good way.

cpressey commented 8 years ago

OK well I could keep tweaking this and tweaking this and tweaking this and inching closer and closer to Goal 1 but honestly I think it has reached the point of diminishing returns and/or the minimum quality level I referred to earlier so - here it is!!!

A Time for Destiny: The Illustrious Career of Serenity Starlight Warhammer O'James during her First Three Years in the Space Fighters

Generator is here, has name in ALLCAPS in great tradition of names of story generators. Will mirror the code on GitHub in near future, time permitting. To reproduce this novel, run the generator with SEEDBANK_SEED=9889.

enkiv2 commented 8 years ago

This is honestly pretty good. Like, I'm having a hard time distinguishing it from slightly-higher-than-average-quality fanfiction, reading through the first two chapters.

On Fri, Nov 20, 2015 at 10:39 AM Chris Pressey notifications@github.com wrote:

OK well I could keep tweaking this and tweaking this and tweaking this and inching closer and closer to Goal 1 but honestly I think it has reached the point of diminishing returns and/or the minimum quality level I referred to earlier so - here it is!!! A Time for Destiny: The Illustrious Career of Serenity Starlight Warhammer O'James during her First Three Years in the Space Fighters https://cdn.rawgit.com/cpressey/eafe2c9fad2884b812f3/raw/602c724016a901a5aafdde688cea805423ebfc03/A%2520Time%2520for%2520Destiny.html

Generator is here https://bitbucket.org/catseye/marysue/src, has name in ALLCAPS in great tradition of names of story generators. Will mirror the code on GitHub in near future, time permitting. To reproduce this novel, run the generator with SEEDBANK_SEED=9889.

— Reply to this email directly or view it on GitHub https://github.com/dariusk/NaNoGenMo-2015/issues/11#issuecomment-158435624 .

greg-kennedy commented 8 years ago

I read three full chapters before skimming. After the first two I was preparing to skip forward, but then Nebulon showed up, and things got interesting again!

...but after that I wondered what other plot events might happen, so I started scrolling...

so I guess that's 2770 words read. Not bad.

enkiv2 commented 8 years ago

The space-opera setting tempts me to swap out some texture in characters.py and costume.py and produce something resembling 'leather goddesses of phobos', only more twee.

On Fri, Nov 20, 2015 at 11:16 AM Greg Kennedy notifications@github.com wrote:

I read three full chapters before skimming. After the first two I was preparing to skip forward, but then Nebulon showed up, and things got interesting again!

...but after that I wondered what other plot events might happen, so I started scrolling...

so I guess that's 2770 words read. Not bad.

— Reply to this email directly or view it on GitHub https://github.com/dariusk/NaNoGenMo-2015/issues/11#issuecomment-158447462 .

MichaelPaulukonis commented 8 years ago

I think I know who Serenity O'James is....

As usual, your code leaves me gnashing my teeth, wishing mine were as robust. And handsome. You have such robust, handsome code. I love to run my keyboard over it....

cpressey commented 8 years ago

Oh! Well! Glad it's well-received (increasingly creepy vibe I'm getting from these responses notwithstanding...)

I think I know who Serenity O'James is....

Well, you're probably wrong, as the character is little more than a synthesis of a selection of these traits. I'll probably try to write something about that, and the implementation of writer's techniques, etc, over the weekend.

greg-kennedy commented 8 years ago

Don't act like you've never heard of LGoP before...

ikarth commented 8 years ago

I'm looking forward to the write-up.

The generator does a pretty good job with creating individual scenes that are at least nominally readable. Which is high praise in NaNoGenMo.

The rather inane resolution of most of the plots is a weakness, of course. Though I suppose it's in-genre for your source material. And I suspect handling that better would be a major project in itself.

tra38 commented 8 years ago

May I request that this generator is under some kind of license (even the Unlicense), in case other people wishes to use or expand on the MARY SUE program?

One thing that I did find interesting in your original writeup and in your source code is that the actual starting plot is pretty basic: characters get introduced, then the characters meet up and laugh. That's it. Literally everything else is just the generator adding additional sub-plots and complications to increase the word count. The system works of course, but it seems incredibly foreign to how a human writer would write plot (come up with a central core plot first and then flesh/pad it out). Maybe this has to do with fundamental differences between man and machine: humans are trying to convey some underlining message or meaning to other humans, while bots don't really care at all what they write.

enkiv2 commented 8 years ago

I'm not convinced that it's alien to the way human writers plot -- particular authors of this particular style of mary-sue-OC fanfiction that the generator mimics. After all, a lot of OC/self-insert fic involves inserting an OC into emotionally satisfying but more or less arbitrary social situations with more extablished characters or settings, and one can make the argument that this is exactly what this generator does (with the exception that the generic parody-space-opera setting and generic parody-space-opera characters aren't clearly attached to an existing franchise -- but they certainly would fit in neatly with, say, TOS-era Star Trek along with a whole host of golden age space operas of the Zapp Brannigan variety).

It's not how a professional author plans out plots. But, it's definitely how some starry-eyed amateurs do.

On Fri, Nov 20, 2015 at 7:55 PM Tariq Ali notifications@github.com wrote:

May I request that this generator is under some kind of license (even the Unlicense), in case other people wishes to use or expand on the MARY SUE program?

One thing that I did find interesting in your original writeup and in your source code is that the actual starting plot is pretty basic: characters get introduced, then the characters meet up and laugh. That's it. Literally everything else is just the generator adding additional sub-plots and complications to increase the word count. The system works of course, but it seems incredibly foreign to how a human writer would write plot (come up with a central core plot first and then flesh/pad it out). Maybe this has to do with humans trying to convey some underlining meaning and message to other humans, while bots don't really care at all what they write.

— Reply to this email directly or view it on GitHub https://github.com/dariusk/NaNoGenMo-2015/issues/11#issuecomment-158569094 .

cpressey commented 8 years ago

I'm looking forward to the write-up.

Had not even enough time over the weekend to do that. Might not have enough time to write up some single coherent thing. Might work in chunks. To wit, I can start with this:

What I most wanted to implement was a story generator that could do Chekov's Gun, i.e. foreshadowing an object which does not start out important in the story, but later on becomes important.

Implementing Checkov's Gun is actually really easy:

This is basically what is described in this article that @ikarth shared earlier -- see the "XXXX ADD GUN EARLIER XXXX" part.

Not difficult, but notably also not something you can do with a simulation alone. Because you can't just output events as they happen. You have to go back and examine them & edit them selectively. So you have to keep the events around in some kind of data structure. This is what led to the compiler-like architecture.

In fact it is very clumsily applied in the novel, but I don't really care, the goal was to implement it. As a sort of bonus I also made it add a mention of the object at the end, as a sort of reminder (I don't know if there's a name for this.)

cpressey commented 8 years ago

May I request that this generator is under some kind of license (even the Unlicense), in case other people wishes to use or expand on the MARY SUE program?

This will probably happen eventually (eventually meaning, sometime after November is over). Because I feel strongly about open-source and all that, and over the past umpteen years, I've put nearly everything I've done under a permissive license.

But honestly, I have to wonder if it even means anything anymore in a world where appropriation artists sell printouts of screenshots of strangers' web pages for tens of thousands of dollars.

enkiv2 commented 8 years ago

I would dare to suggest that the existence of appropriation artists depends upon the existence of non-permissive licenses. There is nothing subversive about 'appropriating' free content.

On Mon, Nov 23, 2015 at 1:24 PM Chris Pressey notifications@github.com wrote:

May I request that this generator is under some kind of license (even the Unlicense), in case other people wishes to use or expand on the MARY SUE program?

This will probably happen eventually (eventually meaning, sometime after November is over). Because I feel strongly about open-source and all that, and over the past umpteen years, I've put nearly everything I've done under a permissive license.

But honestly, I have to wonder if it even means anything anymore in a world where appropriation artists sell printouts of screenshots of strangers' web pages for tens of thousands of dollars.

— Reply to this email directly or view it on GitHub https://github.com/dariusk/NaNoGenMo-2015/issues/11#issuecomment-159018846 .

cpressey commented 8 years ago

I would dare to suggest that the existence of appropriation artists depends upon the existence of non-permissive licenses. There is nothing subversive about 'appropriating' free content.

So... when Georg Baselitz, in The Painter's Equipment (1987), claims to have composed Fidelio (1814) when he was 6 years old - you would say there is nothing subversive about that? Interesting. I think that that is much more subversive than the conceptual parlour tricks that so many so-called artists produce these days.

Not that being subversive is the only way to get attention. Not that getting attention is the purpose of art. Unless that's all that's left of art now, I guess.

cpressey commented 8 years ago

Update: code is on GitHub now and in the public domain now.

Have been too ill in the past week to write anything up further. Really, it mostly comes down to this:

The point of NaNoGenMo is to generate a novel. Even if you take that literally (as is my wont), there's nothing saying it has to be a good novel. So, what's a rich source of bad writing? Fanfiction. And what's the worst kind of writing in fanfiction? Reports vary, but it's hard to go wrong with a Mary Sue. This relieves the writer of many burdens (such as having scenes in which the protagonist does not appear, of the protagonist having character flaws, of the other characters being more than 2-dimensional, etc) and provides much opportunity for padding (the salvation of every writer with a word quota), in this case in the form of poorly thought-through similes and waxing poetic about costume. (In fact, even having a Chekov's Gun in a Mary Sue story is a bit out of place - it's too sophisticated - you'd almost expect things to be pulled out of the air without any foreshadowing instead. Well, this is how it ended up, anyway.)

I read three full chapters before skimming.

Oi! You exceeded the dosage guidelines! There was a warning label! I can't be held responsible...

Yeah, OK, I'm just pointing out, the warning label is the gimmicky cheap idea I referred to earlier. The idea being, you could probably slog through any NaNoGenMo novel, if you did it in small enough pieces and gave yourself enough time between pieces.

Also, there's a sense in which I should've spent the final week adding as many new subplot choices as I could, so maybe you'd see "4. Stranded in Space" after reading the 3rd chapter, and maybe you'd read even more words, and... yeah, I probably should've, in order to strictly pursue Goal 1. But I was so tired of reading the escapades of Serenity Starlight by the time I released this (I'm sure I've read 50,000 words of it myself), and being sick didn't exactly help matters either. I will be content at it being a proof-of-concept for this approach to that goal.

Lastly, I just want to emphasize that it's not just an anthology of short stories, too. (Because that wouldn't be a proper novel, would it?) There is a story arc... sort of.

Thoughts on plot... I might write about... at some future point... maybe.

tra38 commented 8 years ago

An anthology of short stories can also have a story arc too (see "The Martian Chronicles", which was a bunch of short stories that still had an overarching plot). If I understand correctly, there are two central plots in this novel: 1) Serenity's careerist rise in rank, only hampered by Serenity's own refusal of promotions 2) Serenity's love affair with Commander Joe

The problem is that unless you really paid attention to the novel itself, looking at how events change within each individual chapter, you would not really notice the story arcs in question. So while there is an arc, the reader may very well not notice it. (This problem does seem solvable though. If you had added more subplots though to get user attention, maybe the reader who have been invested long enough into the story to detect the story trend.)

EDIT: I also don't think the novel text itself is bad. I really get more of a theme of a "Saturday Morning Cartoon" show than that of an annoying Mary Sue flaunting her status. I notice Serenity never seems to ever get kidnapped herself though.

Johoely commented 3 years ago

The 10 Rules of Writing a proper Novel Read voraciously. Writers are shaped by other writers. Make checklists of details. Develop good habits. Use your limited time wisely. Build a relationship with an editor. Don't stress your first draft. Seek out surprises in the second draft. Start with characters.