Code Review for upcoming contest
Ok on the suggestion of Blackroot I am doing a Risk contest. I have everything completed, but before I post I wanted to get some feedback first on the player_interface. Basically, I want to make sure there aren't any other member functions you need to be able to easily create an AI for it? Other suggestion are fine as well.
Code:
#ifndef PLAYER_INTERACE_H
#define PLAYER_INTERACE_H
#include "helpers.h"
#include "player.h"
class PlayerInterface
{
friend class Player;
public:
//virtual methods must be overidden
virtual std::string getName()const =0;
// This is used by the framework to get the preferred name
// for your AI player. You should return a string container the name of your player.
// If you duplicate an existing name extra letters will be tacked onto your name
// to make it unique.
virtual void init()=0;
// This method is call after all players have been added and the
// players have been "shuffled" to start choosing countries.
// please note that the play order changes again, after all initial
// armies are place before play begin.
// You can use it for whatever initialization your player needs to do that can't
// be done in the constructor
virtual std::string chooseCountry()=0;
// This method is called when there are unclaimed countries available to claim
// You should return a string containing the name of the unclaimed country you wish
// claim. If you return an invalid name (spelling/case or already claimed) one will
// be chosen for you at random. For comparison purposes, it's recommend you use the
// country names as defined in helpers.h. There are several arrays, enums etc at your
// disposable.
virtual std::string placeArmy ()=0;
// This function is called in 2 circumstances
// 1st at the beginning after all countries have been claimed
// this function is called to place your remaining armies on
// countries you own
// 2nd This function is called at the beginning of your turn when you have new armies
// to place.
// Again, you should return a string containing the name of the country you wish to place the army
// One army is placed at a time. Invalid names will result in an army being randomly placed in
// a country you control
virtual std::vector<const Card> redeemCards()=0;
// This method is called if you are in possesion of cards that can be redeemed
// (Either a matched set - 3 like card, or an unmatched set - 3 unlike cards, or
// 2 cards and a wild card. If you wish to redeem your set, return a std::vector<const Card>
// to the framework with the 3 cards from your hand you wish to redeem. You are not
// required to redeem your cards unless you have 5 or more cards. If you do not wish to redeem
// just return an empty vector.
// If you return an invalid set, and you hold less than 5 cards, no action will be taken.
// If you hold 5 or more cards, a valid set will be chosen for you.
// Also not that the order the cards are entered into the vector is important:
// If the country on the card matches a country you control, you receive a bonus of 2 armies
// on that country (They will be placed automatically). You can only receive 1 bonus of 2
// armies per trade-in. Therefore, if more than one of your cards have countries that
// you control and you want the 2 armies to go on a particular country
// put that country first into your vector.
virtual Action getAction()=0;
// This method gets your actions for your turn. There is no set turn length as long
// as you have armies to attack with. Therefore you determine most of the time when
// your turn is over by submitting the apporpriate action. (See helpers.h for actions)
// Basically you complete an action struct with your action and submit it to the framework.
// If you submit an invalid action, it will be treated as an end of turn without fortification.
virtual int defendCountry(Action A)=0;
// When your are on the defending end of an attack, you have the choice
// of defending with 1 or 2 armies (1 or 2 dice) return your choice here.
// If you return a number greater than 2, or if you only have 1 army in the country
// and return 2 then 1 will be used.
virtual int captureCountry(Action A)=0;
// If you defeat all the armies in a country you must now claim that country
// by moving armies into it from the attacking country
// you must move minimum the same number that you attacked with and maximum 1 less
// than the number of armies you have in the attacking country.
// return the number you wish to move. An invalid number results in the minimum move.
virtual void notify(Action A)=0;
// After every action a notification is went to all of the players
// showing the results. Invalid submissions will have been corrected
// so that the actual results are shown here.
// This is information only, use as you see fit.
//non-virtual must NOT!!! be overidden
std::vector<std::string> getCountriesByPlayer(std::string owner_name);
// return a vector of the names of the countries controlled
// by owner_name
std::vector<std::string> getAdjacent(std::string country_name);
// returns a vector of the names of the countries touching/adjacent to country_name
// useful for deciding attacks/fortifications etc.
std::string me();
// Since the framework may change your player name to guarantee uniqueness
// use this function if you need to submit a function with your players name.
// ex: std::vector<std::string> myCountries = getCountriesByPlayer(me());
size_t getArmyCount(std::string country_name);
// returns the number of Armies in country_name
std::string getOwner(std::string country_name);
// returns the owner of countr_name
std::vector<std::string> getPlayers();
// return a vector of the names of the player and their current order
// orders is set twice, once before countries are chosen
// and once before play begins
private:
Player* mpPlayer;
// this is no concern to you and you should not try to use this, but since it's here
// This is a pointer to the real player class where most of the player info is stored
// The Player class also acts as a go between for the player_interface (this class)
// and the main game class. It handles all the validations so the game class only
// gets good inputs and doesn't have to do a lot of error checking
};
#endif
and helpers.h
Code:
#ifndef HELPERS_H
#define HELPERS_H
#include <string>
enum CARD_TYPE {INFANTRY, CAVALRY, ARTILLERY, WILD};
const std::string CONTINENTS[] = {"North America","Europe","Asia","Africa","Australia","South America"};
const std::string COUNTRY_NAMES[] = {"Alaska","Alberta","Central America","Eastern United States","Greenland","Northwest Territory","Ontario","Quebec","Western United States",
"Great Britain","Iceland","Northern Europe","Scandinavia","Southern Europe","Ukraine","Western Europe",
"Afghanistan","China","India","Irkutsk","Japan","Kamchatka","Middle East","Mongolia","Siam","Siberia","Ural","Yakutsk",
"Congo","East Africa","Egypt","Madagascar","North Africa","South Africa",
"Eastern Australia","Indonesia","New Guinea","Western Australia",
"Argentina","Brazil","Peru","Venezuela"};
enum COUNTRY_INDEX
{
Alaska, Alberta, Central_America, Eastern_United_States, Greenland, Northwest_Territory, Ontario, Quebec, Western_United_States,
Great_Britain, Iceland, Northern_Europe, Scandinavia, Southern_Europe, Ukraine, Western_Europe,
Afghanistan, China, India, Irkutsk, Japan, Kamchatka, Middle_East, Mongolia, Siam, Siberia, Ural, Yakutsk,
Congo, East_Africa, Egypt, Madagascar, North_Africa, South_Africa,
Eastern_Australia, Indonesia, New_Guinea, Western_Australia,
Argentina, Brazil, Peru, Venezuela, Wild, Bad_Index
};
const COUNTRY_INDEX NORTH_AMERICA[] = {Alaska, Alberta, Central_America, Eastern_United_States, Greenland, Northwest_Territory, Ontario, Quebec, Western_United_States};
const COUNTRY_INDEX EUROPE[] = {Great_Britain, Iceland, Northern_Europe, Scandinavia, Southern_Europe, Ukraine, Western_Europe};
const COUNTRY_INDEX ASIA[] = {Afghanistan, China, India, Irkutsk, Japan, Kamchatka, Middle_East, Mongolia, Siam, Siberia, Ural, Yakutsk};
const COUNTRY_INDEX AFRICA[] = {Congo, East_Africa, Egypt, Madagascar, North_Africa, South_Africa};
const COUNTRY_INDEX AUSTRALIA[] = {Eastern_Australia, Indonesia, New_Guinea, Western_Australia};
const COUNTRY_INDEX SOUTH_AMERICA[] = {Argentina, Brazil, Peru, Venezuela};
const size_t NORTH_AMERICA_SIZE = 9;
const size_t NORTH_AMERICA_AWARD = 5;
const size_t EUROPE_SIZE = 7;
const size_t EUROPE_AWARD = 5;
const size_t ASIA_SIZE = 12;
const size_t ASIA_AWARD = 7;
const size_t AFRICA_SIZE = 6;
const size_t AFRICA_AWARD = 3;
const size_t AUSTRALIA_SIZE = 4;
const size_t AUSTRALIA_AWARD = 2;
const size_t SOUTH_AMERICA_SIZE = 4;
const size_t SOUTH_AMERICA_AWARD = 2;
const size_t COUNTRIES_SIZE = 42;
struct Action
{
enum ACTION {ATTACK, FORTIFY, ENDTURN, CAPTURE, ADD, REMOVE, PLACEMENT};//
// ATTACK - attack ToCountry from FromCountry wint n number of armers. n = Armies with value of 1, 2 or 3
// FORTIFY - move n armies from FromCountry to ToCountry and ends turn.
// n = Armies with value 1 to AllInCountry-1
// ENDTURN - ends turn without fortifying position. Other values are ignored.
ACTION action;// one of three above
std::string FromCountry;
std::string ToCountry;
unsigned Armies; //1, 2 or 3 for attack, n-1 for fortify with n being number of armies
// in FromCountry
//RESULTS (to be filled in by framework, not player)
int AttackerLosses;
int DefenderLosses;
bool CountryCaptured;
std::string PlayerName;
std::string FromPlayerName;
std::string ToPlayerName;
};
//
struct Card
{
Card(CARD_TYPE t, COUNTRY_INDEX c):type(t),country(c){}
bool operator==(const Card& card)const{return this->type == card.type;}
bool operator!=(const Card& card)const{return !((*this) == card);}
bool operator< (const Card& card)const{return (int)type < (int)card.type;}
CARD_TYPE type;
COUNTRY_INDEX country;
};
//
COUNTRY_INDEX getCountryIndex(std::string Name);
//...removed for posting purposes... not relavent anyway
bool isAdjacent(std::string c1, std::string c2);
#endif