Wednesday, February 26, 2014

More Chrono Trigger

So basically, I don't know what I was thinking, recommending the 6th battle in Black Omen over Geno Dome for XP grinding.  I've been doing it in Geno Dome this time, and it's so much faster that it's ridiculous.  I also got Magus his tech points there.

Geno Dome has always been the levelling spot of choice for speed runners, but I wasn't so sure because of the requirement for Robo to be in the party.  Once he's maxed and not gaining XP, it's technically a wasted party slot.  However, between his damage output and the low health amounts on the enemies, the XP rewards are high enough for it to not matter.  I guess I should have done the same thing the speed runners do, but... meh, whatever.

I've done the math, based on this table that shows how much XP is necessary to get from one level to the next, and it never takes more than seven runs through the conveyor belt battles to level up an in-party character.  Only levels 98 and 99 will take seven grinding runs, the rest will take six at most.  An out-of-party character will take at most nine grinding runs.  Once again, only levels 98 and 99 will take nine grinding runs, the rest will take eight at most.  I am, of course, rounding everything up to the next whole run, because you can't leave in the middle of it.  For programmers, this is the ceiling() function.

For kicks I compared this to the grinding run I used previously, just to further cement how bad it was.  Going from level 98 to level 99 with that method would take 25 grinding runs, and 34 for an out-of-party character.  See now how Geno Dome is faster, even once Robo is at 99?

I still personally believe that it's faster to level Marle and Lucca out-of-party, even though out-of-party characters only receive 75% of the XP that in-party characters receive.  The damage they deal with their regular attacks just isn't high enough, and would slow down the process if they're in the party.  I know Lucca has the WonderShot, which is capable of tripling her damage, but there's a reason why I call it the WonderShit: It hardly ever deals respectable damage.

I'm levelling Robo, Ayla, and Magus currently.  Magus is still catching up in level since I didn't grind his tech points using the DoomSickle and two dead party members like last time.  Ayla will most definitely get swapped out when she hits 99, just so I can bring in Crono.  Once it's down to just Marle and Lucca, I'll put together my highest physical damage party and let 'er roll.  I kind of wish I had three Berserkers so I wouldn't have to press any buttons at all.

Long story short, Ayla now has Bronze Fists.  I was actually confused at first because she reached 96 on the last conveyor belt battle and still had the Iron Fists, but fighting a single battle at level 96 causes the fists to change.  I believe this applies to all of her fist upgrades, including the two that don't change the name.  Just FYI, they happen every 24 levels and pretty much just exist to raise her critical hit rate.

Tuesday, February 18, 2014

Perfect Grilled Cheese Sandwiches

Because grilled cheese sandwiches are awesome, and after having made them with a few different cooking implements (nonstick griddle, contact grill, frying pan), I have arrived at what I deem to be the best way to make them: using a frying pan.

I'm not sure how much different frying pan materials will affect this.  I don't think there will be a noticeable difference, but for scientific purposes, I'm using a stainless steel frying pan.

I also fully recommend seasoning your frying pan, that is, unless you like having your grilled cheese stick to it, and end up both burnt and under-toasted simultaneously.  If your frying pan isn't seasoned and you don't really have the time to do so, you can just apply some vegetable oil cooking spray to it before heating it up.

Anyway, on to the recipe.  Some parts are open to adjustment for your own tastes, obviously.
  • Bread, 2 slices
  • butter
  • cheese, 2 slices
  • seasoning to taste
  • vegetable oil cooking spray
Brand recommendations (aka what I use):
  • Bread: Nature's Own 100% Whole Grain (not the sugar free one, this distinction is important because they look nearly identical)
  • Butter: Brummel & Brown (a low-fat butter substitute).  It's spreadable straight out of the fridge, unlike regular butter that you need to bring to room temperature first.
  • Cheese: Sargento Sharp Cheddar.  Don't get the thin slices, and if you use plastic American processed cheese food product (that can't even legally be called "cheese" in the US), you suck.  Cheddar is better.
  • Seasoning: Old Bay seasoning, or just cut to the chase and use paprika
  • Cooking spray: Pam (make sure to get the regular one, not any of their weird ones with flour, butter, or olive oil)
  1. Get out your slices of bread, and spread a very thin coat of butter across one side of each slice of bread.  Total surface area coated matters more than the volume of butter in that surface area.  Try to get all the way out to the edge of the crust.
  2. Start your frying pan warming up (on medium heat) and spray some cooking spray on it.
  3. When the oil is warm, put one slice of bread on it, butter side down.  It should make a strong sizzling sound immediately, rather than a weak sizzling sound that takes a bit to build in volume.
  4. Sprinkle your seasoning on the bread, place the cheese on top, and add more seasoning if you like.  Place the other slice of bread on top, butter side up, and wait a bit for the cheese to warm up (but not start melting).
  5. Flip the whole thing and toast it on the untoasted side.  Pressing it with the spatula is bad and you should feel bad if you do it.  Once it's toasted, take it off, it's done.
Don't bother slicing it diagonally, that's for patient people and little kids.  Just tear into it like you know you want to.  This whole process should only take a few minutes, frying pans are pretty quick at cooking things.

If your frying pan was seasoned, let it cool and then rinse it with water and dry it with a paper towel.  Soap will displace the nice non-stick surface that's been built up (and that the cooking spray contributed to).

Tuesday, February 11, 2014

Programming With Style

A lot of people refer to the combination of whitespace style, brace style, and capitalization style as "coding style", but I personally hate making a verb out of the word "code", so that's the first and last instance of that word you'll see on this blog.

There are a lot of different styles, and for the most part, to each their own.  Mine should more or less already be clear from the number of programming-related posts I've posted here, but just to be specific, I'll go through the languages I use on any kind of a regular basis and explain myself.  Here's a hint: I don't subscribe to any of the styles listed on this page, but I do use elements of many of them.

General things that apply to all languages:
  • I prefer underscores instead of camelCase (regardless of lowerCamelCase or UpperCamelCase).
  • I also tend to put a space before and after comment syntax.
  • I tend to use single-quoted strings most of the time, and only use double-quoted strings when absolutely necessary (for instance, in PHP, using a C-style escape sequence requires a double-quoted string).  This is for performance reasons in scripting languages that apply extra processing to double-quoted strings.
  • I don't subscribe to any variable naming conventions.  I personally like writing code that's very close to readable English, and embedding the type name in the variable name gets in the way of that.
  • I tend to avoid one-liners when possible, but I will chain object references and array indexing all over the place in JavaScript and PowerShell.
  • I overuse parentheses and force my desired order of operations at all times.
  • I hate languages that have no elseif keyword.  I will do else if, but it always looks wrong to me.
Language-specific things, perhaps even with examples when I can't quite put what I'm trying to say into words any other way:



Seriously, I never indent HTML.  I did, initially, when I first learned it, when I was 11.  As I did more and more stuff with HTML I realized that there are too many corner cases where spacing at the beginning of a line actually matters.  I also only ever write XHTML anymore, but use HTML to refer to it.  I tend to use the HTML5 DOCTYPE declaration for simplicity, though I have HTML5 and XHTML 1.0 Strict doctype declarations set as macros in Notepad++.

I do have a style, but it exists to differentiate between inline elements (no preceding newline) and block elements (with preceding newline).  Even then, I ignore it in some cases (tables).  When integrating with JavaScript, I prefer to bind events from the JavaScript side rather than using the old-school event attributes.  This has the plus side of making my scripts only work on standards-compliant browsers.  I hate using browser detection, and it's easily spoofed by user configuration anyway.  My browser detection is "if the page doesn't work, STOP USING INTERNET EXPLORER."

Also, WYSIWYG editors are for n00bs.


At first, I was like
selector { name:value; name:value; name:value; name:value; }
but then I got tired of holding the spacebar, so then I was like
selector { name: value; name: value; name: value; }
The "two spaces as an indent" thing actually came over from mIRC scripting, believe it or not.

JavaScript/PHP/pretty much any C-based language
  • Originally I used as little whitespace as I could get away with (basically just indents and separating keywords), but then I had trouble reading my code.
  • Single spaces used for each indent level, with code on the same line as the opening curly brace.
  • Hardly ever a comment on the same line as an opening curly brace, because that just looks weird.
  • Code blocks only ever surrounded by curly braces if they contain more than one line or if they're a function body.
  • (JavaScript) I disagree with Douglas Crockford.
function function_name( parameter1, parameter2 ) {line of code; line of code; if( condition ) one line; else {two; or; more; lines; } }
I'll put a single line after (on the same line as) an if (and only after an if) if and only if it's return, break, or continue, and it has no else.  I used the word 'if' a lot in that sentence.


That's pronounced "ess-kyu-ell", not "sequel" or "squirrel".

I stole most of this from a friend of mine, who has really good ideas every now and then.  This is mostly for MSSQL, as that's what we were using.
  • SELECT, FROM, and WHERE on their own line
  • For long lists of stuff in the SELECT clause, indent each column, and put commas before column names instead of after.  This makes it easy to add, remove, and comment/uncomment column names.
  • Indent JOINs/CROSS APPLYs in the FROM clause.
  • Using JOINs looks a lot cleaner than relating all your tables together in the WHERE clause (both produce similar results, but JOINs make controlling what you get easier)
  • Indent conditions in the WHERE clause, with your AND/OR before each condition, again to make it easy to add, remove, and comment/uncomment stuff.
  • Probably more, I haven't used SQL on a daily basis since my contract ran out at Silverchair.


For whatever reason I've been putting opening curly braces at the end of the line in Powershell.  Curly braces are mandatory on all code blocks in Powershell, and there's actually a "script block" data type that you can use as a function argument.  I also use tabs instead of spaces here, but generally set the tab size to one character in my editor (Notepad++).  I will use a combination of tabs and spaces to make things line up regardless of tab size if I split lines for readability.  On a side note, Notepad++ really hates it when I try to use a combination of tabs and spaces when indenting a line.  It converts everything to tabs, forcing me to go back and change things back to spaces when they should be spaces.


This one is a no-brainer, mIRC's script editor forces its own style on you.  Curly braces on the ends of lines, two spaces per indent level, with lines broken apart for readability being indented further.  It's not configurable and it enforces the style with a button press in the editor or when you save.  Also, those unquoted strings.  Khaled Mardam-Bey, you silly.

lol, I don't use Perl.  Because Perl encourages writing unreadable code.  For what it's worth, I have programmed in Perl before (an IRC bot, designed to run via XChat), but everything I did felt incredibly hack-ish, and no other language has ever given me that vibe.

I've used other languages here and there (bash, Java, Lisp, Python), but not nearly often enough to really matter.

Sunday, February 9, 2014

Wallpaper editing math kinda sucks

I don't think I ever posted about this, and I'm too lazy to go check.  And no, I'm not resuming wallpaper updates.  I don't browse /w/ anymore (it sucks now) and I only occasionally save an image for use as a wallpaper.


For quite a while, I would resize and rescale wallpapers to the nearest standard monitor aspect ratio before adding them to my collection or uploading them in one of my wallpaper updates.  To facilitate doing this, I wrote a script in PHP that I could give the dimensions and the target aspect ratio to, and it would calculate the closest dimensions that I could resize the image to in order to achieve that aspect ratio, to minimize the amount of editing I'd have to do.

Like I said in the first sentence of this post, I don't know if I ever made the existence of this script known here, so this post will do just that.  But first, an overview of its features.
  • When supplying the image dimensions, you can either type them in manually, or upload the image.
  • When selecting the aspect ratio, there are a number of common aspect ratios available in a dropdown for easy access.
  • You can also specify a custom aspect ratio, for if you're a n00b and don't know your monitor's aspect ratio, or you're editing something for a mobile device that might use some weird aspect ratio.
  • It returns a minimum of two resolutions and a maximum of four, and tells you the difference in number of pixels for each dimension, so you can decide which one you want to use.
  • The resolutions returned require an absolute minimum amount of editing.
I'm really only posting this because I just added some stuff and reworked some stuff that was stupid to be less stupid.  For shits and giggles, here's what I changed.
  • Added: Ability to specify a custom aspect ratio.
  • Added: Reducing the supplied custom aspect ratio, as the function that looks for target resolutions needs this to be reduced.
  • Added: Slightly better error messages.  Now, instead of just insulting you, they also tell you what you did wrong, so you can go fix it, you horrible person.
  • Changed: Dimension differences were previously "width bigger, height smaller", etc., they are now pixel differences per dimension (i.e. "width + 8 pixels, height - 4 pixels").
  • Changed: Better input verification (regular expressions go).
  • Removed: Arbitrary restriction on image width and height that existed because of my previous shitty input verification.
Necessity is the mother of all invention, and this most recent update (and the script as a whole) is certainly no exception.  I'm fucking around with making wallpapers for my phone, which need to be in a 4:5 aspect ratio and ideally 176x220.  Rather than just adding 4:5 to the aspect ratio dropdown, like I apparently did with 8:7 for making ToxicOS wallpapers for my PS2, I figured it would be better to just allow any aspect ratio to be used.

Reducing a fraction programmatically is a fairly simple process, but involves calculating the greatest common denominator of the two values, which is a rather interesting calculation.  However, once you have the GCD, you simply divide the two values by said GCD and there you go, reduced fraction.  This is how I reduce the values provided in the custom aspect ratio boxes so that the script will work correctly.

Anyway, here's what you've probably been wanting this entire time if you're still reading this: the link.  Enjoy.  It's rather lacking in bells and whistles, but oh boy is it ever functional.

Saturday, February 1, 2014

Chrono Trigger Tech Point Grinding Notes

In the early game, when you go to the Millenial Fair with Crono and bump into Marle, your only option to get their first two skills is Guardia Forest in 1000 AD, which gives 15 Tech Points per run.  The run is pretty simple, all the enemies are visible, and all the battles are avoidable in case you're running low on HP.  There honestly isn't much else to say about it, since the early game has simple, easy to defeat enemies for a pretty good reason.  When you need to recover HP/MP, you can go sleep at Crono's house for free.

Guardia Forest in 600 AD is useful for getting Lucca her first two skills.  I can never remember the tech point yield per run here.  It's more than in 1000 AD, as there's one extra battle and some give more tech points.  Also, some enemies are hiding and waiting to ambush you, but again, all battles are avoidable.  When you need to recover HP/MP, you have options within Guardia Castle that are free: sleep, or eat.  Guardia Forest in 600 AD ceases to be useful for Tech Point grinding at a certain point, though.  It loses all but two encounters, giving a paltry eight Tech Points.

The meat of this post will be discussing the Forest Maze in 65,000,000 BC, which is where I do the vast majority of my tech point grinding.  When I refer to a "run" here, I'm actually making two passes through the Forest Maze.  The first is entering from the Ioka Village side, and the second is entering from the Reptite Lair side.  HP/MP can be replenished for free in the closest Ioka hut, the one with the sweet water.

It's kind of interesting that colored enemies in Chrono Trigger fall into one of two conflicting groups: some will be vulnerable to the magic that the color suggests moreso than anything else, and the others will be resistant or immune to that magic and vulnerable to its opposite.

Enemies you will encounter:
  • Gold Eaglet: 400 HP, divebomb attack, no resistances or weaknesses.  After being hit twice, regardless of how much damage the hits dealt, it turns into a Red Eaglet.  It's possible to kill it before it turns into a Red Eaglet.
  • Red Eaglet: Carries over whatever HP the Gold Eaglet has after it takes the second hit.  Still has the divebomb attack, but now counterattacks whoever hit it with a fire attack if it's dealt non-fatal damage.  Also gains resistance to physical.  May have an elemental weakness, I personally haven't tested it.
  • Kilwala: 160 HP, runs up and hits you, no resistances or weaknesses.
  • Winged Ape: 450 HP, throws a party member either at another party member or the ground, resistant to magic.  These guys seem to have a long time between their attacks, so they'll likely only ever hit you once.
  • Runner: 196 HP, runs up and hits you, resistant to physical.  Nothing really special even with their physical resistance.
All of the enemies encountered give 2 Tech Points each.

Specific encounters, in order, from Ioka Village entrance:
  • 2x Gold Eaglet
  • 3x Kilwala
  • 1x Winged Ape
  • 1x Winged Ape, 2x Kilwala
  • 2x Runner
  • 3x Gold Eaglet
  • 2x Runner
  • 1x Winged Ape, 1x Kilwala
Total: 18 enemies, 36 Tech Points.

Specific encounters, in order, from Reptite Lair entrance:
  • 1x Winged Ape, 1x Kilwala
  • 2x Runner
  • 3x Gold Eaglet
  • 2x Runner
  • 1x Winged Ape, 2x Kilwala
  • 1x Winged Ape
  • 2x Kilwala
  • 2x Gold Eaglet
Total: 17 enemies, 34 Tech Points.

The optimum time to do this run is as soon as the story takes you to 65,000,000 BC for the first time, to get the Dreamstone.  The Forest Maze can't even be traversed until the Gate Key gets stolen.  This is a prime time because Ayla is temporarily in the party, and will leave once you get the Gate Key back.  Make sure to get her all of her techs before she leaves!

I also prefer to hold off on getting Robo's Tech Points until I get here.  It's a bit of a stretch, yes, but the only other easily grindable area is Guardia Forest in 1000 AD, and getting a few thousand Tech Points there takes forever.

Basically, once I arrive here, I don't leave the time period until I have everyone's techs, except for Frog since he doesn't join permanently until after you take the Dreamstone to Melchior and reforge the Masamune.  There's nothing too painful about this tech point grinding run, other than the beginning when you're low-ish on HP and have to heal slightly mid-run (use MP for it, save your items!).  Once you get to the point where everyone has 400-500 HP, death is less of an issue.  As long as you don't put both Marle and Lucca in the party at the same time after Ayla leaves, you'll always have good sources of damage.

Some of the battles can be encountered in a different order than I listed above, but that's my preferred order because it flows well.  Also, just like with Guardia Forest, all battles here are avoidable.  Unlike Guardia Forest, though, every single battle is an ambush.  I prefer to use regular attacks rather than magic, but magic can bring a swift end to some of the battles, so go that route if you like.  I will use Crono's Spincut from time to time, since it's essentially spending MP to guarantee a critical hit.

Without Lucca and the SightScope, you can count enemy HP to be reasonably sure when things only need one more hit.  This is useful for avoiding the fire counterattack from the Red Eaglets.  This is all optional anyway, because once you reach a certain point you can trigger a battle and mash A until victory.  Also, here's a tip I haven't seen anywhere: The X button acts as a shortcut for the regular attack, regardless of what's selected in the menu.  You can use the X button as well as the A button for faster button mashing, if you're going the "regular attacks only" route like me.

Now, Marle and Lucca have crap damage on their regular attacks, because their regular attacks use their Hit stat and everyone else's regular attack uses Power.  Power can be increased much higher than Hit can.  However, they are capable of dealing almost respectable damage via a critical hit.  How is this useful?  Well, I'll tell you.  The game doesn't decide when you land critical hits as you might think.  It actually generates a sequence of critical hits that you can learn and exploit.

I haven't gone very in-depth with experimenting with this, in terms of how it reacts with using techs, but I do know that the counterattack accessories (the Fury Band and the Rage Band) use a hit in the sequence.  Furthermore, anything that affects a character's critical hit rate will of course affect the sequence.  Forest Maze, on this doubled up run, seems to have just the right number of enemies to expose this sequence in the right conditions, so you may not even have to try.  If you notice that you always get a critical hit in the same place on each run, congratulations, you've noticed part of the sequence.  It's tough to notice it that way, because you have to take enemies down in the same number of hits every time, and damage has an inherent randomness to it.

Finally, because grinding is something that nobody really enjoys (and if they say they do, they're lying), it's important to be able to break this large task of getting a few thousand Tech Points per character down into reasonable chunks.  First, since the party size is three, you can get three people's Tech Points simultaneously, at least up until Crono learns Luminaire.  Next, there's a small bit of math you can do to figure out how many times you'll have to do this run to get the next techs for everyone, and even find out in advance which battle they'll learn the tech on.  It's pretty simple.

Because I am who I am, I usually have a PowerShell window open.  PowerShell is handy for this because you can type in a mathematical expression on the command line and it'll evaluate it for you.  And because PowerShell comes standard with any recent Windows OS, if you have Windows, you have PowerShell.  There are solutions for other OSes too.  I would personally just install Python, run it from the Terminal in either Mac OS or Linux, and be done with it.

To calculate how many runs it will take, look at the Techs page of the menu, and select one of the characters.  Divide the number of Tech Points the character has left for their next tech by 70.  You'll likely get a floating point value, but more importantly, you now know how many times you'll have to do this run through Forest Maze to get them their next tech.  Do this for all three characters you have in the party, recalculate every once in a while during your session (always at the end of a run!), and then again at the end of the session so you know where you stand for your next session.

To find out which battle they'll learn the tech on, you need the modulus operation ('mod' for short, in speech), which in both PowerShell and Python, is %.  The remaining Tech Points mod 70 will give you the remainder after division, and then you can look through your sequence and the number of Tech Points you gain in each battle to tell precisely where they'll learn the tech.

For example, let's say that at the beginning of a run, Lucca has 126 Tech Points left until she learns Mega Bomb.  Dividing this value by 70 gives us 1.8, indicating that she's got basically two runs left to get Mega Bomb.  Now mod the remaining Tech Points by 70, and you'll get 56.  Assuming you're using my battle sequence, she'll learn Mega Bomb on the Winged Ape and two Kilwalas as you work your way back through from the Reptite Lair entrance.

None of the math really matters in the long run, because you'll learn everything when you learn everything even if you don't calculate how long it'll take or where it'll happen, but this is to sate your mind's desire for accomplishment.  The big goal is getting everyone's techs, but that's a long way away.  Giving yourself smaller goals in the meantime, and breaking the large task down into several smaller tasks that are more manageable, will keep you sane and continuing to play the game.

Keeping yourself sane is why I also recommend muting the TV and listening to music from your playlist instead of listening to the game audio while grinding Tech Points.  Don't get me wrong, Chrono Trigger's soundtrack is amazing, but having it going constantly while grinding keeps you realizing where you are and what you have left to do.  You can make the whole thing a blur by listening to your own music instead.

Anyway, this post is long enough.  There's a smaller bit left still, which is getting Magus his Tech Points, but at that point, you have a lot of options available.