/Game.c
C | 1297 lines | 1140 code | 42 blank | 115 comment | 285 complexity | 5d0426bb8f134087804c216ecc28386a MD5 | raw file
- /*
- * Game.c
- * 1917 v2.0
- * Add to and change this file as you wish to implement the
- * interface functions in Game.h
- *
- * Created by Richard Buckland on 20/04/11.
- * Copyright 2011 Licensed under Creative Commons SA-BY-NC 3.0.
- * Copyright 2011 Licensed under Creative Commons SA-BY-NC 3.0.
- *
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <limits.h>
-
- #include "Game.h"
-
- #define NUM_DISCIPLINES 6
- #define NUM_VERTECIES 54
- #define NUM_EDGES 72
-
- //defines for rollDice
- #define NUM_VERTECIES_ARROUND_REGION 6
- #define CAMPUS 1
- #define GO8_CAMPUS 2
-
- #define GENERAL_RC 0
-
- // store in this struct all the things you might want to know about
- // the game so we can write the interface functions in the header.
- typedef int vertex;
- typedef int edge;
- typedef struct _region{
- int diceScore;
- int discipline;
- } region;
- typedef struct _board {
- vertex vertexes[11][11];
- edge edges[22][22];
- region regions[11][11];
- } board;
- typedef struct _board *Board;
- typedef struct _player {
- int students[NUM_DISCIPLINES];
- int IPs;
- int publications;
- int exchangeRate[NUM_DISCIPLINES][NUM_DISCIPLINES];
- int ARCs;
- int campuses;
- int GO8s;
- } player;
- typedef struct _game {
- Board gameBoard;
- player players[NUM_UNIS+1];
- int currentTurn;
- int mostARCs;
- int mostPublications;
- } game;
- typedef struct _edgeSpecifier{
- int x;
- int y;
- } edgeSpecifier;
- typedef struct _vertexSpecifier{
- int x;
- int y;
- } vertexSpecifier;
- typedef struct _regionSpecifier{
- int x;
- int y;
- } regionSpecifier;
- //static functions for initialisation
- static void initialisePlayer(Game g, int uni);
- static void initialiseBoard(Game g, int discipline[], int dice[]);
- //static functions for rollDice()
- static void convertMMoneyStudentsToTHD(Game g);
- static void convertMTVStudentsToTHD(Game g);
- static void distributeStudents (Game g, int diceScore);
- static int getTypeOfVertex(vertex input);
- static int getOwnerOfVertex(vertex input);
-
- //static functions for implementing the Board ADT;
- static Board createBoard(void);
- static void disposeBoard(Board gameBoard);
- static int isOnBoard(path pathToCheck);
- static void setVertex (Board b, vertexSpecifier vertexLocation,
- vertex vertexContents);
- static void setEdge (Board b, edgeSpecifier edgeLocation,
- edge edgeContents);
- static void setRegion (Board b, regionSpecifier regionSpecifier,
- region regionContents);
- static vertex getVertex (Board b, vertexSpecifier vertexLocation);
- static edge getEdge (Board b, edgeSpecifier edgeLocation);
- static region getRegion (Board b, regionSpecifier regionLocation);
- static edgeSpecifier getEdgeSpecifierFromPath (path edge);
- static vertexSpecifier getVertexSpecifierFromPath (path vertex);
- static edgeSpecifier getEdgeSpecifierFromIndex (int edgeIndex);
- static vertexSpecifier getVertexSpecifierFromIndex (int vertexIndex);
- static regionSpecifier getRegionSpecifierFromIndex (int regionIndex);
- static int isNextToRetrainingCenter(Board g,
- vertexSpecifier vertexLocation);
- static int getRetrainingCenterType (Board g,
- vertexSpecifier vertexLocation);
- static vertexSpecifier getSpecifierOfSpecialVertex(int specialLocation);
- static edgeSpecifier getSpecifierOfSpecialEdge(int SpecialLocation);
- static vertexSpecifier getVertexAdjacentToRegion (regionSpecifier input,
- int index);
- static vertexSpecifier getRightVertex(vertexSpecifier current,
- vertexSpecifier back);
- static vertexSpecifier getLeftVertex(vertexSpecifier current,
- vertexSpecifier back);
- static void getSurroundingVertecies(vertexSpecifier location,
- /*@out@*/vertexSpecifier output[3]);
- static void tracePath(vertexSpecifier current, vertexSpecifier back,
- path input, /*@null@*//*@out@*/ vertexSpecifier* p1,
- /*@null@*//*@out@*/ vertexSpecifier* p2);
- static int isVertex(int x, int y);
- static int isPointOnBoard(int row,int col);
- static int getArrayOfVertecies(/*@out@*/vertexSpecifier points[]);
- static int getArrayOfEdges(/*@out@*/ edgeSpecifier edges[]);
-
- //static Functions for isLegalAction
- static int isLegalToBuildCampus(Game g, path destination);
- static int isLegalToBuildGO8(Game g, path destination);
- static int isLegalToObtainArc(Game g, path destination);
- static int isLegalToStartSpinoff(Game g);
- static int isLegalToRetrainStudents(Game g, int disciplineFrom,
- int disciplineTo);
- static int isValidArcLocationForPlayer(Game g, path destination);
- static int isEdgeAdjacentToMyCampus(Game g, path destination);
- static int isEdgeAdjacentToMyEdge(Game g, path destination);
- static int isVertexAdjacentToCampus(Game g, path destination);
- static int isVertexAdjacentToMyArc(Game g, path destination);
- static int uniForCurrentPlayer(Game g);
- static int numGO8s(Game g);
- static int playerHasResources(Game g, int studentsNeeded[]);
- static int isLegalPath(path pathToCheck);
-
-
- /* **** Functions which change the game aka SETTERS **** */
- // make a new game, given the disciplines produced by each
- // region, and the value on the dice discs in each region.
- // note: each array must be NUM_REGIONS long
- // eg if you are using my sample game struct above this function
- // would need to set the field currentTurn to 0. (because the turn
- // number is 0 at the start of the game)
- Game newGame (int discipline[], int dice[]) {
- Game newGame;
- newGame = calloc(1, sizeof(*newGame));
- assert (newGame != NULL);
- //initialise the Game here
- initialisePlayer(newGame, UNI_A);
- initialisePlayer(newGame, UNI_B);
- initialisePlayer(newGame, UNI_C);
- //create a new Board
- newGame->gameBoard = createBoard();
- assert (newGame->gameBoard != NULL);
- initialiseBoard(newGame, discipline, dice);
- newGame->mostARCs = NO_ONE;
- newGame->mostPublications = NO_ONE;
- newGame->currentTurn = -1;
- return newGame;
- }
- static void initialisePlayer(Game g, int uni){
- int i, j; //annonymous loop counters;
- assert (g != NULL);
- g->players[uni].IPs = 0;
- g->players[uni].publications = 0;
- g->players[uni].ARCs = 2;
- g->players[uni].campuses = 2;
- g->players[uni].GO8s = 0;
-
- i=0;
- while (i<NUM_DISCIPLINES){
- g->players[uni].students [i]=0;
- i++;
- }
- //Set the default exchange rate. 3 becasue everyone starts on a
- //retraining center
- i=0;
- while (i<NUM_DISCIPLINES) {
- j=0;
- while (j<NUM_DISCIPLINES) {
- g->players[uni].exchangeRate[i][j] = 3;
- j++;
- }
- i++;
- }
- //set the exchange rate for STUDENT_THD to INT_MIN as the only sane
- //value
- i = 0;
- while (i< NUM_DISCIPLINES){
- g->players[uni].exchangeRate[0][STUDENT_THD] = INT_MAX;
- i++;
- }
- i = 0;
- while (i< NUM_DISCIPLINES){
- g->players[uni].exchangeRate[i][i] = 1;
- i++;
- }
- }
- static void initialiseBoard(Game g, int discipline[], int dice[]){
- edgeSpecifier edgeLocation;
- vertexSpecifier vertexLocation;
- regionSpecifier regionLocation;
- region regionContents;
- int i;
- assert (g != NULL);
- assert (g->gameBoard != NULL);
- i = 0;
- //initialise the board to blank
- while (i < NUM_VERTECIES){
- vertexLocation = getVertexSpecifierFromIndex (i);
- setVertex (g->gameBoard, vertexLocation, VACANT_VERTEX);
- i++;
- }
- i=0;
- while (i < NUM_EDGES){
- edgeLocation = getEdgeSpecifierFromIndex (i);
- setEdge (g->gameBoard, edgeLocation, VACANT_ARC);
- i++;
- };
- i=0;
- while (i < NUM_REGIONS){
- regionContents.diceScore = dice[i];
- regionContents.discipline = discipline[i];
- regionLocation = getRegionSpecifierFromIndex (i);
- setRegion (g->gameBoard, regionLocation, regionContents);
- i++;
- }
- /*----- Setup Default Campuses -----*/
- vertexLocation = getSpecifierOfSpecialVertex(0);
- setVertex (g->gameBoard, vertexLocation, CAMPUS_A);
- vertexLocation = getSpecifierOfSpecialVertex(3);
- setVertex (g->gameBoard, vertexLocation, CAMPUS_A);
- vertexLocation = getSpecifierOfSpecialVertex(1);
- setVertex (g->gameBoard, vertexLocation, CAMPUS_B);
- vertexLocation = getSpecifierOfSpecialVertex(4);
- setVertex (g->gameBoard, vertexLocation, CAMPUS_B);
- vertexLocation = getSpecifierOfSpecialVertex(2);
- setVertex (g->gameBoard, vertexLocation, CAMPUS_C);
- vertexLocation = getSpecifierOfSpecialVertex(5);
- setVertex (g->gameBoard, vertexLocation, CAMPUS_C);
-
- /*----- Setup Default ARCs -----*/
- edgeLocation = getSpecifierOfSpecialEdge(0);
- setEdge (g->gameBoard, edgeLocation, ARC_A);
- edgeLocation = getSpecifierOfSpecialEdge(3);
- setEdge (g->gameBoard, edgeLocation, ARC_A);
- edgeLocation = getSpecifierOfSpecialEdge(1);
- setEdge (g->gameBoard, edgeLocation, ARC_B);
- edgeLocation = getSpecifierOfSpecialEdge(4);
- setEdge (g->gameBoard, edgeLocation, ARC_B);
- edgeLocation = getSpecifierOfSpecialEdge(2);
- setEdge (g->gameBoard, edgeLocation, ARC_C);
- edgeLocation = getSpecifierOfSpecialEdge(5);
- setEdge (g->gameBoard, edgeLocation, ARC_C);
- }
- // after the break we will talk about implementing this. for now
- // you can have it doing nothing
- void disposeGame (Game g) {
- assert (g != NULL);
- assert (g->gameBoard != NULL);
- disposeBoard(g->gameBoard);
- free (g);
- }
-
- // make the specified action for the current player and update the
- // game state accordingly.
- // The function may assume that the action requested is legal.
- void makeAction (Game g, action a){
- int currentPlayer;
- edgeSpecifier edgeLocation;
- vertexSpecifier vertexLocation;
- int retrainingCenterType;
- int i, j;
- assert (g != NULL);
- currentPlayer = getWhoseTurn(g);
- //executes action PASS
- if(a.actionCode == PASS) {
- //do nothing
- } else if(a.actionCode == BUILD_CAMPUS) {
- //modifies the contents of the vertex
- vertexLocation = getVertexSpecifierFromPath (a.destination);
- setVertex (g->gameBoard, vertexLocation, (vertex)currentPlayer);
- //gives the current player a campus
- g->players[currentPlayer].campuses++;
- //taking away the student costs for building a campus
- g->players[currentPlayer].students[STUDENT_BPS]--;
- g->players[currentPlayer].students[STUDENT_BQN]--;
- g->players[currentPlayer].students[STUDENT_MJ]--;
- g->players[currentPlayer].students[STUDENT_MTV]--;
- //Checks if the vertex is Adjacent a retraining Centre and if so
- //Changes the exchange rate appropriately
- if (isNextToRetrainingCenter(g->gameBoard, vertexLocation)){
- retrainingCenterType = getRetrainingCenterType (g->gameBoard, vertexLocation);
- if(retrainingCenterType == GENERAL_RC){
- i=1; //do not change the exchange rate for STUDENT_THD
- while(i<NUM_DISCIPLINES){
- j = 0;
- while(j<NUM_DISCIPLINES){
- if(g->players[currentPlayer].exchangeRate[i][j] > 3){
- g->players[currentPlayer].exchangeRate[i][j] = 3;
- }
- if(g->players[currentPlayer].exchangeRate[i][i] > 3){
- g->players[currentPlayer].exchangeRate[j][i] = 3;
- }
- if(g->players[currentPlayer].exchangeRate[i][i] > 3){
- g->players[currentPlayer].exchangeRate[i][j] = 3;
- }
- if(g->players[currentPlayer].exchangeRate[i][j] > 3){
- g->players[currentPlayer].exchangeRate[i][j] = 3;
- }
- if(g->players[currentPlayer].exchangeRate[i][j] > 3){
- g->players[currentPlayer].exchangeRate[i][j] = 3;
- }
- if(g->players[currentPlayer].exchangeRate[i][j] > 3){
- g->players[currentPlayer].exchangeRate[i][j] = 3;
- }
- j++;
- }
- i++;
- }
- } else {
- i=0;
- while(i<NUM_DISCIPLINES){
- g->players[currentPlayer].exchangeRate[retrainingCenterType][i] = 2;
- i ++;
- }
- }
- }
- } else if(a.actionCode == BUILD_GO8) {
- //updates the contents of the vertex (the player number and codes for GO8s are off by 3)
- vertexLocation = getVertexSpecifierFromPath (a.destination);
- setVertex (g->gameBoard, vertexLocation, (vertex)(currentPlayer+3));
- //gives the current player a GO8
- g->players[currentPlayer].GO8s++;
- g->players[currentPlayer].campuses--;
- //taking away the student costs for building a GO8
- g->players[currentPlayer].students[STUDENT_MJ] -= 2;
- g->players[currentPlayer].students[STUDENT_MMONEY] -= 3;
- } else if(a.actionCode == OBTAIN_ARC) {
- //modifies the contents of the edge
- edgeLocation = getEdgeSpecifierFromPath (a.destination);
- setEdge (g->gameBoard, edgeLocation, (edge)currentPlayer);
- //gives the current player an ARC
- g->players[currentPlayer].ARCs++;
- //taking away the student costs for building an ARC
- g->players[currentPlayer].students[STUDENT_BPS]--;
- g->players[currentPlayer].students[STUDENT_BQN]--;
- //checks if the current player has the most ARCs
- if (g->players[getMostARCs(g)].ARCs < g->players[currentPlayer].ARCs) {
- //if so then modifies the game struct to signify
- g->mostARCs = currentPlayer;
- }
- } else if(a.actionCode == OBTAIN_PUBLICATION) {
- //give the current player a publication
- g->players[currentPlayer].publications++;
- //takes away the student costs for a spinoff
- g->players[currentPlayer].students[STUDENT_MJ]--;
- g->players[currentPlayer].students[STUDENT_MTV]--;
- g->players[currentPlayer].students[STUDENT_MMONEY]--;
- //checks if the current player has the most publications
- if (g->players[getMostPublications(g)].publications < g->players[currentPlayer].publications){
- //if so then modifies the game struct to signify
- g->mostPublications = currentPlayer;
- }
- } else if(a.actionCode == OBTAIN_IP_PATENT) {
- //gives the current player a patent
- g->players[currentPlayer].IPs++;
- //takes away the student costs for a spinoff
- g->players[currentPlayer].students[STUDENT_MJ]--;
- g->players[currentPlayer].students[STUDENT_MTV]--;
- g->players[currentPlayer].students[STUDENT_MMONEY]--;
- } else if(a.actionCode == RETRAIN_STUDENTS) {
- //adds one student of the discipline that the player wanted
- g->players[currentPlayer].students[a.disciplineTo]++;
- //takes away a certain amount of students according to the player's exchange rate for that discipline
- g->players[currentPlayer].students[a.disciplineFrom] -= getExchangeRate (g, currentPlayer, a.disciplineFrom, a.disciplineTo);
- } else {
- assert(FALSE);
- }
- }
-
- // advance the game to the next turn,
- // assuming that the dice has just been rolled and produced diceScore
- // the game starts in turn -1 (we call this state "Terra Nullis") and
- // moves to turn 0 as soon as the first dice is thrown.
- void throwDice (Game g, int diceScore){
- assert (g != NULL);
- if (diceScore == 7){
- convertMMoneyStudentsToTHD(g);
- convertMTVStudentsToTHD(g);
- }
- distributeStudents(g, diceScore);
- g->currentTurn ++;
- }
-
- static void distributeStudents (Game g, int diceScore){
- vertexSpecifier locationOfVertexOfInterest;
- regionSpecifier locationOfRegionOfInterest;
- region regionOfInterest;
- vertex vertexOfInterest;
- int typeOfVertex;
- int studentType;
- int university;
- int i, j;
- assert (g != NULL);
- assert (g->gameBoard != NULL);
- i = 0;
- while (i < NUM_REGIONS){
- locationOfRegionOfInterest = getRegionSpecifierFromIndex (i);
- regionOfInterest = getRegion (g->gameBoard, locationOfRegionOfInterest);
- if(regionOfInterest.diceScore == diceScore){
- j = 0;
- while (j < NUM_VERTECIES_ARROUND_REGION){
- studentType = regionOfInterest.discipline;
- locationOfVertexOfInterest = getVertexAdjacentToRegion (locationOfRegionOfInterest, j);
- vertexOfInterest = getVertex (g->gameBoard, locationOfVertexOfInterest);
- typeOfVertex = getTypeOfVertex(vertexOfInterest);
- university = getOwnerOfVertex(vertexOfInterest);
- if (typeOfVertex == VACANT_VERTEX){
- //do nothing
- } else if (typeOfVertex == CAMPUS){
- g->players[university].students[studentType] += 1;
- } else if (typeOfVertex == GO8_CAMPUS){
- g->players[university].students[studentType] += 2;
- } else {
- assert(FALSE);
- }
- j++;
- }
- }
- i++;
- }
- }
- static int getTypeOfVertex(vertex input){
- int returnValue;
- if ((input == CAMPUS_A)||(input == CAMPUS_B)||(input == CAMPUS_C)){
- returnValue = CAMPUS;
- } else if ((input == GO8_A)||(input == GO8_B)||(input == GO8_C)){
- returnValue = GO8_CAMPUS;
- } else {
- returnValue = VACANT_VERTEX;
- }
- return returnValue;
- }
- static int getOwnerOfVertex(vertex input){
- int returnValue;
- if((input == CAMPUS_A)||(input == GO8_A)){
- returnValue = UNI_A;
- } else if((input == CAMPUS_B)||(input == GO8_B)){
- returnValue = UNI_B;
- } else if((input == CAMPUS_C)||(input == GO8_C)){
- returnValue = UNI_C;
- } else {
- returnValue = NO_ONE;
- }
-
- return returnValue;
- }
- static void convertMTVStudentsToTHD(Game g){
- int numOfMTVStudents;
- int university = UNI_A;
- assert (g != NULL);
-
- while (university < (UNI_A + NUM_UNIS)){
- numOfMTVStudents = g->players[university].students[STUDENT_MTV];
-
- g->players[university].students[STUDENT_THD] += numOfMTVStudents;
- g->players[university].students[STUDENT_MTV] = 0;
- university++;
- }
- }
- static void convertMMoneyStudentsToTHD(Game g){
- int numOfMMoneyStudents;
- int university = UNI_A;
- assert (g != NULL);
-
- while (university < UNI_A + NUM_UNIS){
- numOfMMoneyStudents = g->players[university].students[STUDENT_MMONEY];
-
- g->players[university].students[STUDENT_THD] += numOfMMoneyStudents;
- g->players[university].students[STUDENT_MMONEY] = 0;
- university++;
- }
- }
-
- /* **** Functions which GET data about the game aka GETTERS **** */
-
- // what type of students are produced by the specified region?
- // see discipline codes above
- int getDiscipline (Game g, int regionID){
- regionSpecifier regionLocation;
- region regionValue;
- assert (g != NULL);
- assert (g->gameBoard != NULL);
- regionLocation = getRegionSpecifierFromIndex(regionID);
- regionValue = getRegion (g->gameBoard, regionLocation);
- return regionValue.discipline;
- }
-
- // what dice value produces students in the specified region?
- // 2..12
- int getDiceValue (Game g, int regionID){
- regionSpecifier regionLocation;
- region regionValue;
- assert (g != NULL);
- assert (g->gameBoard != NULL);
- regionLocation = getRegionSpecifierFromIndex(regionID);
- regionValue = getRegion (g->gameBoard, regionLocation);
- return regionValue.diceScore;
- }
-
- // which university currently has the prestige award for the most ARCs?
- // this is NO_ONE until the first arc is purchased after the game
- // has started.
- int getMostARCs (Game g){
- assert(g != NULL);
- return g->mostARCs;
- }
-
- // which university currently has the prestige award for the most IP?
- // this is NO_ONE until the first IP is patented after the game
- // has started.
- int getMostPublications (Game g){
- assert (g != NULL);
- return g->mostPublications;
- }
-
- // return the current turn number of the game -1,0,1, ..
- int getTurnNumber (Game g) {
- assert (g != NULL);
- return g->currentTurn;
- }
-
- // return the id of the player whose turn it is 0,1 ..NUM_UNIS
- // the result of this function is undefined during Terra Nullis
- // don't call it until the game has started.
- int getWhoseTurn (Game g){
- int whoseTurn;
- assert(g != NULL);
- if (g->currentTurn < 0){
- whoseTurn = NO_ONE;
- } else {
- whoseTurn = (g->currentTurn % NUM_UNIS) + UNI_A;
- }
- return whoseTurn;
- }
-
- // return the contents of the given vertex (ie campus code or
- // VACENT_VERTEX)
- int getCampus(Game g, path pathToVertex){
- vertexSpecifier vertexLocation;
- vertex vertexContents;
- assert (g != NULL);
- assert (g->gameBoard != NULL);
- if (isOnBoard(pathToVertex)){
- vertexLocation = getVertexSpecifierFromPath (pathToVertex);
- vertexContents = getVertex (g->gameBoard, vertexLocation);
- } else {
- vertexContents = VACANT_VERTEX;
- }
- return (int) vertexContents;
- }
-
- // the contents of the given edge (ie ARC code or vacent ARC)
- int getARC(Game g, path pathToEdge){
- edgeSpecifier edgeLocation;
- edge edgeContents;
- assert (g != NULL);
- assert (g->gameBoard != NULL);
- if(isOnBoard(pathToEdge)){
- edgeLocation = getEdgeSpecifierFromPath (pathToEdge);
- edgeContents = getEdge (g->gameBoard, edgeLocation);
- } else {
- edgeContents = VACANT_ARC;
- }
- return (int) edgeContents;
- }
-
- // returns TRUE if it is legal for the current
- // player to make the specified move, FALSE otherwise.
- // legal means everything is legal eg when placing a campus consider
- // such things as:
- // * is the specified path a valid path?
- // * does it lead to a vacent vertex?
- // * under the rules of the game are they allowed to place a
- // campus at that vertex? (eg is it adjacent to one of their ARCs?)
- // * does the player have the 4 specific students required to pay for
- // that campus?
- // It is not legal to make any action during Terra Nullis ie
- // before the game has started.
- // It is not legal for a player to make the moves OBTAIN_PUBLICATION
- // or OBTAIN_IP_PATENT (they can make the move START_SPINOFF)
- int isLegalAction (Game g, action a){
- int returnValue;
- if (a.actionCode == PASS){
- returnValue = TRUE;
- } else if (a.actionCode == BUILD_CAMPUS){
- returnValue = isLegalToBuildCampus(g, a.destination);
- } else if (a.actionCode == BUILD_GO8){
- returnValue = isLegalToBuildGO8(g, a.destination);
- } else if (a.actionCode == OBTAIN_ARC){
- returnValue = isLegalToObtainArc(g, a.destination);
- } else if (a.actionCode == START_SPINOFF){
- returnValue = isLegalToStartSpinoff(g);
- } else if (a.actionCode == OBTAIN_PUBLICATION){
- returnValue = FALSE;
- } else if (a.actionCode == OBTAIN_IP_PATENT){
- returnValue = FALSE;
- } else if (a.actionCode == RETRAIN_STUDENTS){
- returnValue = isLegalToRetrainStudents(g, a.disciplineFrom,
- a.disciplineTo);
- } else {
- returnValue = FALSE;
- }
- return returnValue;
- }
- static int isLegalToBuildCampus(Game g, path destination){
- int returnValue = TRUE;
- int resourcesToBuildCampus[NUM_DISCIPLINES] = {0, 1, 1, 1, 1, 0};
- if(!(isLegalPath(destination))){
- returnValue = FALSE;
- } else {
- if(!((getCampus(g, destination) == VACANT_VERTEX))){
- returnValue = FALSE;
- }
- if(!(playerHasResources(g, resourcesToBuildCampus))){
- returnValue = FALSE;
- }
- if(!(isVertexAdjacentToMyArc(g, destination))){
- returnValue = FALSE;
- }
- if(isVertexAdjacentToCampus(g, destination)){
- returnValue = FALSE;
- }
- }
- return returnValue;
- }
- static int isLegalToBuildGO8(Game g, path destination){
- int returnValue = TRUE;
- int resourcesToBuildGO8[NUM_DISCIPLINES] = {0, 0, 0, 2, 0, 3};
- if(!isLegalPath(destination)){
- returnValue = FALSE;
- } else {
- if(!(getCampus(g, destination) == uniForCurrentPlayer(g))){
- returnValue = FALSE;
- }
- if(!playerHasResources(g, resourcesToBuildGO8)){
- returnValue = FALSE;
- }
- if(!(numGO8s(g) < 8)){
- returnValue = FALSE;
- }
- }
- return returnValue;
- }
- static int isLegalToObtainArc(Game g, path destination){
- int returnValue = TRUE;
- int resourcesToObtainARC[NUM_DISCIPLINES] = {0, 1, 1, 0, 0, 0};
- if(!isLegalPath(destination)){
- returnValue = FALSE;
- } else {
- if(!(getARC(g, destination) == VACANT_ARC)){
- returnValue = FALSE;
- }
- if(!playerHasResources(g, resourcesToObtainARC)){
- returnValue = FALSE;
- }
- if(!isValidArcLocationForPlayer(g, destination)){
- returnValue = FALSE;
- }
- }
- return returnValue;
- }
- static int isLegalToStartSpinoff(Game g){
- int returnValue = TRUE;
- int resourcesToStartSpinoff[NUM_DISCIPLINES] = {0, 0, 0, 1, 1, 1};
- if(!playerHasResources(g, resourcesToStartSpinoff)){
- returnValue = FALSE;
- }
- return returnValue;
- }
- static int isLegalToRetrainStudents(Game g, int disciplineFrom,
- int disciplineTo){
- int returnValue = TRUE;
- if (disciplineFrom == disciplineTo){
- returnValue = FALSE;
- }
- if (disciplineFrom == STUDENT_THD){
- returnValue = FALSE;
- }
- if (getStudents (g,getWhoseTurn(g), disciplineFrom) <
- getExchangeRate(g, getWhoseTurn(g), disciplineFrom, disciplineTo)){
- returnValue = FALSE;
- }
- return returnValue;
- }
- static int isValidArcLocationForPlayer(Game g, path destination){
- int returnValue = FALSE;
- if (isEdgeAdjacentToMyCampus(g, destination)){
- returnValue = TRUE;
- }
- if (isEdgeAdjacentToMyEdge(g, destination)){
- returnValue = TRUE;
- }
- return returnValue;
- }
- static int isEdgeAdjacentToMyCampus(Game g, path destination){
- path tempPath;
- int returnValue = FALSE;
- int player = getWhoseTurn(g);
- int myCampus = player;
- int length = (int) strlen (destination);
- strcpy (tempPath, destination);
- tempPath[length] = '\0';
- tempPath[length - 1] = 'B';
- if(getCampus(g, tempPath) == myCampus){
- returnValue = TRUE;
- }
- if(getCampus(g, destination) == myCampus){
- returnValue = TRUE;
- }
- return returnValue;
- }
- static int isEdgeAdjacentToMyEdge(Game g, path destination){
- printf("%s\n", destination);
- int returnValue = FALSE;
- path tempPath;
- int player = getWhoseTurn(g);
- int myARC = player;
- int length = (int)strlen (destination);
- strcpy (tempPath, destination);
- tempPath[length + 1] = '\0';
- tempPath[length] = 'R';
- if(getARC(g, tempPath) == myARC){
- returnValue = TRUE;
- }
- tempPath[length] = 'L';
- if(getARC(g, tempPath) == myARC){
- returnValue = TRUE;
- }
- tempPath[length] = 'B';
- tempPath[length + 2] = '\0';
- tempPath[length + 1] = 'R';
- if(getARC(g, tempPath) == myARC){
- returnValue = TRUE;
- }
- tempPath[length + 1] = 'L';
- if(getARC(g, tempPath) == myARC){
- returnValue = TRUE;
- }
- return returnValue;
- }
- static int isVertexAdjacentToCampus(Game g, path destination){
- int returnValue = FALSE;
- path tempPath;
- int length = (int)strlen (destination);
- strcpy (tempPath, destination);
- tempPath[length] = '\0';
- tempPath[length - 1] = 'R';
- if(getCampus(g, tempPath) != VACANT_VERTEX){
- returnValue = TRUE;
- }
- tempPath[length - 1] = 'L';
- if(getCampus(g, tempPath) != VACANT_VERTEX){
- returnValue = TRUE;
- }
- if(getCampus(g, tempPath) != VACANT_VERTEX){
- returnValue = TRUE;
- }
- return returnValue;
- }
- static int isVertexAdjacentToMyArc(Game g, path destination){
- int returnValue = FALSE;
- path tempPath;
- int player = getWhoseTurn(g);
- int myARC = player + 1;
- int length = (int)strlen (destination);
- strcpy (tempPath, destination);
- tempPath[length] = '\0';
- tempPath[length - 1] = 'R';
- if(getARC(g, tempPath) == myARC){
- returnValue = TRUE;
- }
- tempPath[length - 1] = 'L';
- if(getARC(g, tempPath) == myARC){
- returnValue = TRUE;
- }
- tempPath[length - 1] = 'B';
- if(getARC(g, tempPath) == myARC){
- returnValue = TRUE;
- }
- return returnValue;
- }
-
- static int uniForCurrentPlayer(Game g){
- return getWhoseTurn(g) +1;
- }
- static int numGO8s(Game g){
- int returnValue = 0;
- int i = 0;
- while (i < NUM_UNIS){
- returnValue += getGO8s (g, i);
- i++;
- }
- return returnValue;
- }
- static int playerHasResources(Game g, int studentsNeeded[]){
- int returnValue = TRUE;
- int discipline = 0;
- int player = getWhoseTurn(g);
- while (discipline < NUM_DISCIPLINES){
- if(getStudents (g, player, discipline) < studentsNeeded[discipline]){
- returnValue = FALSE;
- }
- discipline++;
- }
- return returnValue;
- }
- static int isLegalPath(path pathToCheck){
- int returnValue = TRUE;
- path tempPath;
- int lengthOfPath = (int)strlen (pathToCheck);
- strcpy (tempPath, pathToCheck);
- tempPath[lengthOfPath - 1] = '\0';
- if (lengthOfPath == 0){
- returnValue = TRUE;
- } else {
- returnValue = (isLegalPath(tempPath) && isOnBoard(pathToCheck));
- }
- return returnValue;
- }
- // --- get data about a specified player ---
-
- // return the number of KPI points the specified player currently has
- int getKPIpoints (Game g, int player){
- int KPIsDueToARCs;
- int KPIsDueToCampuses;
- int KPIsDueToGO8s;
- int KPIsDueToIPs;
- int KPIsDueToHavingMostARCs;
- int KPIsDueToHavingMostPublications;
- int KPIs;
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- KPIsDueToARCs = getARCs (g, player)*2;
- KPIsDueToCampuses = getCampuses (g, player)*10;
- KPIsDueToGO8s = getGO8s (g, player)*20;
- KPIsDueToIPs = getIPs (g, player)*10;
- if (getMostARCs(g) == player) {
- KPIsDueToHavingMostARCs = 10;
- } else {
- KPIsDueToHavingMostARCs = 0;
- }
- if (getMostPublications(g) == player) {
- KPIsDueToHavingMostPublications = 10;
- } else {
- KPIsDueToHavingMostPublications = 0;
- }
- KPIs = KPIsDueToARCs + KPIsDueToCampuses + KPIsDueToGO8s +
- KPIsDueToIPs + KPIsDueToHavingMostARCs +
- KPIsDueToHavingMostPublications;
- return KPIs;
- }
-
- // return the number of ARC grants the specified player currently has
- int getARCs (Game g, int player){
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- return g->players[player].ARCs;
- }
-
- // return the number of GO8 campuses the specified player currently has
- int getGO8s (Game g, int player){
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- return g->players[player].GO8s;
- }
-
- // return the number of normal Campuses the specified player currently has
- int getCampuses (Game g, int player){
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- return g->players[player].campuses;
- }
-
- // return the number of IP Patents the specified player currently has
- int getIPs (Game g, int player){
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- return g->players[player].IPs;
- }
-
- // return the number of Publications the specified player currently has
- int getPublications (Game g, int player){
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- return g->players[player].publications;
- }
-
- // return the number of students of the specified discipline type
- // the specified player currently has
- int getStudents (Game g, int player, int discipline){
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- return g->players[player].students[discipline];
- }
-
- // return how many students of discipline type disciplineFrom
- // the specified player would need to retrain in order to get one
- // student of discipline type disciplineTo. This will depend
- // on what retraining centers, if any, they have a campus at.
- int getExchangeRate (Game g, int player,
- int disciplineFrom, int disciplineTo){
- assert ((player > NO_ONE) && (player < UNI_C + 1) );
- assert (g != NULL);
- return g->players[player].exchangeRate[disciplineFrom][disciplineTo];
- }
-
- /* static helper functions that deal with the board */
- //static functions for dealing with the board;
- //static functions for implementing the Board ADT;
- static Board createBoard(void){
- Board newBoard;
- newBoard = calloc(1, sizeof(*newBoard));
- assert(newBoard != NULL);
- return newBoard;
- }
- static void disposeBoard(Board gameBoard){
- assert(gameBoard != NULL);
- free(gameBoard);
- }
- static int isOnBoard(path pathToCheck){
- vertexSpecifier endOfPathLocation;
- int c1, c2, c3, c4, c5, c6;
- endOfPathLocation = getVertexSpecifierFromPath(pathToCheck);
- c1 = (endOfPathLocation.y+2*endOfPathLocation.x)>= 7;
- c2 = (2*endOfPathLocation.y+endOfPathLocation.x)>= 7;
- c3 = (endOfPathLocation.y-endOfPathLocation.x) <= 8;
- c4 = (2*endOfPathLocation.y + endOfPathLocation.x) <= 23;
- c5 = (endOfPathLocation.y+2*endOfPathLocation.x) <= 23;
- c6 = (endOfPathLocation.x- endOfPathLocation.y) <= 8;
- return c1 && c2 && c3 && c4 && c5 && c6;
- }
- static vertex getVertex (Board b, vertexSpecifier vertexLocation){
- return b->vertexes[vertexLocation.x][vertexLocation.y];
- }
- static edge getEdge (Board b, edgeSpecifier edgeLocation){
- return b->edges[edgeLocation.x][edgeLocation.y];
- }
- static region getRegion (Board b, regionSpecifier regionLocation){
- return b->regions[regionLocation.x][regionLocation.y];
- }
-
- static void setVertex (Board b, vertexSpecifier vertexLocation,
- vertex vertexContents){
- b->vertexes[vertexLocation.x][vertexLocation.y] = vertexContents;
- }
- static void setEdge (Board b, edgeSpecifier edgeLocation,
- edge edgeContents){
- b->edges[edgeLocation.x][edgeLocation.y] = edgeContents;
- }
- static void setRegion (Board b, regionSpecifier regionLocation,
- region regionContents){
- b->regions[regionLocation.x][regionLocation.y] = regionContents;
- }
- static edgeSpecifier getEdgeSpecifierFromPath (path edgeLocation){
- vertexSpecifier startVertex = {2,10};
- vertexSpecifier startbackVertex = {1,11};
- vertexSpecifier p1, p2;
- edgeSpecifier returnValue;
- tracePath(startVertex, startbackVertex,edgeLocation, &p1, &p2);
- returnValue.x = p1.x+p2.x;
- returnValue.y = p1.y+p2.y;
- return returnValue;
- }
- static vertexSpecifier getVertexSpecifierFromPath (path vertexLocation){
- vertexSpecifier startVertex = {2,10};
- vertexSpecifier startbackVertex = {1,11};
- vertexSpecifier returnValue;
- tracePath(startVertex, startbackVertex,vertexLocation, &returnValue, NULL);
- return returnValue;
- }
- static int isPointOnBoard(int row,int col){
- return (((row+2*col)>= 7)&& ((2*row+col)>= 7) && ((row-col) <= 8) &&
- ((2*row + col) <= 23) && ((row+2*col) <= 23) && ((col- row) <= 8));
- }
- static edgeSpecifier getEdgeSpecifierFromIndex (int edgeIndex){
- edgeSpecifier edges[NUM_EDGES];
- (void)getArrayOfEdges(edges);
- return edges[edgeIndex];
- }
- static int getArrayOfEdges(edgeSpecifier edges[]){
- int i = 0;
- int row = 10;
- while(row>=0){
- int col=0;
- while( col<=10){
- if(isVertex(row, col) && isPointOnBoard(row, col)){
- if(isVertex(row, col+1) && isPointOnBoard(row, col+1)){
- edges[i].x = 2*col + 1;
- edges[i].y = 2*row;
- i++;
- }
- if(isVertex(row-1, col) && isPointOnBoard(row-1,col)){
- edges[i].x = 2*col;
- edges[i].y = 2*row-1;
- i++;
- }
- if(isVertex(row-1,col+1)&& isPointOnBoard(row-1, col+1)){
- edges[i].x = 2*col+1;
- edges[i].y = 2*row-1;
- i++;
- }
- }
- col++;
- }
- row --;
- }
- return i;
- }
- static vertexSpecifier getVertexSpecifierFromIndex (int vertexIndex){
- vertexSpecifier points[NUM_VERTECIES];
- (void) getArrayOfVertecies(points);
- return points[vertexIndex];
- }
- static int getArrayOfVertecies(vertexSpecifier points[]){
- int i = 0;
- int row = 10;
- while(row>=0){
- int col=0;
- while( col<=10){
- if(isVertex(row, col) && isPointOnBoard(row, col)){
- points[i].x = col;
- points[i].y = row;
- i++;
- }
- col++;
- }
- row --;
- }
- return i;
- }
- static regionSpecifier getRegionSpecifierFromIndex (int regionIndex){
- regionSpecifier regions[NUM_REGIONS];
- regions[0].x = 1;
- regions[0].y = 7;
- regions[1].x = 2;
- regions[1].y = 5;
- regions[2].x = 3;
- regions[2].y = 3;
- regions[3].x = 2;
- regions[3].y = 8;
- regions[4].x = 3;
- regions[4].y = 6;
- regions[5].x = 4;
- regions[5].y = 4;
- regions[6].x = 5;
- regions[6].y = 2;
- regions[7].x = 3;
- regions[7].y = 9;
- regions[8].x = 4;
- regions[8].y = 7;
- regions[9].x = 5;
- regions[9].y = 5;
- regions[10].x = 6;
- regions[10].y = 3;
- regions[11].x = 7;
- regions[11].y = 1;
- regions[12].x = 5;
- regions[12].y = 8;
- regions[13].x = 6;
- regions[13].y = 6;
- regions[14].x = 7;
- regions[14].y = 4;
- regions[15].x = 8;
- regions[15].y = 2;
- regions[16].x = 7;
- regions[16].y = 7;
- regions[17].x = 8;
- regions[17].y = 5;
- regions[18].x = 9;
- regions[18].y = 3;
- return regions[regionIndex];
- }
- static int isNextToRetrainingCenter(Board g, vertexSpecifier vertexNo){
- int returnValue = FALSE;
- int i;
- vertexSpecifier regionsThatAre[18];
- regionsThatAre[0].x = 1;
- regionsThatAre[0].y = 9;
- regionsThatAre[1].x = 2;
- regionsThatAre[1].y = 9;
- regionsThatAre[2].x = 4;
- regionsThatAre[2].y = 9;
- regionsThatAre[3].x = 5;
- regionsThatAre[3].y = 9;
- regionsThatAre[4].x = 0;
- regionsThatAre[4].y = 8;
- regionsThatAre[5].x = 0;
- regionsThatAre[5].y = 7;
- regionsThatAre[6].x = 7;
- regionsThatAre[6].y = 8;
- regionsThatAre[7].x = 8;
- regionsThatAre[7].y = 7;
- regionsThatAre[8].x = 1;
- regionsThatAre[8].y = 5;
- regionsThatAre[9].x = 2;
- regionsThatAre[9].y = 4;
- regionsThatAre[10].x = 9;
- regionsThatAre[10].y = 5;
- regionsThatAre[11].x = 8;
- regionsThatAre[11].y = 4;
- regionsThatAre[12].x = 4;
- regionsThatAre[12].y = 2;
- regionsThatAre[13].x = 5;
- regionsThatAre[13].y = 1;
- regionsThatAre[14].x = 9;
- regionsThatAre[14].y = 2;
- regionsThatAre[15].x = 9;
- regionsThatAre[15].y = 1;
- regionsThatAre[16].x = 7;
- regionsThatAre[16].y = 0;
- regionsThatAre[17].x = 8;
- regionsThatAre[17].y = 0;
- i = 0;
- while (i<18){
- if((vertexNo.x == regionsThatAre[i].x) &&
- (vertexNo.y == regionsThatAre[i].y)){
- returnValue = TRUE;
- }
- i++;
- }
- return returnValue;
- }
- static int getRetrainingCenterType(Board g, vertexSpecifier vertexNo){
- int retrainingCenters[11][11] = {{0}};
- int returnValue;
- retrainingCenters[1][9] = STUDENT_MTV;
- retrainingCenters[2][9] = STUDENT_MTV;
- retrainingCenters[4][9] = STUDENT_MMONEY;
- retrainingCenters[5][9] = STUDENT_MMONEY;
- retrainingCenters[0][8] = GENERAL_RC;
- retrainingCenters[0][7] = GENERAL_RC;
- retrainingCenters[7][8] = GENERAL_RC;
- retrainingCenters[8][7] = GENERAL_RC;
- retrainingCenters[1][5] = GENERAL_RC;
- retrainingCenters[2][4] = GENERAL_RC;
- retrainingCenters[9][5] = STUDENT_BQN;
- retrainingCenters[8][4] = STUDENT_BQN;
- retrainingCenters[4][2] = STUDENT_BPS;
- retrainingCenters[5][1] = STUDENT_BPS;
- retrainingCenters[9][2] = STUDENT_MJ;
- retrainingCenters[9][1] = STUDENT_MJ;
- retrainingCenters[7][0] = GENERAL_RC;
- retrainingCenters[8][0] = GENERAL_RC;
- returnValue = retrainingCenters[vertexNo.x][vertexNo.y];
- return returnValue;
- }
- static vertexSpecifier getSpecifierOfSpecialVertex(int specialLocation){
- int specialPointArray[6] = {0, 6, 42, 53, 41, 11};
- vertexSpecifier a;
- a= getVertexSpecifierFromIndex (specialPointArray[specialLocation]);
- return a;
- }
- static edgeSpecifier getSpecifierOfSpecialEdge(int SpecialLocation){
- int specialEdgeArray[6] = {1, 18, 60, 70, 51, 15};
- edgeSpecifier a;
- a= getEdgeSpecifierFromIndex (specialEdgeArray[SpecialLocation]);
- return a;
- }
-
- static vertexSpecifier getVertexAdjacentToRegion (regionSpecifier input,
- int index){
- vertexSpecifier vertexAdjacentToRegion;
- if (index == 0){
- vertexAdjacentToRegion.x = input.x;
- vertexAdjacentToRegion.y = input.y + 1;
- } else if (index == 1){
- vertexAdjacentToRegion.x = input.x + 1;
- vertexAdjacentToRegion.y = input.y;
- } else if (index == 2){
- vertexAdjacentToRegion.x = input.x + 1;
- vertexAdjacentToRegion.y = input.y - 1;
- } else if (index == 3){
- vertexAdjacentToRegion.x = input.x;
- vertexAdjacentToRegion.y = input.y - 1;
- } else if (index == 4){
- vertexAdjacentToRegion.x = input.x - 1;
- vertexAdjacentToRegion.y = input.y;
- } else if (index == 5){
- vertexAdjacentToRegion.x = input.x - 1;
- vertexAdjacentToRegion.y = input.y + 1;
- } else {
- vertexAdjacentToRegion.x = 0;
- vertexAdjacentToRegion.y = 0;
- assert(FALSE);
- }
- return vertexAdjacentToRegion;
- }
- static vertexSpecifier getRightVertex(vertexSpecifier current,
- vertexSpecifier back){
- int backcount=0;
- int i=0;
- vertexSpecifier surroundingVertecies[3];
- getSurroundingVertecies(current, surroundingVertecies);
- while(i<3){
- if((surroundingVertecies[i].x == back.x) && (surroundingVertecies[i].y == back.y)){
- backcount = i;
- }
- i++;
- }
- return surroundingVertecies[(backcount+2)%3];
- }
- static vertexSpecifier getLeftVertex(vertexSpecifier current,
- vertexSpecifier back){
- int backcount = 0;
- int i=0;
- vertexSpecifier surroundingVertecies[3];
- getSurroundingVertecies(current, surroundingVertecies);
- while(i<3){
- if((surroundingVertecies[i].x == back.x) && (surroundingVertecies[i].y == back.y)){
- backcount = i;
- }
- i++;
- }
- return surroundingVertecies[(backcount+1)%3];
- }
- static void getSurroundingVertecies(vertexSpecifier p1,
- vertexSpecifier surroundingVertecies[3]){
- int i = 0;
- if(isVertex(p1.x,p1.y+1)){
- vertexSpecifier temp = {p1.x, p1.y +1};
- surroundingVertecies[i] = temp;
- i++;
- }
- if(isVertex(p1.x+1,p1.y)){
- vertexSpecifier temp = {p1.x+1, p1.y};
- surroundingVertecies[i] = temp;
- i++;
- }
- if(isVertex(p1.x+1,p1.y-1)){
- vertexSpecifier temp = {p1.x+1, p1.y -1};
- surroundingVertecies[i] = temp;
- i++;
- }
- if(isVertex(p1.x,p1.y-1)){
- vertexSpecifier temp = {p1.x, p1.y-1};
- surroundingVertecies[i] = temp;
- i++;
- }
- if(isVertex(p1.x-1,p1.y)){
- vertexSpecifier temp = {p1.x-1, p1.y};
- surroundingVertecies[i] = temp;
- i++;
- }
- if(isVertex(p1.x-1,p1.y+1)){
- vertexSpecifier temp = {p1.x-1, p1.y+1};
- surroundingVertecies[i] = temp;
- i++;
- }
- }
- static int isVertex(int x, int y){
- return ((y - x)%3 != 0);
- }
- static void tracePath(vertexSpecifier start, vertexSpecifier back,
- path input, vertexSpecifier* p1, vertexSpecifier* p2){
- vertexSpecifier currentNode = start;
- vertexSpecifier currentBackDirection = back;
- vertexSpecifier temp;
- int i;
- i=0;
- while (input[i] != '\0'){
- temp = currentNode;
- if (input[i] == 'L'){
- currentNode = getLeftVertex (currentNode, currentBackDirection);
- currentBackDirection = temp;
- } else if (input[i] == 'R'){
- currentNode = getRightVertex (currentNode, currentBackDirection);
- currentBackDirection = temp;
- } else if (input[i] == 'B'){
- currentNode = currentBackDirection;
- currentBackDirection = temp;
- }
- i++;
- }
- if(p1 != NULL){
- *p1 = currentNode;
- }
- if(p2 != NULL){
- *p2 = currentBackDirection;
- }
- }