CG1103 2011/2012 Semester 2 - Individual Lab 2

for Week 5, January 2012

Introduction

The purpose of this lab is to introduce the concepts of inheritence, header files and the use of vectors.

In general, you should use the standard C++ iostream  using cin for input and cout for output in your programs, unless otherwise stated.

Unlike lab 1, this lab should not be submitted to CourseMarker. Instead your tutors will look at your work and grade you during the lab session itself. You should submit a word document with a 1 page write-up detailing your idea. In addition, copy paste ONLY your source code containing your AI to the document and submit this file to IVLE workbin.

If you have any questions, you may post your queries in the IVLE forum. Remember to put "Ilab2" somewhere in the subject line of your forum message.

The deadline for completing the lab is 16 February.


Pokemon Arena!

While the length of this writeup can be quite intimidating, the actual length of your code may only be 70 lines (depending on how intelligent your AI is). You can skip some of the overview writeup if you are familiar with the game. The article is written with the assumption that the reader has not played the game before.

The concept of the Pokémon universe, in both the video games and the general fictional world of Pokémon, stems from the hobby of insect collecting, a popular pastime which Pokémon executive director Satoshi Tajiri-Oniwa enjoyed as a child.[8] Players of the games are designated as Pokémon Trainers, and the two general goals (in most Pokémon games) for such Trainers are: to complete the Pokédex by collecting all of the available Pokémon species found in the fictional region where that game takes place; and to train a team of powerful Pokémon from those they have caught to compete against teams owned by other Trainers, and eventually become the strongest Trainer, the Pokémon Master. These themes of collecting, training, and battling are present in almost every version of the Pokémon franchise, including the video games, the anime and manga series, and the Pokémon Trading Card Game. (wikipedia)

Task

In this individual assignment, your task is to improve the game AI by implementing a simple Artificial Intelligence that can defeat the (provided) Stupid AI. Your AI should not accept any input from the user - but make smart decisions depending on the state of the game. You should download the fully completed game here.

You are highly encouraged to ask for ideas / clarify any doubts you have on the forum. You may post code that provide hints on how to start (e.g. iterating through all the player's Pokemons) but you may not post an obvious solution to the problem.


Gameplay overview

The gameplay itself of the actual game is very similar to this text-based game we are writing (All Pokemon statistics, damage formula are taken from the Pokemon official database). For simplicity (and fairness), we ignore the concept where a Pokemon can "level up" and improve its attributes. All our Pokemon start at level 50 and both players start with exactly the same pokemons with same attributes. Students who are familiar with the game play, or can learn by understanding code should jump to the section "Artificial Intelligence" below.

Beginning of the game

The genre of the game is a turned based "Role Playing Game". Each player starts with the same set of pre-determined pokemon. The game is a strategy game which pits the player's Pokemon against the opponent's Pokemon. The battle starts with each player choosing a Pokemon at the same time (with each being unaware of each other's selection until starting). The battle then proceeds with several rounds, with each player taking a turn until all their Pokemon's have been defeated. (No Pokemons are ever harmed - they only become unconscious when they they are defeated). Once a player has all their Pokemons defeated, he/she lose the game.

Turn based combat

In every turn, both the players(or AI in our case) would select an action/move without knowing in advance what move the other would make. The moves a player may select is dependent on the "chosen" pokemon (which the player may select at the beginning of the battle). In general, a player may use any moves available to the chosen pokemon as long as the moves have not been exhausted yet. In addition, a player may change to a different pokemon that is still conscious.

In general, the attack moves are executed in order of the Pokemon's speed statistic. However when defending, the defending pokemon will go first and when changing, the changing player will go last. Note that to prevent stalemate situations from happening (where both players keep changing their pokemons), each player is allowed to change their Pokemon THREE times. You do not have to keep track of this - this move becomes unavailable once the player has exceeded the number of times he may change a pokemon

Once a Pokemon has been knocked unconscious, the next round will begin with the first available pokemon. This will resume until all a player's pokemon have been defeated.

Pokemon types

In our game, each Pokemon MUST be one of three different types - GRASS, FIRE, WATER. The type of a Pokemon would influence the moves it can make (e.g. WATER pokemon gets WATER type moves - we will discuss move types in the next section). In addition, a Pokemon type affects its weakness to certain move types - since the move type of a Pokemon is dependent on its type, we can determine when a Pokemon is weak to another Pokemon by directly looking at both their type.

It therefore makes sense to select a correct Pokemon to counter an opponent's Pokemon.

Pokemon Moves

As mentioned earlier, each Pokemon has an array of moves it can make. The moves available to a Pokemon is determined by the Pokemon type. In our game, each of our Pokemon has four possible moves - a physical move (no damage bonus regardless of defending pokemon type), two elemental moves corresponding to the Pokemon type (Water Pokemon gets two Water type abilities) and a defense type move. As mentioned earlier, if an elemental move is made against a defending pokemon which is weak against that element, it will be more effective and deal twice damage (E.g. Charmander uses EMBER on Bulbasaur. It is super effective!). Defending doubles the Pokemon's defense for that round.

Every move is limited by the number of times it can be used per battle. In general, the more powerful a move is, the less times it can be used. In this aspect, our game differ from the real Pokemon game as we reduce the number of available moves. Every move also has a power rating that affects how powerful an attack will be.

Pokemon statistics and moves

NameBulbasaurCharmanderSquirtle
TypeGrassFireWater
HP128123127
Attack798278
Defense797395
Speed759473
Move 1Tackle (NON)Scratch (NON)Tackle (NON)
Move 2Vinewhip (GRASS)Ember (FIRE)Bubble (WATER)
Move 3Razorleaf (GRASS)Flamethrower (FIRE)Watergun (WATER)
Move 4DefendDefendDefend
DescriptionFor some time after its birth, it grows by gaining nourishment from the seed on its back.The fire on the tip of its tail is a measure of its life. If healthy, its tail burn intensely.It shelters itself in its shell, then strikes back with sprouts of water at every opportunity.


C++ Classes

Pokemon

We represent a Pokemon by using a class called Pokemon (surprise, surprise). We only list the functions which are useful to you:

FunctionReturn typeDescription
getAttack()intGets the attack stat of the Pokemon
getDefense()intGets the defense stat of the Pokemon
getHp()intGets the hp of the Pokemon
getSpeed()intGets the speed stat of the Pokemon
getType()intGets the type of the Pokemon. Possible types are Pokemon::FIRE, Pokemon::WATER, Pokemon::GRASS
isWeak(Pokemon)boolReturns true if current Pokemon is weak against the target Pokemon type
isWeak(Move)boolReturns true if current Pokemon is weak against the target Move type
isAlive()boolReturns true if current Pokemon is conscious (i.e. hp > 0)

Move

We represent the actions a player can make using this class. The actions a player can make includes the options to change pokemon, as well as the abilities of the selected pokemon. We only list the functions which are useful to you:

FunctionReturn typeDescription
getPower()intGets the power stat of the ability
getNumLeft()intGets the num of remaining times this ability can be used
getElement()enum ElementGets the Element of this move. Possible values are Move::NON, Move::Change, Move::FIRE, Move::Water, Move::GRASS
getIndex()intNote: Only used if the element of this move is CHANGE. This returns the index position of the player's pokemon to change to.
use()voidDecreases the number of times this ability can be used by 1.
Player

We represent each player by using this class. This class stores a list of the player's pokemon as well as their names. We only list the functions which are useful to you:

FunctionReturn typeDescription
getPokemon(int)Pokemon&Returns a reference to a Pokemon at specified index.
countLivePokemons()intGets the total number of conscious pokemons.
getMoves()vector<Move>Gets a vector of possible moves a player may make (including changing Pokemon, and the Pokemon's ability) for this turn

Artificial Intelligence

Students who are familiar with the game may skip most of the above section. Your main task starts from this point. The game works by using a pair of AI to determine the logic each player would make.

Our AI implementation MUST inherit from the class AIBase which contains the following pure virtual functions:

The student is provided with TWO AI implementations - AIStupid and AIPlayer. Your task is to write an AI<YOURNAME> (YOURNAME is replaced by yourname) that is smart enough to defeat AIStupid. AIStupid is a rather stupid AI that does not know how to change Pokemon and uses the worst ability each turn (so practically any other AI would be able to defeat it). AIPlayer is not a true AI - instead this AI lists available options the player can make and allows a human to decide a move to make. You should make a single modification to Main.cpp to use your AI as follows:

int main()
{
	srand(time(NULL));
	Player p1("Player 1"), p2("Player 2");
	initPlayers(p1, p2);
	AIBase *p1AI = new AIPlayer;    // <---- Change this to the AI class you wrote
	AIBase *p2AI = new AIStupid;
	
	.... //remaining code not shown

Max would like to point out that the parameters to each of the above function is a copy of the actual object. Any attempt to "cheat" by modifying the Player's attributes (e.g. adding more pokemons) would not work, since they are only modifying the local copy!


Tips

Pokemon FIGHT!

It's not so much fun to defeat the StupidAI. On the week of 12th Feburary 2012 during your scheduled lab session bring a thumb drive containing only your AI implementation (or upload somewhere accessible). You will pit YOUR AI against your friend's AI. Each pair will get ONLY one round. The loser is eliminated and the winner will continue to battle the other winners. There can only be one champion!

Prizes

There's not much fun without prizes! For each group:

First Prize: 1 BONUS POINT to your CA mark (in addition to the 1 mark for this lab) + $20 COOP Voucher

2nd - 5th? Prize: 1 BONUS POINT to your CA mark. The number of students receiving this prize is uncertain - all students who have progressed to round 3 automatically qualifies for this prize.

All students participating will automatically receive 1 mark credit for this lab (if they have coded a reasonably decent AI)