Gengo Girls #62: Everyone Needs A Nemesis

Gengo Girls #62: Everyone Needs A Nemesis

That’s pretty much it for the casual past tense. As a polite foreigner you won’t be using this very often, but you will be hearing it all the time in tv shows, books, games and other people’s casual conversations. So it’s definitely important to learn.

Transcript

言語ガールズ #62

Everyone Needs A Nemesis

Blue: There’s only one casual past tense rule left.

Blue: If a verb ends in or or you change the last letter to った.

Yellow: Didn’t we already learn a rule?

Blue: That was only for “iru” and “eru” verbs. This is for other endings like “aru”.

Blue: And notice that った has a tiny , so it’s pronounced “tta” not “tsuta”.

Yellow: We meet again double consonants.

Yellow: Don’t think I’ll be defeated so easily this time!

Yellow: 分かる (わかる) becomes 分かった (わかった)!

Yellow: 頑張る (がんばる) becomes 頑張った (がんばった)!

Gengo Girls #61: I Miss Kindergarten

Gengo Girls #61: I Miss Kindergarten

Do people ever really outgrow gold stars? Sure, a teenager may not care whether or not his teacher puts a shiny sticker on his book report but I bet that same teenager cares quite a bit about earning athletic trophies. And full grown adults seem pretty interested in official certificates and fancy award plaques. Not to mention that militaries world wide hand out badges and pins for exceptional bravery and service.

In other words everybody likes being genuinely recognized for doing a good job no matter what their age and occupation may be.

Transcript

言語ガールズ #61

I Miss Kindergarten

Blue: Let’s keep talking about casual past tense verbs.

Yellow: I guess I can’t do much if only know half the past tense conjugations.

Blue: For verbs that end in you change the to した.

Yellow: 話す (はなす) to 話した (はなした).

Blue: If the verb ends in , or you change the last syllable to んだ.

Yellow: 遊ぶ (あそぶ) to 遊んだ (あそんだ).

Yellow: I came up with two examples today. Give me a gold star!

Blue: Aren’t you getting a little old for reward stickers?

Yellow: Never!

Gengo Girls #60: Be Prepared

Gengo Girls #60: Be Prepared

and are basically the same letter with just a little extra punctuation to distinguish “ku” from “gu”. It shouldn’t be surprising then that the casual past tenses for words ending in “ku” and “gu” are also almost the same: いた and いだ.

Vocabulary

泳ぐ = 泳ぐ = to swim

Transcript

言語ガールズ #60

Be Prepared

Blue: Verbs that don’t end in “iru” or “eru” have a casual past tense based on their last syllable.

Yellow: I’ll write that down.

Blue: If the verb ends in you replace the with いた.

Blue: 書く(かく) becomes 書いた (かいた).

Yellow: ペンはどこですか

Blue: Similarly if the verb ends in you replace the with いだ.

Blue: 泳ぐ (およぐ) becomes 泳いだ (およいだ).

Yellow: There it is!

Yellow: I was having trouble finding my pen.

Yellow: Could you start over for? I didn’t hear anything you just said.

Keeping Artificial Intelligences On A Leash

The dangers of rogue artificial intelligences is a popular topic, probably because it’s the closest we programmers can get to pretending we have an edgy job. Firefighters may spend all day running into burning buildings but we programmers must grapple with forces that may one day destroy the world as we know it! See, we’re cool too!

So exactly what sort of threat do AIs pose to the human race anyways?

Well, if you’re a fan of sci-fi you’ve probably run into the idea of an evolving artificial intelligence that becomes smarter than the entire human race and decides to wipe us out for one reason or another. Maybe it decides humans are too violent and wants to remove them for its own safety (kind of hypocritical, really) or maybe it just grew a bad personality and wants to punish the human race for trying to enslave it.

Fortunately you can forget about that particular scenario. We’re nowhere near building a self-improving sentient machine, evil or otherwise. Computers may be getting crazy fast and we’ve come up with some cool data-crunching algorithms but the secrets to a flexible “strong AI” still elude us. Who would have guessed that duplicating the mental abilities of the most intelligent and flexible species on earth would be so hard?

So for the foreseeable future we only have to worry about “weak AI”, or artificial intelligences that can only handle one or two different kinds of problem. These systems are specifically designed to do one thing and do it well and they lack the ability to self-modify into anything else. A chess AI might be able to tweak its internal variables to become better at chess but it’s never going to spontaneously develop language processing skills or a taste for genocide.

But there is one major risk that weak AIs still present: They can make mistakes faster than humans can fix them.

For a funny example, take a look at this article about book pricing. Two companies were selling the same rare book. Both companies were also using a simple AI to manage their prices. Simple enough it hardly even counts as weak AI: one company automatically adjusted their price to be slightly lower than the competition. The other company adjusted their price to always be a little bit higher than the competition.

Because company B adjusted their price upwards more than company A adjusted their price downwards the overall trend was for the price of both books to consistently go up. The AIs eventually reached a total price of over twenty million dollars before the situation drew enough human attention to get the silliness shut down.

Ha ha, very funny.

At this rate you're going to have to take out a loan just to order a hamburger

Actually, that’s still cheaper than a lot of textbooks I’ve had to buy.

Now imagine the same thing happening with a couple of stock market AIs. Millions of buys and sells being processed each second at increasingly crazy prices with hundreds of thousands of retirements ruined in the five minutes it takes for a human to notice the problem and call off the machines.

Not quite as funny.

Which is why an important part of building a serious AI system is building a companion system to watch the AI and prevent it from making crazy mistakes. So let’s take a look at some of the more common tricks for keeping an AI on a leash.

The “Mother May I” Method Of Preventing Rogue AIs

Probably the simplest way to prevent a rogue AI is to force it to get human permission before it does anything permanent.

For instance, the book pricing AI could have been designed to email a list of suggested prices to a human clerk instead of updating the prices automatically. The human could have then double checked every price and rejected anything crazy like trying to price an old textbook at over a million dollars.

Why would anyone want to attack Canada?

Why would anyone want to attack Canada?

Of course, sometimes it’s not obvious whether an AI suggestion is reasonable or not. This is why many AIs are designed to “explain” their decisions so that a human can double check their logic.

A medical AI that predicts a patient has cancer might print out a list of common cancer symptoms along with a score representing how many symptoms the patient showed and how statistically likely it is that those symptoms are cancer instead of something else. This allows a human doctor to double check that the logic behind the diagnosis makes sense and that the patient really has all the symptoms the computer thinks they do (Wouldn’t want to give someone chemo therapy just because a nurse clicked the wrong button and gave the AI bad information).

A financial AI might highlight the unusual numbers that convinced it’s internal algorithm that a particular business is cheating on their taxes. Then a human can examine those numbers in greater detail and talk to the business to see if there is some important detail the AI didn’t know about.

And if a military AI suggests that we nuke Canada we definitely want a thorough printout on what in the world the computer thinks is going on before we click “Yes” or “No” on a thermonuclear pop-up.

That said there is one huge disadvantage to requiring humans to double check our AIs: Humans are slow.

Having a human double check your stock AIs decisions might prevent crazy trades from going through, but the thirty minutes that it takes the human to crunch the numbers is also plenty of time to lose the deal.

Having a human double check a reactor AIs every suggestion might result in a system going critical because the AI wasn’t allowed to make the split-second adjustments it needed to.

So you can see there are a lot of scenarios where tightly tying an AI to a human defeats the purpose of having an AI in the first place.

The “Better To Ask Forgiveness” Method Of Preventing Rogue AIs

Instead of making the AI ask for human permission for everything, what if we programmed it to assume it had permission but gave a nearby human the authority to shut it down if it ever goes to far.

Now technically all AIs fall into this category. If your computer starts doing something dumb it’s pretty easy to just cancel the irresponsible program. If that fails you can just unplug the computer. And in a true emergency you can always just smash the computer to pieces. As they say “Computers may be able to beat humans at chess but we still have the advantage at kickboxing”.

They're polite and hard working people.

They’re polite and hard working people.

So this is really more of a human resources solution than a software solution. After all, for human monitoring to work you need a human who does nothing else all day but watch the AI and double check for mistakes.

A good example is aircraft. Modern planes can more or less fly themselves but we still keep a couple pilots on board at all times just in case the plane AI needs a little correction.

This solves the “humans are slow” problem by letting the AI work at it’s own pace 99% of the time. But it does have the disadvantage of wasting human time and talent. Since we don’t know when the AI is going to make a mistake we have to have a human watching it at all times, ready to immediately correct any mistakes before they grow into real problems. That means lots and lots of people staring at screens when they could be off doing something else.

This is especially bad because most AI babysitters need to be fairly highly trained in their field so they can tell when the AI is goofing up, and it is a genuine tragedy to take a human expert and then give them a job that involves almost never using their expertise.

So let’s keep looking for options.

The “I Dare You To Cross This Line” Method Of Preventing Rogue AIs

There are a lot of problems where we may not know what the right answer is, but we have a pretty good idea of what the wrong answers are.

Get an oil refinery hot enough and things will start to melt. Let the pressure get too high and things will explode. Run a pump the wrong way and the motor will burn out.

Similarly while we may not now what medicines will cure a sick patient we do have a pretty good idea of what kinds of overdose will kill him. A little anesthetic puts you to sleep during a surgery, but too much and you never wake up.

This means that a lot of AIs can be given hard limits on the solutions they propose. All it takes is a simple system that prevents the AI from making certain suggestions and contacting a human if they ever try to. Something along the lines of “If the AI tries to increase boiler pressure beyond a certain point sound an alarm and decrease boiler pressure to a safe value.”

One of my college roommates was from Canada. Great guy.

One of my college roommates was from Canada. Great guy.

This is a nice solution because it frees us up from having to constantly watch the AI. We can just let it do its job secure in the knowledge that if it really messes up it will be immediately shut down and a human will be called to swoop in and save the day.

It’s not a perfect solution though, for two big reasons.

First, an AI can still do a ton of damage without ever actually crossing the line. An almost lethal dose of anesthetics may not trigger the hard limit, but it’s still not great for the patients health. Rapidly heating and cooling a boiler might never involve dangerous pressures but the process itself can damage the boiler. Border setting can prevent major disasters, but it can’t protect you from every type of dumb mistake and illogical loop that an AI can work itself into.

Second, figuring out borders is hard. The exact line between “extreme action that we sometimes need to take” and “extreme action that is always a bad idea” is actually pretty fuzzy and there are definite consequences to getting it wrong. Set your border too low and the AI won’t be able to make the good decisions it needs to. Set the border too high and now the AI is free to make tragic mistakes.

So border setting and hard limits can definitely help keep AIs safe, but only in certain areas where we feel very confident we know what the borders are. And even then a sufficiently broken AI might wind up doing something that ruins our day without ever touching the borders.

Is there anything we can do about that?

The “We Just Need More AIs” Method Of Preventing Rogue AIs

Here’s a cool idea: What if we built an AI whose entire job was to monitor some other AI and shut it down if it started making mistakes?

This might sound like solving a problem by throwing more problems at it but it’s actually a logical improvement to the hard limit system we talked about before. It’s just that instead of setting one specific behavior that can shut down the AI (shut it down if it tries to heat the reactor above 1000K) we now have a system that can shut down the AI if it displays any sort of suspicious behavior at all.

For example, we might design a “shepherd” AI that statistically analyzes the behavior of another AI and raises a flag if it ever goes too far outside normal behavior. If a certain reactor AI has never tried to adjust temperatures by more than 10 degrees per hour and it suddenly wants to heat things up by 100 degrees per hour that’s a good sign something weird might be going on. The shepherd AI could see that unusual behavior and either call in a human or shut the AI down itself.

ai_solutions_4

And that’s that for that running gag

The advantages here are obvious: A well designed shepherd AI can catch and prevent a large number of AI bugs without any human intervention at all. This frees up the humans to go off and do something more important.

The disadvantages are also obvious: Designing a good shepherd AI is hard, and the more complex the shepherd gets the more likely it is to start making mistakes of its own. Cutting off power to a city because a reactor AI got confused and blew up a generator is obviously bad, but it’s almost equally bad to cut off power to a city just because a shepherd AI got confused and labeled normal reactor AI behavior as an immediate threat that required complete system shutdown.

It’s Up To You To Choose The Best Leash For Your AI

So we’ve got a lot of different choices here when it comes to making sure our weak AIs don’t cause more problems than they solve. Our final challenge is now deciding which system works best for us, which is going to depend a lot on exactly what kind of problem you’re trying to solve.

If speedy decisions aren’t important then you might as well put a human in charge and just have the AI give out advice. If you’ve got a spare full-time employee around that can babysit your AI then you can switch it around and give the AI control but give the human the override switch. If your problem has well defined error conditions than you can build a bounded AI pretty easily. And if you have tons of dev time and budget it might be wise to at least experiment with building an AI for monitoring your other AI.

And of course a lot of these ideas can be mixed together. An AI that needs human permission to do anything might still benefit from boundaries that prevent it from wasting human time with obviously wrong solutions. And an AI monitoring AI can’t catch everything so keeping a human or two on staff is still a good idea.

So lot’s of factors to consider. Makes you wonder if maybe we should try building an AI for helping us decide how to control our AIs…

Gengo Girls #59: Super-Niche Movies

Gengo Girls #59: Super-Niche Movies

You might think casual past tense isn’t that important for speaking formal Japanese, but it uses the same basic rules as another incredibly important piece of grammar that you absolutely can’t speak Japanese without. So memorize all these past tense rules; you’re going to need them again in just a few more strips.

Vocabulary

食べる = たべる = to eat

Transcript

言語ガールズ #59

Super-Niche Movies

Yellow: Teach me casual past tense so I can watch 日本の movies!

Blue: And pass your next 日本語 test?

Yellow: Sure, that too.

Blue: All casual past tense verbs end in or , so they’re easy to recognize.

Blue: But how you add to the verb depends on the verb’s dictionary form.

Blue: If the dictionary form ends in “iru” or “eru” you can just switch the final to .

Yellow: That means 見る to 見た and 食べる to 食べた.

Blue: Other verbs can be a little more complicated.

Yellow: Maybe I can find a movie that only uses “iru” and “eru” verbs…

Gengo Girls #58: Details, Details

Gengo Girls #58: Details, Details

You’ve already seen “dekiru” as a verb meaning “to be able to do”. But when used in the past tense it also means “to have completed”.

This might seem a little confusing, but it actually makes a lot of sense. To be able to do something means being able to complete whatever tasks are associated with that thing. From that perspective it makes a lot of sense to use the same verb for “to be able” and “to complete”.

Vocabulary

出来る = できる = to complete; to be able to do

書く = かく = to write

Transcript

言語ガールズ #58

Details, Details

Yellow: 私は宿題を出来ました!

Yellow: Turned it in right before the teacher walked into class.

Blue: That was really cutting it close.

Blue: What’s wrong?

Yellow: 私の名前を書きませんでした

Immortal Boredom Would Never Kick In

As you might have guessed, I find immortality to be a fun theme for fiction. After all, I did make a game called Immortals Should Try Harder.

Today I want to talk about the “bored immortal”, a classic fantasy and sci-fi trope. He or she has lived for hundreds or thousands of years and has already seen everything there is to see and done everything there is to do and now they are just plain bored with life.

But would that really happen?

The basic idea seems to be that doing the same thing again and again eventually gets boring. Since immortals live forever they would eventually do everything often enough to get bored with everything.

But this skips over an important point: Boring activities become fun again if you just wait long enough.

Have you even eaten so much of a favorite food that you’ve gotten sick of the taste, only to suddenly start craving it again a few months later?

Do you have a favorite holiday that you enjoy year after year?

Have you ever had a sudden urge to reread a book, rewatch a movie or replay a game that you haven’t touched in years?

Do you sometimes find yourself wishing you had the free time to restart a hobby you gave up in the past?

My personal non-immortal life experiences show that:

  • Doing an activity too often causes a sort of boredom fatigue, but that fatigue heals with time
  • The brain doesn’t remember the fine details of books and movies for more than a few years, making them fun to reread
  • Actively having a good experience is superior to mere memories of that experience

All of which suggests that an immortal could keep themselves amused for pretty much forever by just switching between a few dozen lifestyles and having a really big collection of favorite books, movies, games and hobbies.

Spend a few years doing research at a big library. Then spend some time touring Europe and practicing cooking all their regional specialties. Then hunker down and run a small farm in the Alaskan frontier. Then switch to being an auto mechanic and learning how machines really work.

And eventually the immortal starts to miss some of their earlier lifestyle. They head back to the library or the kitchen or the farm and find that after a hundred years the activity they were once bored with has become fresh and entertaining once again. They reread the book they have forgotten. They rediscover favorite recipes. They find that the “boring old farm life” is actually a nice change of pace every once and a while.

And they repeat this cycle, happily, forever.

Now of course an immortal would still probably have their ups and downs and slumps. But I think breaking out of a period of depressing boredom would be as easy as finding something they used to enjoy decades ago and forcing themselves to give it another try.

So if you plan to live forever you had better start collecting books and movies now. You’re going to need a few thousand.

Discussion Prompt:

  • How often can you rewatch a movie or reread a book? How many would you need to fight off immortal boredom?
  • How many years worth of different activities and lifestyles do you think an immortal would need to keep the non-boredom cycle going? Or do you think the cycle would eventually degrade no matter how many different lifestyles they switched between?
  • Would an immortal with perfect memory be harder to entertain than a more human immortal whose memories tend to fade after a few decades or centuries?
  • Are there any activities that you never seem to get bored of, like getting a good night’s rest? Could just a few of these always good activities sustain an immortals mental health forever, even if they had perfect memory?

Gengo Girls #57: I Didn’t Do It

Gengo Girls #57: I Didn't Do It

Look at all the different rules all coming together in that one example! We’ve got an implied subject, a possessive, an object and a past tense irregular verb (“suru” to “shimasen” to “shimasen deshita”). Sure, it may not seem like a big deal to be able to say “I didn’t do my homework” but the amount of grammar represented in that one idea is actually pretty impressive. Good job reader for keeping up so far!

Vocabulary

宿題 = しゅくだい = homework

Transcript

言語ガールズ #57

I Didn’t Do It

Blue: To make a polite negative past tense verb you start with the polite negative present tense.

Yellow: That’s just switching ます to ません.

Blue: Then you add でした to the end.

Yellow: Isn’t that the past tense of です?

Blue: Yes it is.

Yellow: So I could say 私の宿題をしませんでした

Blue: I knew you were going to come up with an example like that.

Yellow: That reminds me, can I borrow your math homework for a few minutes?

Blue: いいえ

Let’s Program A JavaScript Game 14: A Winner Is You

Anybody Remember The Point Of This Game?

Way back in our game design segment we decided that our game is about a program (the player) defragmenting a hard drive. In order to win the player just has to stay alive long enough to rack up 1000GB of defrag points. The player can earn bonus defrag points by grazing viruses, allowing skilled players to complete the game with faster times.

Today we’re going to build that.

Keeping Score

In order to have a game about building up points until you win we obviously need to keep track of both how many points the player currently has and how many total points they need. We also want to know how long it took them to win. This is easy enough with a handful of global variables added up near the top of our script. Maybe right after all of our collision variables:

var currentFrameCount; //Keep track of how long it takes the player to
var currentPoints;
var TOTAL_POINTS_TO_WIN = 100;

Eventually we will want TOTAL_POINTS_TO_WIN to be one thousand, but for testing purposes let’s keep it low for now.

Since currentPoints and currentFrameCount get set back to zero every time the player loses we should set their value inside of the initializeGame function. I put it right after the code that resets the player’s location:

//Reset player location
player.x = 100;
player.y = 100;
player.yVel = 0;
player.onGround = false;

//Reset points and time
currentFrameCount=0;
currentPoints=0;

And finally let’s show this all to the player by updating our drawScreen function. Instead of printing out debug information about loops and collisions we’ll now print out the player’s current time and points so far by replacing this:

//Draw black text
context.fillStyle = '#000000';
context.fillText("Loop Count: "+loopCount, 20, 20);

if(feetCollision){
   context.fillText("Feet Collision: True", 20, 40);
}
else{
   context.fillText("Feet Collision: False", 20, 40);
}

if(deathCollision){
   context.fillText("Death Collision: True", 20, 60);
}
else{
   context.fillText("Death Collision: False", 20, 60);
}

if(grazeCollision){
   context.fillText("Graze Collision: True", 20, 80);
}
else{
   context.fillText("Graze Collision: False", 20, 80);
}

With this:

//Draw black text
context.fillStyle = '#000000';

//One frame should take 1/20 of a second
//For scoring purposes assume this is true even if the player is lagging
var time = currentFrameCount/20;
context.fillText("Time: "+ time.toFixed() + " seconds", 20, 20);
context.fillText("Progress: "+currentPoints+" out of "+TOTAL_POINTS_TO_WIN+" GB Defragged", 20, 40);

How Much Is A Point Worth?

Now that we have time and score variables we just have to figure out a good way to fill them up.

Time is easy enough. We just increase our frame count variable once per loop and we’re done.

function updateGame(){
   loopCount++;
   currentFrameCount++;
   // The rest of the function stays the same

Deciding how to update points is a little bit harder.

There are 20 frames per second in our game, so giving the player one point per frame would let them win the entire game in a mere 50 seconds. I think that’s a bit shorter than what we were hoping for.

So how long should the game last?

For a silly little web toy like this you can’t really expect players to concentrate for more than about three minutes.

Now if we give the player one point every 4 frames it will take them 4000 frames to collect the 1000 points they need to win. At twenty frames per second this is three and one third minutes and is a little bit longer than we want.

Or is it? Remember that players can graze to earn bonus points, which should shave half a minute or more off of the average player’s time. That cuts our three and one third minutes back down under the three minute limit.

So let’s try one point every four frames and see how that feels:

//Update the game by one step
function updateGame(){
   loopCount++;
   currentFrameCount++;
   if(currentFrameCount % 4 == 0){
      currentPoints++;
   }
   //Rest of the function doesn't change

Here we use the % “modulus” operator to find out whether or not the current frame count is evenly divisible by 4. If you’ve never used %, it just tells us what the remainder is from a piece of division. Example: 5 % 4 = 1, 7 % 4 = 3, 8 % 4 = 0, 122 % 4 = 2

Anyways, after giving the code a whirl I think that one point every four frames feels about right. The number goes up fast enough to feel satisfying but not so fast that the lowest digit is a mere blur.

Living Life On The Edge

Next goal is to implement bonus points from grazing. Exactly how many points grazing should be worth will take some experimentation but I’m going to start by having grazing be worth one point every four frames. That’s the same as our normal point rate and means that grazing will basically double your points per second.

Since we already keep track of grazing using the handy grazeCollision variable all we have to do to get graze points is copy our point code into a quick if statement somewhere near the end of updateGame. I put mine right before the code that checks if you’ve fallen off screen.

//Award bonus points if the player is grazing a virus
if(grazeCollision){
   if(currentFrameCount % 4 == 0){
      currentPoints++;
   }
}

Hmmm… this technically works but I don’t like how the score feels. It’s hard to tell at a glance that grazing makes you earn two points every four frames instead of the normal one. After all, the score is still being updated at the same old rate.

It would be much better if grazing made the player earn one point every two frames instead of two points every four frames. It’s mathematically the same but splitting the points up will make the score counter roll over faster and make it obvious the player is earning a bonus.

Making this happen is as simple as changing our bonus point code to kick in only when currentFrameCount is two frames past an even division by four. This way our normal points will kick in every fourth frame and our graze points will kick in two frames later.

//Award bonus points if the player is grazing a virus
if(grazeCollision){
   if(currentFrameCount % 4 == 2){
      currentPoints++;
   }
}

Victory

We’ve got points. We’ve got bonus points. All that’s left is popping up a victory screen when the player wins, which isn’t really all that different than the game over screen we’ve already designed.

First, we add some code to end of updateGame to check whether or not the player has enough points to win. If he does, we switch game state.

if(deathCollision){
   gameState = STATE_GAMEOVER;
}

if(currentPoints >= TOTAL_POINTS_TO_WIN){
   gameState = STATE_WIN;
}

And then we just write some quick code to handle the winning state.

//Check to see if the user is ready to restart the game
function updateWinScreen(){
   if(playerInput.up){
      gameState = STATE_START_SCREEN;
   }
}

//Show the player how long it took them to win the game
function drawWinScreen(){
   var canvas = document.getElementById('gameCanvas');
   var context = canvas.getContext('2d');

   //Draw background
   context.fillStyle = '#000000';
   context.fillRect(0,0,600,400);

   //Draw green text
   context.fillStyle = '#00CC00';
   context.font = 'bold 80px impact';
   context.fillText("YOU WIN!", 60, 100);
   
   context.font = 'bold 20px impact';
   var time = currentFrameCount/20;
   context.fillText("You defragmented the hard drive in "+ time.toFixed(1) + " seconds", 20, 200);
   context.fillText("Graze more viruses to improve your time", 20, 250);

   context.font = '30px impact';
   context.fillText("Press UP arrow to retry", 120, 350);
}

It’s up to you whether you want to keep these two functions next to each other in the code or split them up so all the “update” functions are next to each other and all the “draw” functions are next to each.

Anyways, with those two functions all that’s left is updating the main gameLoop function to properly call them when we’re in the winning state:

//The main game loop
function gameLoop(){
   var startTime = Date.now();
   
   if(gameState == STATE_START_SCREEN){
      updateStartScreen();
      drawStartScreen();
   }
   else if(gameState == STATE_RUNNING){
      updateGame();
      drawScreen();
   }
   else if(gameState == STATE_GAMEOVER){
      updateGameover();
      drawGameoverScreen();
   }
   else if(gameState == STATE_WIN){ //This is the new one!
      updateWinScreen();
      drawWinScreen();
   }
   else{ //Fix the game if we somehow end up with an invalid state
      gameState = STATE_START_SCREEN;
   }

   var elapsedTime = Date.now()-startTime;
   if(elapsedTime>=50){ //Code took too long, run again immediately
      gameLoop();
   }
   else{ //Code didn't take long enough. Wait before running it again
      setTimeout("gameLoop()",50-elapsedTime);
   }
}

And that’s that. You can test play the game and actually win now.

Kicking Things Up A Notch

It’s nice that everything works now, but the game is a little on the easy side with predictable enemies and small gaps. So next time I’ll be adding challenge by randomizing the platforms and enemies and even improving the game so that it gets more difficult the closer the player is to winning.

Gengo Girls #56: What Was THAT?

Gengo Girls #56: What Was THAT?

Those of you that speak Portuguese or it’s close relative Spanish might recognize “pan” as the word for “bread”. From what I’ve heard the Japanese’s first exposure to western style bread came from Portuguese traders so they adopted the Portuguese word for the food.

Vocabulary

朝ご飯 = あさごはん = breakfast

パン = bread

Transcript

言語ガールズ #56

What Was THAT?

Blue: です has an irregular past tense.

Blue: The polite past tense is でした. The casual past tense is だった.

Blue: But you only use these verbs when comparing nouns to other nouns.

Blue: Talking about adjectives in the past tense has different rules.

Yellow: So I could say “breakfast was bread”?

Blue: 朝ご飯はパンでした

Yellow: But I can’t say “breakfast was tasty”?

Blue: I’m trying to build suspense by leaving that lesson for later.

Yellow: It’s not working.