state: Added more scoring and turn actions

This commit is contained in:
Nathan Woodburn 2023-04-24 16:56:31 +10:00
parent 28630ea520
commit 8ed19d75bd
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
3 changed files with 169 additions and 16 deletions

View File

@ -1,5 +1,8 @@
package comp1110.ass2;
import java.util.Random;
import java.util.Set;
/**
* Player class
* This class is used to store the information of a player
@ -231,6 +234,47 @@ public class Player {
return numPieces;
}
/**
* Check if player is able to do any moves
* @return true if player can do any moves, false otherwise
*/
public boolean canPlay(State state) {
Set<String> validMoves = BlueLagoon.generateAllValidMoves(state.toString());
return validMoves.size() > 0;
}
/**
* Do a Random Move
* @param state State to do the move on
*/
public void doRandomMove(State state) {
if (state.getCurrentPlayerID() != playerID) {
return;
}
Set<String> validMoves = BlueLagoon.generateAllValidMoves(state.toString());
if (validMoves.size() == 0) {
return;
}
Random rand = new Random();
int randomMove = rand.nextInt(0, validMoves.size());
int i = 0;
for (String move : validMoves) {
if (i == randomMove) {
char pieceType = move.charAt(0);
String coordStr = move.substring(2);
int x = Integer.parseInt(coordStr.split(",")[0]);
int y = Integer.parseInt(coordStr.split(",")[1]);
Coord coord = new Coord(x, y);
state.placePiece(coord, pieceType);
state.nextPlayer();
return;
}
i++;
}
}
@Override
public String toString() {
String str = "p " + playerID + " " + score + " " + numCoconuts + " " + numBamboo + " " + numWater + " " + numPreciousStones + " " + numStatuette + " S";

View File

@ -228,19 +228,29 @@ public class State {
}
/**
* Get the current player
* Get the current player ID
* @return int current player
*/
public int getCurrentPlayer() {
public int getCurrentPlayerID() {
return currentPlayer;
}
/**
* Get the current player
* @return Player current player
*/
public Player getCurrentPlayer() {
return players[currentPlayer];
}
/**
* Get the current phase
* Returns 'E' for exploration, 'S' for settlement, 'O' for game over
* @return char current phase
*/
public char getCurrentPhase() {
if (currentPhase == 0) return 'E';
else return 'S';
else if (currentPhase == 1) return 'S';
else return 'O'; // Return 'O' for game over
}
/**
@ -340,16 +350,6 @@ public class State {
if (currentPlayer >= numPlayers) currentPlayer = 0;
}
/**
* Start next phase.
* This handles changing the current player and scoring
*/
public void nextPhase() {
currentPhase++;
if (currentPhase > 1) currentPhase = 0;
nextPlayer();
}
/**
* Place a piece on the board. Uses current turn's player
* @param coord Coord coordinate to place piece
@ -374,9 +374,54 @@ public class State {
}
}
/**
* is the phase over?
*/
public boolean isPhaseOver() {
boolean resourcesLeft = false;
for (Resource r : resources) {
if (!r.isClaimed() && r.getType() != 'S') resourcesLeft = true;
}
boolean moveLeft = false;
for (Player player : players) {
if (player.canPlay(this)) moveLeft = true;
}
return !resourcesLeft || !moveLeft;
}
// endregion
// region Scoring
/**
* Score for that phase
*/
public void scorePhase() {
for (Player p: players) {
p.addScore(createScore(p.getPlayerID()));
}
if (getCurrentPhase() == 'E') {
currentPhase++;
}
else {
// Game over
finalScore();
currentPhase++;
}
}
/**
* Final score
*
*/
public void finalScore() {
}
/**
* Get score of player ID based on current phase and game state
* @param playerID int player ID base 0
@ -465,12 +510,64 @@ public class State {
return score;
}
/**
* Score Links
* A (potentially) branching path of neighbouring settlers and villages
* belonging to a player forms a chain. Players earn points from the chain
* of their pieces which links the most islands. Players earn 5 points
* per linked island in this chain.
* @param playerID int player to score
* @return int score
*/
public int scoreLinks(int playerID) {
int score = 0;
return score; //! TODO
}
/**
* Score resources
* @param playerID int player to score
* @return int score
*/
public int scoreResources(int playerID) {
int score = 0;
char[] resourceTypes = {'C', 'B', 'W', 'P'};
for (char type : resourceTypes) {
int numResources = players[playerID].getNumResource(type);
if (numResources >= 4) {
score += 20;
} else if (numResources == 3) {
score += 10;
} else if (numResources == 2) {
score += 5;
}
}
int numCoconuts = players[playerID].getNumResource('C');
int numBananas = players[playerID].getNumResource('B');
int numWater = players[playerID].getNumResource('W');
int numPreciousStones = players[playerID].getNumResource('P');
if (numCoconuts >= 1 && numBananas >= 1 && numWater >= 1 && numPreciousStones >= 1) {
score += 10;
}
return score;
}
/**
* Score statuettes
* @param playerID int player to score
* @return int score
*/
public int scoreStatuettes(int playerID) {
int score = 0;
return score; //! TODO
}
// endregion
@Override
public String toString() {
String str = "a " + boardHeight + " " + getNumPlayers() + "; c " + getCurrentPlayer() + " " + getCurrentPhase() + "; ";
String str = "a " + boardHeight + " " + getNumPlayers() + "; c " + getCurrentPlayerID() + " " + getCurrentPhase() + "; ";
for (Island island : islands) {
str += island.toString() + " ";
}

View File

@ -15,7 +15,7 @@ public class StateTest {
State state = new State(GameDataLoader.DEFAULT_GAME);
Assertions.assertEquals(13, state.getBoardHeight(), "The test failed because the board length is not 13");
Assertions.assertEquals(2, state.getNumPlayers(), "The test failed because the number of players is not 2");
Assertions.assertEquals(0, state.getCurrentPlayer(), "The test failed because the current player is not 0");
Assertions.assertEquals(0, state.getCurrentPlayerID(), "The test failed because the current player is not 0");
Assertions.assertEquals('E', state.getCurrentPhase(), "The test failed because the current phase is not E");
Assertions.assertEquals(GameDataLoader.DEFAULT_GAME,state.toString(), "The test failed because the state created from the string is not the same as the state created from the string");
@ -56,7 +56,6 @@ public class StateTest {
// Distribute resources
state.distributeResources();
Resource toClaim = state.getUnclaimedResource(new Coord(0,0));
System.out.println(toClaim);
// Place a settler at (0,0)
state.placePiece(new Coord(0,0), 'S');
@ -71,6 +70,19 @@ public class StateTest {
public void testStateWHEELSGAME(){
State state = new State(GameDataLoader.WHEELS_GAME);
Assertions.assertEquals(GameDataLoader.WHEELS_GAME,state.toString(), "The test failed because the state created from the string is not the same as the state created from the string");
state.distributeResources();
Assertions.assertFalse(state.isPhaseOver(), "The test failed because the phase is over even though it should not be because the phase is not over");
// Test endPhase
while (!state.isPhaseOver()) {
if (!state.getCurrentPlayer().canPlay(state)) state.nextPlayer();
state.getCurrentPlayer().doRandomMove(state);
}
state.scorePhase();
System.out.println(state);
}
}