Tuesday, May 11, 2010

Linear Algebra: Basics

Today with my math teacher I went over some of the basics of linear algebra. The two topics I went over included solving for the intersection of two lines in 3D space, and finding the angle between two vectors. The rest of the mathematical topics I'll try to cover in the near future include: finding a vector orthogonal to two other vectors in 3D space; finding the time T during the intersection of ray between a circle of sphere; using a matrix to rotate a vector by an arbitrary angle. I found these topics, as well as an entire survival guide for DigiPen students, at this site here. Hopefully by explaining the math I went over today I can solidify my own understanding.

First off: solving for the intersection of two lines in 3D space. I know how to do this in matrix form, as it is easiest and simplest in matrix form. Here is a matrix of the x y and z coordinates for a point in 3D space: [x, y, z]. An equation for a vector in 3D space consists of a point on a line, and the direction vector of a line multiplied by a magnitude. This magnitude represents the length of the line, whereas the timestep, or t, represents a constant.

Here is an equation for a line in 3D space: L1 = [2, 4, -1] + t[-1, 2, 3]. I just chose these numbers at random because they really don't matter. The first matrix is a point on the line. The second matrix is the rise, run, and the z equivalent to rise or run (just like two dimensional lines). You need a point on the line, otherwise the direction vector (rise//run//zrun) could sit anywhere in space. Without the direction vector for your line, you line could be facing in any direction as long as it sits on your point. The t is the magnitude of the direction vector, and these could be used as something to define the distance something traveled over time of t. t is just a constant.

In order to solve for the intersection of two lines, I'll quickly show the process with some variables. Here are the two lines: L1 = [a, b, c] + t[d, e, f]; L2 = [g, h, i] + r[j, k, l]. Now since these two equations each represent a line, the point of intersection is going to be a point that can be used to satisfy either of the equations. You just set both of the equations equal to each other, one variable at a time (x, y and z) and solve for each one. To solve for the x coordinate of the intersection you would use a + td = g + rj. You do this for variable a through c corresponding to d through f. Then using substitution, if need be, you can solve for t and then solve for the rest of the variables, thus getting a final matrix of [x, y, z].

The second thing I learned today was finding the angle between two vectors. Luckily, you only need the direction vectors of the line equations. This makes sense because no matter where the lines are in space, they will have the same angle of intersection as long as the direction of the lines face in stays constant. To do this, you use the equation of:


Theta, the zero thingy on the left, is the angle you are solving for. a and b both represent matrices that represent direction vectors, like the direction vectors in the line equations earlier in this post. Arccos is cos^-1. The a and b on the top half of the right side of the equation is pronounced as a dot b. The dot is the operator for the dot product. The dot product is used to find the scalar projection of a onto b, and vise versa. I honestly don't fully understand what exactly the dot product does yet (read last paragraph, I understand it now), but for now I just need it for equations like this one, and it returns a scalar value. To use the dot product on two 1x3 matrices, you would do this: [a, b, c] dot [d, e, f] = ((a x d) + (b x e) + (c x f). The |a| represents the magnitude of a, which is the length of a. If the direction vector of a line is representing velocity vectors, then the magnitude of a would be the speed of the direction vector. To find the magnitude of a 1x3 matrix you do this: |M| = |[a, b, c]| = sqrt(a^(2) + b^(2) + c^(2)). Does that look familiar? It should; it's basically the Pythagorean Theorem in 3D. It takes the rise, run, and zrun and converts the three into a length value, just like the Pythagorean Theorem does with two lines, except this is with three.


Now once you find a dot b, and magnitude of a times magnitude of b, you then divide a dot by magnitude of a times magnitude of b, then arccos that value which results in your angle!


Dot product explained: Okay! I so I did a bit of research and asked a couple people some questions and now I understand what the value returned by the dot product does. It projects a vector onto another vector and returns the length. A dot B also equals B dot A, which makes sense because multiplication itself is commutative, and the formula for the dot product is just multiplication of three values. Here is a picture to help visualize this:



The blue line would be the dot product of A and B. This is very useful for collision in programming, and transforming vectors from one grid space to another. Here is a good example of using the dot product for 2D collision detection of convex polygons:




The red and blue are both one dimensional projections of the objects onto a line. The dotted line is perpendicular one side length of one of the objects. In the diagram is looks like it is perpendicular to both, which is fine, but it is important to understand that the dotted line is normal to one of the sides of one of the polygons. Once you find a dotted line that is perpendicular to a side of one of the shapes, you use the dot product on a two dimensional matrix and project both of the shapes onto the normal to the dotted line. You can then compare the two projections to see if they overlap. If the two projections overlap, you then try the entire process over for a different side of one of the polygons. Once you try this algorithm over each of the sides of each object and no collision vector was detected (a collision vector would be the length of overlap formed by overlapping projections) in at least one of the iterations, then the two objects are not colliding with one another.


Sources:
http://www.mvps.org/directx/articles/math/dot/index.htm
http://en.wikipedia.org/wiki/Dot_product
http://www.gamedev.net/reference/programming/features/verletPhys/page2.asp

Monday, May 10, 2010

Game Design: Positive and Negative Feedback; Flow Control

 As I've said a few times in the past, I have been reading Rules of Play: Game Design Fundamentals. Lately I have also been applying what I've learned into judging StarCraft mapping contests, like this one, and weaving them into my own map like this one. I've decided to take some of the knowledge and tools I've gained and write a post here about them. First, I want to talk about positive and negative feedback back loops in two different contexts.


The first context I want to talk about them in, is in the study of cybernetics.
Cybernetics deals with the ways a system gauges its effect and makes necessary adjustments. The simplest cybernetic device consists of a sensor, a comparator, and an activator. The sensor provides feedback to the comparator, which determines whether the machine is deviating from its established norm. The comparator then provides guidance to the activator, which produces an output that affects the environment in some way. This fundamental process of output-feedback-adjust-ment is the basis of cybernetics.—Stephen Littlejohn, Theories of Human Communication

 As this quote explains, cybernetics is a study of how a system reacts and makes adjustments to the current state of the system. This should sound rather relevant to video games. This type of automated reaction is used all the time; have you ever played a game that automatically tiers to the user's level of skill? There are two primary types of adjustments that are made upon a system, these two are positive and negative feedback reactions, usually used within a loop.

For example, take a room with a thermostat and a heater. When this room's sensor, the thermostat, reads a certain temperature it can trigger the heater to react. This system can be rigged to perform a negative feedback reaction in which the heater heats the room when the temperature is less than or equal to a certain amount. Assuming the room naturally cools, the room's temperate will oscillate between a few degrees and stay that way, all the while the room's specific state is constantly changing. A positive feedback loop would be if the heater turns on when the temperate is equal to or greater than a specific temperature. In a positive feedback loop, the temperature of the room will spiral up and up once it hits a certain activation point. Both positive and negative feedback loops are essential tools to be used in game design.

Too often I see games designed in StarCraft maps that are too hard or too easy, or too hard or too easy once the player reaches a certain point. I also see games made in which the leader has no way of letting the other players catch up to him, because he has such a great advantage over the other players. I also see the losers in a game have no means of catching up to the leaders. What's the point of continuing play if the outcome of the match has already been determined in the middle of the game because the leading player has a tremendous advantage over the rest of the players? These types of design flaws can be controlled with positive and negative feedback loops. Usually positive feedback loops are harmful to a game's flow (flow will be explained more in depth soon), and should be switched out for negative feedback loops. If a leading player seems to be constantly destroying all the other players in an unfair way, create a negative feedback response in which the system (the game) reacts and hinders the leading player. Similarly, you can give advantages to the players in last place to encourage and help them catch up to the leaders.

A great example of a negative feedback response is in the game Super Mario Cart. In Super Mario Cart there are weapons you gain from running into question marked boxes with your cart. Once you hit one you obtain a random weapon. You have a much greater chance to obtain a powerful weapon when you are near last place in the race, and you have a much greater chance to obtain a weak weapon when you are in first place. This sort of automated reaction the system generates creates a much more compelling form of gameplay, in which all the racers are usually closely pitted against each other neck to neck until the very end of the race. This generates an exciting play in which the outcome of the overall match remains uncertain till the very end.

The second meaning of positive and negative feedback would be rewards and punshiments to a player. Simply put, rewards are great to use to encourage players to make certain choices, and punishments are used to deter certain behavior. There is also a third category known as negative feedback. Negative feedback is not necessarily a punishment, but is used to deter a player from making specific choices. For example say you do not want your game to be focused on fighting, although you want to have an occasional enemy in your game. It turns out that too many players are focusing on finding and fighting enemies rather than experiencing your game how you designed it to be experienced. You do not want to punish the player as to deter them from playing at all, so what you could do instead is implement a clever negative feedback mechanism. You might be thinking that you could just make enemies stronger and therefore make the player want to avoid them -this might just make finding and killing enemies an interesting challenge for the player. Instead you could give the player absolutely no reward for killing the enemy (no points or anything), you could also make enemy encounters not worth the risk (as in making the player restart the level if an enemy kills them, or have enemies be "thieves" where if they hit you you lose items). If your goal is to make enemies something the player wants to avoid, give the player a reason to avoid them. If you find that fighting these enemies is truly fun for the players, you could also switch your game to a fighting one; it's your design, you decide.
Flow; flow would be the fine balance between difficulty in a game and the player's skills. Skills do not just include physical coordination; skills also include knowledge of the game's workings, knowledge of the other player's skill level, physical coordination, intelligence level, and response time. There are more than likely many many more forms of skill which I did not mention, but these should give a general idea. The difficulty of the game is pretty self-explanatory. The flow channel of a game is a narrow isle where the difficulty of the game is perfectly balanced and matched to the skill level of the player. Here is a diagram of the flow channel graphed with challenge over skill level:





 As you can see, it can be hard to create a flow in gameplay for all different types of players. One way that game designers achieve balanced flow is to apply positive and/or negative feedback loops to a game's processes.


Here is an interesting excerpt from the book Rules of Play that talks about the design process for a game made by two designers:
In a wonderful essay published on Gamasutra.com, Jesse Schell and Joe Shochet of Disney Imagineering write about the process of designing Pirates of the Caribbean-Battle for the Buccaneer Gold, a game "ride" where a group of players stands on a motion-platform pirate ship surrounded by video projections. During the game, one player steers the ship while the other players operate a number of cannons, firing at monsters, forts, and enemy vessels. Pirates of the Caribbean is designed as a condensed five-minute experience, and it was essential that players feel properly challenged at every moment of the game.
In their design analysis, Schell and Shochet detail a number of design problems that had to be overcome in order to maximize player enjoyment. For example, during playtesting they identified as a problem the fact that the player steering the ship could take the ship to what they call "dull places," leading to a less engaging experience for all of the players. In the selected quotes below, Schell and Shochet outline some solutions to this problem:
Architectural Weenies: "Weenie" is a phrase coined by Walt Disney himself. It refers to the technique used on movie sets of guiding stage dogs by holding up part of a sausage… In the case of Pirates, [there are] three main "weenies," one for each island: a volcano, an enormous fort, and a plume of smoke coming from a burning town. No matter which way the boat is facing, at least one of these "weenies" is in view. Since the coolest action takes place at the islands, [we wanted] to guide the captains to go there.
Guide Ships: Since the short-term goal of the game is to fire on other pirate ships, captains strive to get near these ships so that their gunners can get a clear shot. Many of the ships in the Pirates world are "on their way" to the islands mentioned above. Many captains, in just trying to stay near these ships find that just as they have destroyed the ship, they have arrived at one of the islands, without even trying to get there.
Sneak attacks: What if the captain ignores the guide ships? Even if he heads toward one of the "weenies" it might mean as long as a minute during which the gunners have little to shoot at. For this reason, [we] created special "sneak attack" ships that "magically" appear behind the players' ship, and quickly pull up alongside, when no other boats are in range.
The Waterspout: This was [a] nickname for [a] "last ditch" forcefield that surrounds the game play area.If a captain tries to sail out of the main game play area and out to open sea, they hit the forcefield, and the ship is "magically" pointed back to where the action is. The few guests who see this don't even realize that anything unusual has happened. They are just pleased to have their boat going somewhere cool.
Schell and Shochet are thinking in very experiential terms, using clever techniques to subtly guide player action in meaningful directions. At the time of its release, Pirates was a very high-tech production, featuring real-time 3D graphics, physically engaging cannon-firing interfaces, and a large motion platform to simulate a pirate ship rocking on the waves. Often in these instances, a desire to "properly" simulate a coherent 3D space or "correctly" output logical behavior for computer-controlled characters overshadows the design of the actual play experience. But Schell and Shochet had no hesitation in making pirate ships "magically" appear to guide the player, or abandoning "realistic" physics to have the player's ship turn on a dime to facilitate navigation. As they put it,"By choosing to be less concerned with reality and more concerned with what was fun, we created an experience that…is easier to adapt to, quicker to learn, and is a better show." In game design, player experience should always trump so-called "realism."

Boredom and anxiety, as game design watchwords, are wonderful because they speak directly to player experience. As you shape and sculpt your players' pleasure, you are guiding them between the Scylla and Charybdis of anxiety and boredom.This task is made all the more difficult because, as we know, the experience of play can only be indirectly designed. How do you create a set of rules that maximizes the play of pleasure for your audience?

The designers of this game implement two negative feedback loops. Did you see them? Onewould be the sneak attack ships. These ships react to the players being all alone at seas, and then appear out of nowhere to create an exciting experience. The other would be the water spout; the water spout reacts to the players entering the boundaries of the map, then spins them in the correct direction, thus keeping the game in a specific state. The guideships and weenies would be more a form of positive feedback in which encourage the player to make specific decisions. The guideships encourage the players to travel to the key focul points of the game while the weenies create enticing visual scenes that players are likely to travel to. Both of these provide the players with a reward and a reason to take specific actions.

Wednesday, May 5, 2010

Mini RPG: Continued

I have been working on a StarCraft map for a week long contest at StarEdit.net, however, today I forgot to bring my flashdrive with me so I now have no access to my mapfile and cannot work on it. Since I am unable to work on that for most of today, I decided to work on this file since I can copy//paste the source from my older post :)


Today I added in some comments to my code for easier read, added in a tiny method for the character class to add inventory items to the inventory (which is just a single list within the character class), created an item class, and started on the function that handles battles.


Overall progress is going at a decent pace while working on this project, but, I am not spending much time on it currently due to the week long contest I had mentioned.


At the moment this file doesn't do anything new, but has new code within it.

Here is my current source file: http://www.mediafire.com/?ymwminmhige

Monday, April 26, 2010

Mini RPG: Just Started

I have started on my mini-RPG! As of now I have a field and character class. The field has three obstacles in it now, and the entire field is represented by the currentMap list shown at the beginning of the source code. A 1 is a wall, 0 is empty space, 2 is an obstacle (not walkable), and 3 is a newline character.


At the moment the obstacles are represented by one of five different characters, and each obstacle is assigned one of these characters during the instantiation (creation) of the game field's instance. This way, random characters are generated for the obstacles and stay that way the entire game.

For now the only things that this does are create a field and print it when you hit enter, and move the character around. In order to detect collision I created an isValidMove function. This function checks to see if the next move the player can take will be anything but a 0 or not, and returns True or False.


import random

currentMap = [
    [1, 1, 1, 1, 1, 3],
    [1, 0, 0, 0, 1, 3],
    [1, 2, 0, 0, 1, 3],
    [1, 0, 0, 0, 1, 3],
    [1, 0, 0, 2, 1, 3],
    [1, 0, 0, 0, 1, 3],
    [1, 0, 2, 0, 1, 3],
    [1, 0, 0, 0, 1, 3],
    [1, 1, 1, 1, 1, 3]
    ]


class gameField:
    def __init__(self, mapData=[0]):
        self.mapData = mapData
        self.string = ''
        self.blocks = []
        for i in range(len(self.mapData)):
            for j in range(len(self.mapData[i])):
                if self.mapData[i][j] == 2:
                    r = random.randrange(1, 5)
                    if r == 1:
                        self.blocks.append(' v ')
                    if r == 2:
                        self.blocks.append(' x ')
                    if r == 3:
                        self.blocks.append(' ^ ')
                    if r == 4:
                        self.blocks.append(' * ')
                    if r == 5:
                        self.blocks.append(' ~ ')

class character:
    def __init__(self, x=0, y=0, field=None):
        self.crds = [x, y]
        self.x = self.crds[0]
        self.y = self.crds[1]
        self.field = field

    def __str__(self):
        s = ''
        r = 0
        for i in range(len(self.field.mapData)):
            for j in range(len(self.field.mapData[i])):
                if self.field.mapData[i][j] == 4:
                    self.field.mapData[i][j] = 0
        self.field.mapData[self.y][self.x] = 4
        for i in range(len(self.field.mapData)):
            for j in range(len(self.field.mapData[i])):
                if self.field.mapData[i][j] == 0:
                    s += '   '
                elif self.field.mapData[i][j] == 1:
                    s += ' / '
                elif self.field.mapData[i][j] == 2:
                    r += 1
                    if r == 1:
                        s += self.field.blocks[0]
                    if r == 2:
                        s += self.field.blocks[1]
                    if r == 3:
                        s += self.field.blocks[2]
                elif self.field.mapData[i][j] == 3:
                    s += '\n'
                elif self.field.mapData[i][j] == 4:
                    s += ' O '
        self.field.string = s
        return self.field.string

    def isValidMove(self, move):
        if move == 'a':
            if self.field.mapData[self.y][self.x - 1] != 0:
                return False
        if move == 'a':
            if self.field.mapData[self.y][self.x - 1] == 0:
                return True
        if move == 'w':
            if self.field.mapData[self.y - 1][self.x] != 0:
                return False
        if move == 'w':
            if self.field.mapData[self.y - 1][self.x] == 0:
                return True
        if move == 's':
            if self.field.mapData[self.y + 1][self.x] != 0:
                return False
        if move == 's':
            if self.field.mapData[self.y + 1][self.x] == 0:
                return True
        if move == 'd':
            if self.field.mapData[self.y][self.x + 1] != 0:
                return False
        if move == 'd':
            if self.field.mapData[self.y][self.x + 1] == 0:
                return True

currentGameField = gameField(currentMap)
currentCharacter = character(3, 1, currentGameField)

while True:
    print(currentCharacter)
    char = raw_input()
    if char == 'a':
        if currentCharacter.isValidMove(char):
            currentCharacter.x -= 1
    if char == 'd':
        if currentCharacter.isValidMove(char):
            currentCharacter.x += 1
    if char == 'w':
        if currentCharacter.isValidMove(char):
            currentCharacter.y -= 1
    if char == 's':
        if currentCharacter.isValidMove(char):
            currentCharacter.y += 1


After that is complete, I'll add in an option to enter your inventory and have a chance of a random battle sequence after each step the player takes.

Hopefully in the future I will have support for having multiple rooms, doors to and from rooms, and a .txt loader that can load maps from a .txt file. We'll see how things go.

Here is an example of some output text:

 /  /  /  /  /
 /           /
 /  v        /
 /  O        /
 /        ^  /
 /           /
 /     v     /
 /           /
 /  /  /  /  /

d
 /  /  /  /  /
 /           /
 /  v        /
 /     O     /
 /        ^  /
 /           /
 /     v     /
 /           /
 /  /  /  /  /


The character is the O, and the / are walls, the rest are just impassable obstacles. I hit the d key, and moved the character a space right. 

Monday, April 19, 2010

Card Simulation: Complete

I have finished my Mau Mau card game!!


There are now two "unique" cards. Playing a seven makes the next player draw a card, and playing an Ace makes the next player lose a turn. The face up stack now sets itself as the deck and shuffles when the deck empties. If a player plays all their cards in their hand they win, and the program exits using sys.exit().

I may in the future add in support for multiple Ai players, but for now I shall not. I want to start on a new and more complicated project, and I don't feel that working on this much more will help me to learn much more.

Currently 333 lines of code.

Here is a link to the .exe file in case you want to play it:

http://www.mediafire.com/?jjymynjngdz

Here is a link to the .py source file:

http://www.mediafire.com/?jnzum2zdrdv

As for my next project, I want to make a very small fighting game. The game will be text based, and will feature a small map, a battle sequence, and random battle events while walking on the map. I also want to have a interactive map (e.g. open doors), as well as a very limited inventory for dealing out different attacks. All in all, I want to have about 3 enemies. Basically this project is a mini-RPG, without upgradeable stats or any storyline. The point of the project is just to solidify my general coding capabilities, along with furthering my use of OO.

Saturday, April 17, 2010

Card Simulation: Continued


Here is a code update for the day. I have to spend the rest of my day doing homework, so I don't know what progress will be made throughout the weekend. I may work on this more tomorrow.

Here is a link to the current build's source code.

As you can see, I have an Ai working to play against me. I currently don't have anything to have a player win the game, so there should be an exception thrown during one of the Ai's methods or during the makeMove method when either player has no cards in their hand.

The Ai works by creating a list of cards available to play, then randomly choosing one to play. If none of the cards in the Ai's are playable then it will draw a card from the deck. This reminds me, if the deck empties then there should be a thrown exception as well, as I haven't coded switching the stack with the deck when the deck is empty.

Since I created an Ai class, I should be able to instantiate multiple Ai instances with ease to allow for multiple Ai players to be playing simultaneously.

Once I work on this some more, I plan to handle the mentioned exceptions that should be thrown, as well as begin working on creating some unique cards. For now I like the "make next player skip their turn" and "wild card". The wild card would allow the player to switch the current suit to any suit desired.

Here is a .exe in case you wanted to play the game ^^
http://download510.mediafire.com/13dumzc1bodg/awtwokn2wmt/Cards1.7z

Thursday, April 15, 2010

Card Simulation

Lately I have been documenting my experience with creating a deck simulator here, which is being written with Python 2.5.6.


I plan to continue documenting my progress at the link above, as well as on this blog. I posted the above link so that anyone that would like to can see all previous posts I've made up to my current point of development, which will be explained throughout this post.


I have chosen to create a card game called MauMau. MauMau is a game very similar to Uno, the main difference being that MauMau is played with a traditional deck of cards.


I currently have created a card class, deck class, MauMau class, and hand class. I manipulate these within the main function, which is the game loop. I also have created a function for determining if a player move is a valid move.


My immediate plans for the game is to:


- Create the used stack pile.
- Allow players to make a move by playing a card onto the used stack pile.
- Create an Ai which plays available cards, and draws if unavailable.
- Create rules for unique cards, like lose a turn, etc.



Here is my current build:


"""
To do:
- Create the used stack pile.
- Allow players to make a move by playing a card onto the used stack pile.
- Create an Ai which plays available cards, and draws if unavailable.
- Create rules for unique cards, like lose a turn, etc.

Created by: CecilSunkure
"""

import sys
import random

ACES_HIGH = True
GAME_RUNNING = True

class card:
    suits = ["Clubs",
             "Diamonds",
             "Hearts",
             "Spades" ]
    ranks = ["Ace",
             "2",
             "3",
             "4",
             "5",
             "6",
             "7",
             "8",
             "9",
             "10",
             "Jack",
             "Queen",
             "King" ]

    def __init__(self, suit=0, rank=0):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return (self.ranks[self.rank] + " of " + self.suits[self.suit])

class deck:
    def __init__(self):
        self.cards = []
        for suit in range(4):
            for rank in range(12):
                self.cards.append(card(suit, rank))

    def __str__(self):
        s = ''
        for i in range(len(self.cards)):
            s = s + str(self.cards[i]) + '\n'
        return s
          

    def shuffle(self):
        import random
        cards_length = len(self.cards)
        for i in range(cards_length):
            j = random.randrange(i, cards_length)
            self.cards[i], self.cards[j] = self.cards[j], self.cards[i]

    def remove(self, card):
        if card in self.cards:
            self.cards.remove(card)
            return True
        else:
            return False

    def draw(self):
        return self.cards.pop()

    def is_empty(self):
        return (len(self.cards) == 0)

    def deal(self, hands, num_cards=999):
        for i in range(num_cards):
            if self.is_empty(): break
            card = self.pop()
            hand = hands[i % len(hands)]
            hand.add(card)

    def pop(self):
        return self.cards.pop()


class hand(deck):
    def __init__(self, player=''):
        self.cards = []
        self.player = player

    def add(self, card):
        self.cards.append(card)

    def __str__(self):
        s = self.player + "'s Hand"
        t = 0
        if self.is_empty():
            s = s + " is empty\n"
        else:
            s = s + " contains\n"
        for i in range(len(self.cards)):
            t += 1
            s = s + str(t) + '. ' + str(self.cards[i]) + '\n'
        return s

class MauMau:
    def __init__(self, stack=0, topCard=0):
        self.deck = deck()
        self.deck.shuffle()
        self.players = []
        self.stack = stack
        self.topCard = topCard

    def getName(self):
        print('Welcome to Mau Mau!')
        player = raw_input()
        print('What is your name?')
        player = raw_input()
        print('')
        return player

    def startCard(self):
        self.topCard = self.deck.pop()

    def cmp_topCard(self, other):
        if self.topCard.suit == other.suit:
            if self.topCard.rank == other.rank:
                return True

def isValidMove(move, hand, game, handlen):
    """Used to determine if a move by checking to see if the move is an integer, followed by and testing to see
    if the proposed move is within the length of the hand passed to this function. Finally, this function
    makes sure that the proposed card to be played is valid within the rules of the game (same rank)."""
    x = []
    for i in range(1, (handlen+2)):
        x.append(i)
  
    try:
        int(move)
    except:
        print('That is not a valid move (not int).\n')
        return False

    if int(move) not in x:
        print('That is not a valid move (not 1-' + str(handlen+1) + ').\n')
        return False

    if move != str(handlen+1):
        if game.topCard.rank == hand.cards[(int(move)-1)].rank:
            return True
        else:
            return False
    elif move == str(handlen+1):
        return True

def main():
    """This function is the main loop used for running the Class MauMau. The turns between Ai and human are
    represented by integers, and those integers are used in if statements to determine which player is currently
    taking their turn."""
    #turn = random.randrange(2) + 1 <-- A comment for now, so for testing the human always goes.
    turn = 0
    game = MauMau()
    name = game.getName()
    hand1 = hand(name)
    hand2 = hand("CPU")
    game.deck.deal([hand1], 5)
    game.deck.deal([hand2], 5)
    game.startCard()
  
    if turn == 1:
        print('The computer will go first, as decided at random.')
    else:
        print('You will move first, as decided at random.')
  
    while GAME_RUNNING:
        print ('///' + '\n' + '/// ' + str(game.topCard) + '\n' + '///' + '\n')
        print (hand1)

        if turn == 1:
            print ('The computer will now take its turn, hit enter to proceed.')
            Move = raw_input()
        else:
            print ('Choose a card to play (1-' + str(len(hand1.cards)) + ') or draw a card (' + str((len(hand1.cards)+1)) + ').')
            Move = raw_input()

            if isValidMove(Move, hand1, game, len(hand1.cards)):
                print('Valid move check passed.\n')

                if Move == str(len(hand1.cards)+1):
                    hand1.add(game.deck.draw())
            else:
                print('Valid move check failed.\n')
              

if __name__ == "__main__":
    main()


In order to use the stack of cards for the face up cards that were already played, I plan to implement a common stack. A stack would be a list or array that is used to grab values out of in the order of the last appended first. I created a test module (.py file) before actually using it in the game. I have yet to implement something similar, but the source for this test is here:

 #A test module for creating a stack.

run = True
stack = []

while run:
    print('Stack, Pop, end, or continue? (1, 2, 3, enter)')
    yesno = raw_input()

    if yesno == '1':
        print('Enter a value to stack')
        a = raw_input()
        stack.append(a)

    if yesno == '2':
        try:
            stack.pop()
            b = stack.pop()
            print(b)
        except:
            print('Stack is empty.\n')

    if yesno == '3':
        run = False


    
Development is moving at a decent pace. Most of the time I am debugging the code I have written, but I am learning a ton. I've become very much more familiar with object orientation through the use of all my classes, and this project is definitely helping to enhance my overall coding ability. It's really pretty exciting :)

Here is a link to a .exe of my current build: http://download503.mediafire.com/m5ydqyl9zzng/nyfzyamykzi/Cards.7z