Wednesday, August 15, 2018

Shuffling Cards When You Are a Computer

The last time I programmed anything, programs started at the top of the Main function and proceeded to the bottom...if the Unix terminal was working.  In my life, I have written one program in this new-fangled graphics/mouse paradigm.  Uh, so it's time to change that.  I'm currently trying to write a Solitaire/Klondike/Patience program to figure things out.  First step:  I need to shuffle a deck of cards.

Even if you are a methodical, obsessive human, you probably do not shuffle cards like a computer.  When computers do things, they prefer to be told how to do them with repetitive but clear commands, with clear stopping and starting points (this is one definition of an algorithm).  How to shuffle cards (when human):  get the deck and divide it into two piles with about twenty-six cards, but you know, it doesn't matter a whole lot if they are uneven.  Interlace the two piles.  You will probably want to make that part look fancy and impressive.  They say to shuffle seven times for approximate randomness, but no one does that.  You can get away with two or three times, and then if someone is still giving you the stink-eye, you let them cut the deck.  Of course, if you are really good at this, you have learned to exactly cut the deck into even piles and interlace the cards one-at-a-time from each pile.  If you are that good, you are no longer allowed to play cards.  Strangely, you have to be a certain level of bad at it to stay in the game.

If you are a computer, you will shuffle cards a different way:

A.  Someone gives me a stack of cards called "Unshuffled Cards."

B.  I randomly select any one Unshuffled Card and move it to another stack, which I call. "Shuffled Cards."
C.   I continue to do this until there are no cards in Unshuffled Cards.

D.  I announce that I have a deck of shuffled cards:  Shuffled Cards.

This has the benefit that you get an entirely shuffled deck after only one go-round.  Also, notice that any card has an equal change to be in any place, so any shuffle order of the deck is equally possible.  (Vocabulary word:  a "permutation" of a deck of cards is an arrangement of the cards in a particular order.)

As a human on the other hand, no one is going to sit there while you move cards one at a time to shuffle the deck.  Also, no one is going to trust you to pick a random not-cheating card to place on the shuffled stack.  It is better for humans to take the slightly-less-random but faster and more impressive shuffling method.

The standard algorithm for shuffling is called the Fisher-Yates algorithm.  It uses the steps above, except it does not make a new stack for the shuffled cards.  To save memory, it just uses the end of the current stack to store the new stack of shuffled cards, like this:


If I have a stack of ten "cards," as in A, the computer will pick the first card (here it picked the six), and move it to the end.  Notice in B, the 6 is now at the end, and the 10 has been moved into 6's old location.  The computer will pick the next "card," from the underlined numbers.  They are slightly out of order now that the ten has been shoved in, but the computer does not care, and it does not affect each card's chance of being picked.  In B, the computer has picked the four to be the next card.  In C, the 4 has been moved to the end, and the computer is selecting the next card from the underlined ones.  Here it has picked the 8.  The 8 stays where it is, but it is no longer a candidate to be picked.  In D, it is not underlined.  So, the area of the list of numbers to be picked gets shorter and shorter while the area of shuffled numbers gets longer.  Eventually, the entire list of numbers is shuffled from back to front.

Let's talk C#.


I'm going to show you my C# implementation of the Fisher-Yates algorithm.  At the top of my file, I have the above stuff.  "UnityEngine" is what is called a namespace.  The "using UnityEngine;" line is important because it tells the compiler where to look for the Unity-specific commands I'm using.  It also tells the compiler that in the case of two functions having the same name, I prefer UnityEngine's version.  This latter thing actually causes a small issue here.  The UnityEngine namespace defines a command called Random.  Random can do a lot of things (click the link for a complete list), but it does not do what I want, which is to give me a random integer in a particular range (note that with extra math, it can be forced to work, but it is easier to avoid that).  So, here, on the line "private.System.Random.rnd = new System.Random();" I am telling the compiler to look in the System namespace to use that Random function instead of UnityEngine's.  I have to specify with "System[dot]" because I have told the computer that by default I am "using" UnityEngine's commands.

System's Random is a pseudo-random number generator.  It's main use it to take a number and give you another number in return.  The numbers are more-or-less uniformly distributed, but it always gives identical lists of numbers.  For example, a list might be "7, 5, 2, 2, 6, 8, 25."  If you start with a seven, you will always get the 5, the 2, another 2, etc, so the starting number is critical in getting the appearance of randomness.  You do not want to always start with a seven.  (Vocabulary:  the starting number is called a "seed.")  The "new" command, when it is activated, looks at the user's current date and time and uses that to seed the generator, so two users are unlikely-ish to encounter the exact same list of "random" numbers.  In the code below, the command "Next" is used, which gets the next number on the "random" list.


And there it is.  I'm storing the cards currently as an array of numbers 0-51.  That may change later as I figure out what to actually do with the numbers to turn them into visible cards...um...I'm working on it!  (It would not be hard to do, probably, except that no one has written a tutorial for "how to work in Unity if you are a relic from the age of dinosaurs.")

Thursday, August 2, 2018

Day Three: Unity Game Kits

 Well, I finally understand the concept of "asset flipping."  With Unity's 2D Game Kit, you too can make an absolutely terrible platformer in thirty minutes with no knowledge of coding.  You could probably make a quite bad one in two hours.  Compared to fast-food work, this is more profitable.  I did not realize it was this easy.

I did not learn anything from the 2D Game Kit.  The tutorial it includes only explains the interface.  It tells you, for example, how to paint platforms onto the void by clicking on the tileset tool to access pictures of platforms.  Note that this is not actually a "2D Game Kit."  It is ONLY for making terrible platformers.

Anyway, there is NO information on how to open the 2D Game Kit, so see below if you want to do it for some reason.  There is allegedly a sample game included, but I still haven't found it.  I wish I could because the screenshots show dialogue and menus, and I haven't been able to find any information about how to do anything except a free-form level yet.

What I did find that was extremely helpful is this video by Youtuber Brackeys:





LINK

With this, I was able to start making some controls to move my cube.  The first thing I did was to make a "Physic Material," which, strangely, is not misspelled.  This is applied to the floor so that you can turn the friction off.  The cube can then move smoothly over the floor.


Here is where the video leads:


The important part of this is the "FixedUpdate" function at the bottom, which happens a fixed number of times every second.  First, a force is being added to the cube every time the function is called.  The effect of this is to make the cube go forward faster and faster.  The "If" statements conditionally add a sideways force to the cube, if the player is pressing the "a" or "d" cubes.  (These are the traditional left and right keys for PC players, not the arrow keys for some reason.)

This is the code you will get from following the video, but Brackeys leaves you with homework.  There are two problems with this code.  The first one is huge, that it hard-codes many values, including the movement keys.  If this code were in your game, there would be no way for the player to choose an alternate control scheme.  If you wanted to add that functionality, you would have to spend hours checking every line of code and replacing all the "d" and "a" references.  Here is how I fixed this, which I cannot guarantee is correct:


I just added some variables to contain the desired values.  I added variables for the key bindings and for the values of the forces involved.  (The values are numbers, but they have an "f" at the end to specify they are floating point decimals, even though the values listed are integers.  Apparently, if the "f" is not there, this can cause errors sometimes.  Weird.)  Ideally, I would not specify that kbMoveRight IS definitely "KeyCode.D" here in the script but fetch that information from a player preferences file.  I don't have one of those yet, though.

The more subtle problem with the code, according to Brackeys, is that FixedUpdate is not constantly being called, so if the player is taping keys quickly, you might miss some of their key taps.  Here is what I did to try to fix that:



The function "Update" is called very fast, so I put some boolean flags in there which are set if the player is tapping a key.  Later, when fixedUpdate is called, it responds to those taps.  I think this is what Brackeys suggested, but he was talking very fast in that part of the video, so, again, I don't guarantee that this is completely correct code.

To sum up, I now have a featureless white floor on which there is a red cube which quickly speeds into the distance.  If you are quick, you can move it left or right before it falls into the void.  Nice.




 ...
 
How to open (in Windows) the 2D Game Kit from the Unity Store*
*Guaranteed to work until it doesn't.

1.  Open Unity, and start a new 2D project by clicking "new" and typing in a name.  Be sure to select 2D from the Template drop-down.

2.  Close the project and Unity.

3.  With a browser, go to the Unity Asset Store, go to the 2D Game Kit page, and "Add to My Assets" the 2D Game Kit.

4.  The button will change to "Open in Unity."  Click on that.  Windows will ask, so tell it to "Open With" Unity.

5.  The main Unity menu will open, but the asset will not open.  Open your previously saved project.  The project will now have a Window in the center of the screen that has the logo for the 2D Game Kit.  Click the "Update" or "Import" button on this window.  The button will change to a slowly-incrementing counter.  When this completes, Unity will ask if you want to Import a Complete Project.  Click yes and wait some more.  A box with a progress bar will pop up.

6.  Eventually, a menu with a file hierarchy will pop up.  Make sure every file is checked, and click "Import."  Watch the progress bar some more.  For me, this took > 15 minutes.

7.  Once that finishes, the menu bar will not yet contain the extras needed by the tutorial.  Close Unity.

8.  Reopen Unity.  Reopen the project.  There will still be nothing there, but now you can go to the Unity Learn page and follow the tutorial.

Design Document, v. 0.0.1

In order to get somewhere, you have to know where you are going, or something, so I'm making a design document.  This is also sometimes called a "Project Bible."  It is a list of all the features that are intended to be put in the game, stylistic guidelines, and a timeline.  It can include concept art and perhaps a demo as well.

This is my initial draft.

Codename:  Arkcraft*

Stats:  A game for any type of PC (initially), single player, offline, with a projected length of 20-40 hours.

Pitch:  In thirty weeks, planet earth will be destroyed via an asteroid.  Humanity united is working feverishly to build a colony ship that will roam the stars until a new home is found.  Carrying genetic databases and thousands of sleeping passengers, the ship will deploy an entire planets' worth of earth creatures before waking the colonists.  Your job is to collect as many genetic samples as possible and also to collect records of animal behavior.  At the new world, cloned animals will be mass produced, programmed with social and survival behaviors, and released to make a new ecosystem.

You play as a series of volunteers.  Each one is in a different area of the world collecting animals within the time limit.  "Collecting" will proceed as a turn-based battle similar to what goes on in the Pokemon games.  You will also play as a series of scientists that are observing animals.  All behaviors observed during these activities go in a knowledge database, and the ultimate player goal is to fill the database with multiple gene specimens for each animal and a list of a wide variety of observed behaviors.  Each play-through is limited to the thirty-week time limit where the volunteer collects animals in their home-country.  Afterwards, they get an epilogue about their ultimate fate.  Subsequent play-throughs happen with different player-characters in perhaps a different region, with knowledge collected preserved.

Story and Mechanics Details:

The first volunteer starts the game with a robot companion with which to do "battle."  It knows only a basic move, such as "Zap," and you are supposed to train it to emulate natural animal behavior by "battling" various creatures.  Storywise, you are trying to train a machine-learning AI to make an algorithm for seeding a cloned animal with a realistic consciousness.  Mechanics-wise, you will eventually be able to "battle" with AI versions of animals that know sortof appropriate moves based on real animals.  For example, you might battle with a Mouse, which knows how to Scratch and Bite.  Storywise, cloned animals can also be programmed with these behaviors.

Playing with Time:

If one of your volunteers unlocked the Mouse on week 13, your subsequent volunteers will have access to Mouse on week 13 as well, so volunteers will get more and more versatile.  Subsequent characters may live in "better-funded" parts of the world so that they get access to better starting tech to avoid always starting out completely helpless.  Subsequent volunteers can also unlock animals earlier.

Volunteer 1--starts in a large city where starter animals can be acquired, such as Mouse, Roach, Squirrel, Robin, etc.  It must be certain that the player will acquire a basic animal immediately.

Volunteer 2--can get something more interesting, such as Wallaby, or something

Meanwhile, Scientist 1--uses Volunteer one's animal, which is either male or female, and observes its breeding behavior with a lab animal.  Of course, scientists actually know a lot about this sort of thing in the real world, so the justification is that the behavior is simultaneously being recorded for use in cloned animals.

...

eventually

...

Volunteer n starts the game but instead of a usually play-through, Volunteer n gives the tech to a group that Opposes the Mission.  Antagonists start to appear and challenge the player to battles.

...

eventually

...

One of the volunteers is running a deep-sea submarine version of the mission.  Some are spelunking, mountain-climbing, and other extreme environments.

...

eventually

...

The player goes through some challenge missions, such as creating programs for extinct animals from scratch.  You can clone a Tasmanian wolf, but how should it act?  Battles will initally be silly, with messages such as, "Tasmanian wolf tries to attack but becomes confused by its teeth."

...

eventually
...

The player is happy with the percentage of the animals collected and the completeness of the behavior list and chooses to view the Epilogues for all volunteers, ending the game.

Design Goals:

I have played a few Pokemon-inspired games (amusingly, I haven't actually played Pokemon), and I want to try to address a few design flaws.  All of the computer versions I have played had a terrible interface, so one of the things I want to do is

A.  Make a Nice Interface.  Computers have mice, and menus exist.  Playing the game should not give finger cramps, and I do not want to try to pretend the player is using an original Nintendo.  Also,

B.  No Grinding.  Playing the game should not required utter, slavish devotion.  There should be no point at which the game says, "Okay, now do that exact thing over and over for the next twenty hours."  Also, nothing should be on a timer.  Not that it's a flaw per se, but this particular game will avoid

C.  Fantasy Biology (avoiding).  We are strictly Sci-fi Biology here, lol.  This game will be vaguely educational in the sense that it will have actual animals in their approximate actual locations.  Animals are cool!  As far as aesthetics, I am initially aiming for

D.  Slightly rounded and cartoonish style with high saturation.  I will be avoiding photo-realism and huge pixels equally.  The theme here is "life," so it should look clean and appealing.  I will avoid overly-taxing effects, such as individual grass strands that bend in the wind.  Of course, I can't actually ART, so I'm probably going to actually make every object a plain cube with a name on it and try to fix that later.

Timeline:

1.  Program a single battle with fixed opponents.

2.  Program a fixed environment with spawn points for battles.  Try to make the interface work.

3.  Expand the battle system to include a huge number of creatures, and order them by progressive difficulty.  Set up a way for me to organize a vast amount of creature data.  At this point, consider a way to make creatures moddable.

4.  Expand the environment system to include procedurally-generated environments.  Work on balancing every region.

5.  Set up the campaign, starting with an initial cut-scene or tutorial mission.  Arrange region-unlocks.

6.  Figure out how to make game art.

7.  Add random generation to volunteers.  They should have an appearance, perhaps a photo, perhaps a family photo, perhaps an inspiring saying.  Each one should have something happen to them in the end, such as making it on the colony ship or...not.


*This name was suggested by a friend of mine, and I find it amusingly cliche.

Shuffling Cards When You Are a Computer

The last time I programmed anything, programs started at the top of the Main function and proceeded to the bottom...if the Unix terminal was...