Compare commits
58 Commits
generateAl
...
master
Author | SHA1 | Date | |
---|---|---|---|
7c8dac2aff | |||
|
a19f6e371c | ||
|
bad42dd8e8 | ||
|
7fcf6d3a1b | ||
20e6c9e3c1 | |||
6f727478be | |||
5ba6fc5d76 | |||
1f73ffcab9 | |||
6edfd9266a | |||
|
dd4e360d8e | ||
|
d99b63c82b | ||
55933ae49e | |||
519e9e840e | |||
77aaa07984 | |||
|
56b29a3301 | ||
|
bf38979834 | ||
|
6da9b06e9b | ||
|
227f4f8e3a | ||
|
ec4d3b938c | ||
|
c4db86793c | ||
|
bd2b3477b6 | ||
|
28b0288e8a | ||
|
0f203df939 | ||
9381eedf5f | |||
8a4e83b9a7 | |||
f6f3f4a6a1 | |||
|
73293edb43 | ||
|
90674de713 | ||
|
199a50b088 | ||
|
3d84fa1e83 | ||
|
6e6bf69bdf | ||
506c2bb395 | |||
bdaaf35a88 | |||
d0c3d0faee | |||
|
ad3a9c4a00 | ||
cf4bb47c8f | |||
8fdf5a2cdb | |||
025d5af907 | |||
91d9721855 | |||
329a65176b | |||
7aa5605ed2 | |||
b4e3afb867 | |||
3c343d002a | |||
e52d16d01a | |||
a13e93c339 | |||
d436cdb138 | |||
649481583a | |||
2f0964b26b | |||
dd56bbfdd7 | |||
|
8f0be1948f | ||
52630951f0 | |||
035d3bf022 | |||
|
98e98e496c | ||
|
2cb2a46b01 | ||
e6b4f9fd89 | |||
aa0bbb146d | |||
355af7e358 | |||
8b142ad434 |
@ -10,8 +10,8 @@ declaration: >-
|
||||
contributions:
|
||||
- uid: u7156831
|
||||
contribution: 33
|
||||
- uid:
|
||||
contribution:
|
||||
- uid: u7492895
|
||||
contribution: 33
|
||||
- uid: u7280427
|
||||
contribution: 33
|
||||
|
||||
@ -20,7 +20,7 @@ contributions:
|
||||
signatures:
|
||||
- name: Nathan Woodburn
|
||||
uid: u7156831
|
||||
- name:
|
||||
uid:
|
||||
- name: Justin Ryu
|
||||
uid: u7492895
|
||||
- name: Immanuel Alvaro Bhirawa
|
||||
uid: u7280427
|
@ -52,7 +52,7 @@ declaration: >-
|
||||
signatures:
|
||||
- name: Nathan Woodburn
|
||||
uid: u7156831
|
||||
- name:
|
||||
uid:
|
||||
- name:
|
||||
uid:
|
||||
- name: Immanuel Alvaro Bhirawa
|
||||
uid: u7280427
|
||||
- name: Justin Ryu
|
||||
uid: u7492895
|
||||
|
@ -4,7 +4,7 @@ Reviewed by: Nathan Woodburn, u7156831
|
||||
|
||||
Reviewing code written by: Immanuel Alvaro Bhirawa, u7280427
|
||||
|
||||
Component: `isMoveValid` from [BlueLagoon.java L145-L311](https://gitlab.cecs.anu.edu.au/u7156831/comp1110-ass2/-/blob/master/src/comp1110/ass2/BlueLagoon.java#L145-L311)
|
||||
Component: `isMoveValid` from [BlueLagoon.java L145-L311](https://gitlab.cecs.anu.edu.au/u7156831/comp1110-ass2/-/blob/b8487c3c0826bef4e676a13f8ea05c578c73d2de/src/comp1110/ass2/BlueLagoon.java#L145-L311)
|
||||
|
||||
### Comments
|
||||
|
||||
@ -17,10 +17,10 @@ Component: `isMoveValid` from [BlueLagoon.java L145-L311](https://gitlab.cecs.an
|
||||
|
||||
- Places to improve:
|
||||
- Some comments are not needed, such as commenting about well named variables.
|
||||
```java
|
||||
int numberOfPlayer = 0; // Number of player
|
||||
String playerId = ""; // Player ID
|
||||
```
|
||||
```java
|
||||
int numberOfPlayer = 0; // Number of player
|
||||
String playerId = ""; // Player ID
|
||||
```
|
||||
- Duplicate code could be avoided. For example [this switch](https://gitlab.cecs.anu.edu.au/u7156831/comp1110-ass2/-/blob/b8487c3c0826bef4e676a13f8ea05c578c73d2de/src/comp1110/ass2/BlueLagoon.java#L231-L256) could be shortened to the below to avoid duplicate code.
|
||||
```java
|
||||
switch (numberOfPlayer) {
|
||||
|
0
admin/E-review-u7492895.md
Normal file
0
admin/E-review-u7492895.md
Normal file
53
admin/F-best-u7156831.yml
Normal file
53
admin/F-best-u7156831.yml
Normal file
@ -0,0 +1,53 @@
|
||||
# IMPORTANT: It is very important that you correctly complete this originality
|
||||
# statement.
|
||||
#
|
||||
# This is your statement of your submitted work being your own.
|
||||
# Incorrectly filling out this statement could lead to charges
|
||||
# of academic misconduct.
|
||||
#
|
||||
# For information on how to fill this out correctly, see
|
||||
# https://cs.anu.edu.au/courses/comp1110/help/faq/09-originality/
|
||||
#
|
||||
|
||||
declaration: >-
|
||||
I submit the work below for assessment as my best work. I declare that this
|
||||
is entirely my own work, with the following documented exceptions:
|
||||
|
||||
# Use this to list names of people who you collaborated with, and a
|
||||
# comment about what you collaborated on.
|
||||
#
|
||||
# Add as many "name+comment" entries as necessary
|
||||
# (or remove it altogether if you haven't collaborated with anyone)
|
||||
# collaboration:
|
||||
# - name:
|
||||
# comment: >-
|
||||
|
||||
# Use this to list any code that you used that you did not write,
|
||||
# aside from code provided by the lecturer. Provide a comment
|
||||
# explaining your use and the URL to that code and the licence for
|
||||
# that code
|
||||
#
|
||||
# Add as many "url+licence+comment" entries as necessary
|
||||
# (or remove it altogether if you haven't used any external code)
|
||||
# code:
|
||||
# - comment:
|
||||
# url:
|
||||
# licence:
|
||||
|
||||
# I wish to submit the following classes as entirely my own (remove this if
|
||||
# you want to just submit methods):
|
||||
class:
|
||||
- Island
|
||||
- Coord
|
||||
- Player
|
||||
- Resource
|
||||
|
||||
# I wish to submit the following methods as entirely my own (remove this if
|
||||
# you want to just submit classes):
|
||||
method:
|
||||
- Everything in class state except for scoreLinks(), findLongestLinkScore(),
|
||||
DFSRecursionLink(), findScoreForLink()
|
||||
|
||||
# sign *your* name and uid here
|
||||
name: Nathan Woodburn
|
||||
uid: u7156831
|
@ -9,5 +9,5 @@ of our project implements the following features:
|
||||
- Playable against a computer opponent / AI (Task 16)
|
||||
- Generalised GUI to more than two players (Task 17)
|
||||
- Generalised GUI to different sized boards (Task 17)
|
||||
|
||||
additional features...
|
||||
- Allow more than one AI player (up to 4)
|
||||
- Toggleable Dark mode
|
@ -19,9 +19,9 @@ declaration: >-
|
||||
#
|
||||
# Add as many "name+comment" entries as necessary
|
||||
# (or remove it altogether if you haven't collaborated with anyone)
|
||||
collaboration:
|
||||
- name:
|
||||
comment: >-
|
||||
# collaboration:
|
||||
# - name:
|
||||
# comment: >-
|
||||
|
||||
# Use this to list any code that you used that you did not write,
|
||||
# aside from code provided by the lecturer. Provide a comment
|
||||
@ -30,10 +30,10 @@ collaboration:
|
||||
#
|
||||
# Add as many "url+licence+comment" entries as necessary
|
||||
# (or remove it altogether if you haven't used any external code)
|
||||
code:
|
||||
- comment:
|
||||
url:
|
||||
licence:
|
||||
# code:
|
||||
# - comment: CSS styling for buttons + comboboxes
|
||||
# url: http://fxexperience.com/2011/12/styling-fx-buttons-with-css/
|
||||
# licence: Public Domain
|
||||
|
||||
# Use this to list any assets (artwork, sound, etc) that you used.
|
||||
# Provide a comment explaining your use of that asset and the URL
|
||||
@ -41,18 +41,18 @@ code:
|
||||
#
|
||||
# Add as many "url+licence+comment" entries as necessary
|
||||
# (or remove it altogether if you haven't used any external assets)
|
||||
assets:
|
||||
- comment:
|
||||
url:
|
||||
licence:
|
||||
# assets:
|
||||
# - comment:
|
||||
# url:
|
||||
# licence:
|
||||
|
||||
|
||||
# Sign *your* name and uids here. (Remove entries if you have fewer
|
||||
# than three members.)
|
||||
signatures:
|
||||
- name: Nathan Woodburn
|
||||
uid: u7156831
|
||||
- name:
|
||||
uid:
|
||||
- name:
|
||||
uid:
|
||||
- name:
|
||||
uid:
|
||||
- name: Justin Ryu
|
||||
uid: u7492895
|
||||
|
@ -1,21 +1,15 @@
|
||||
package comp1110.ass2;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class BlueLagoon {
|
||||
// The Game Strings for five maps have been created for you.
|
||||
// They have only been encoded for two players. However, they are
|
||||
// easily extendable to more by adding additional player statements.
|
||||
|
||||
// region Game Strings
|
||||
public static final String DEFAULT_GAME = "a 13 2; c 0 E; i 6 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 1,4 2,0 2,1; i 6 0,5 0,6 0,7 1,6 1,7 1,8 2,6 2,7 2,8 3,7 3,8; i 6 7,12 8,11 9,11 9,12 10,10 10,11 11,10 11,11 11,12 12,10 12,11; i 8 0,9 0,10 0,11 1,10 1,11 1,12 2,10 2,11 3,10 3,11 3,12 4,10 4,11 5,11 5,12; i 8 4,0 5,0 5,1 6,0 6,1 7,0 7,1 7,2 8,0 8,1 8,2 9,0 9,1 9,2; i 8 10,3 10,4 11,0 11,1 11,2 11,3 11,4 11,5 12,0 12,1 12,2 12,3 12,4 12,5; i 10 3,3 3,4 3,5 4,2 4,3 4,4 4,5 5,3 5,4 5,5 5,6 6,3 6,4 6,5 6,6 7,4 7,5 7,6 8,4 8,5; i 10 5,8 5,9 6,8 6,9 7,8 7,9 7,10 8,7 8,8 8,9 9,7 9,8 9,9 10,6 10,7 10,8 11,7 11,8 12,7 12,8; s 0,0 0,5 0,9 1,4 1,8 1,12 2,1 3,5 3,7 3,10 3,12 4,0 4,2 5,9 5,11 6,3 6,6 7,0 7,8 7,12 8,2 8,5 9,0 9,9 10,3 10,6 10,10 11,0 11,5 12,2 12,8 12,11; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String WHEELS_GAME = "a 13 2; c 0 E; i 5 0,1 0,2 0,3 0,4 1,1 1,5 2,0 2,5 3,0 3,6 4,0 4,5 5,1 5,5 6,1 6,2 6,3 6,4; i 5 0,8 0,9 0,10 1,8 1,11 2,7 2,11 3,8 3,11 4,8 4,9 4,10; i 7 8,8 8,9 8,10 9,8 9,11 10,7 10,11 11,8 11,11 12,8 12,9 12,10; i 7 10,0 10,1 10,4 10,5 11,0 11,2 11,3 11,4 11,6 12,0 12,1 12,4 12,5; i 9 2,2 2,3 3,2 3,4 4,2 4,3; i 9 2,9; i 9 6,6 6,7 6,8 6,9 6,10 6,11 7,6 8,0 8,1 8,2 8,3 8,4 8,5; i 9 10,9; s 0,1 0,4 0,10 2,2 2,3 2,9 2,11 3,0 3,2 3,4 3,6 4,2 4,3 4,10 6,1 6,4 6,6 6,11 8,0 8,5 8,8 8,10 10,0 10,5 10,7 10,9 10,11 11,3 12,1 12,4 12,8 12,10; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String FACE_GAME = "a 13 2; c 0 E; i 6 0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 0,10 0,11 1,0 1,12 2,0 2,11 3,0 3,12 4,0 4,11 5,0 5,12 6,0 6,11 7,0 7,12 8,0 8,11 9,0 9,12 10,0 10,11 11,0 11,12 12,0 12,1 12,2 12,3 12,4 12,5 12,6 12,7 12,8 12,9 12,10 12,11; i 6 2,4 2,5 2,6 2,7; i 9 4,4 4,5 4,6 4,7; i 9 6,5 6,6 7,5 7,7 8,5 8,6; i 12 2,2 3,2 3,3 4,2 5,2 5,3 6,2 7,2 7,3; i 12 2,9 3,9 3,10 4,9 5,9 5,10 6,9 7,9 7,10; i 12 9,2 9,10 10,2 10,3 10,4 10,5 10,6 10,7 10,8 10,9; s 0,3 0,8 1,0 1,12 2,2 2,4 2,7 2,9 4,2 4,5 4,6 4,9 5,0 5,12 6,2 6,5 6,6 6,9 8,0 8,5 8,6 8,11 9,2 9,10 10,3 10,5 10,6 10,8 11,0 11,12 12,4 12,7; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String SIDES_GAME = "a 7 2; c 0 E; i 4 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3 3,0 3,1 3,2 3,3 4,0 4,1 4,2 4,3 5,0 5,1 5,2 5,3 6,0 6,1 6,2 6,3; i 20 0,5 1,5 1,6 2,5 3,5 3,6 4,5 5,5 5,6 6,5; s 0,0 0,1 0,2 0,3 1,1 1,2 1,3 1,5 1,6 2,0 2,1 2,2 2,3 3,0 3,1 3,2 3,3 3,5 3,6 4,0 4,1 4,2 4,3 5,1 5,2 5,3 5,5 5,6 6,0 6,1 6,2 6,3; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String SPACE_INVADERS_GAME = "a 23 2; c 0 E; i 6 0,2 0,7 1,3 1,7 2,2 2,3 2,4 2,5 2,6 2,7 3,2 3,4 3,5 3,6 3,8 4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9 5,0 5,1 5,3 5,4 5,5 5,6 5,7 5,9 5,10 6,0 6,2 6,7 6,9 7,3 7,4 7,6 7,7; i 6 0,14 0,19 1,15 1,19 2,14 2,15 2,16 2,17 2,18 2,19 3,14 3,16 3,17 3,18 3,20 4,12 4,13 4,14 4,15 4,16 4,17 4,18 4,19 4,20 4,21 5,12 5,13 5,15 5,16 5,17 5,18 5,19 5,21 5,22 6,12 6,14 6,19 6,21 7,15 7,16 7,18 7,19; i 6 17,9 18,8 18,9 19,6 19,7 19,8 19,9 19,10 19,11 19,12 20,5 20,6 20,7 20,8 20,9 20,10 20,11 20,12 21,5 21,6 21,7 21,8 21,9 21,10 21,11 21,12 21,13 22,5 22,6 22,7 22,8 22,9 22,10 22,11 22,12; i 8 12,3 12,5 13,3 13,4 13,5 13,6 14,1 14,2 14,3 14,4 14,5 15,1 15,2 15,3 16,1 16,2; i 8 12,17 12,18 12,19 13,17 13,18 13,19 13,20 14,17 14,18 14,19 14,20 15,19 15,20 15,21 16,19 16,20; i 8 13,14 14,13 14,14 15,13 15,14 15,15 16,13 16,14; i 8 14,7 15,7 15,8 16,7; i 10 8,9 9,9 10,9 11,9; i 10 8,12 9,13 10,12 11,13; i 10 9,1 10,1 11,1 12,1; i 10 9,22 10,21 11,22 12,21; i 10 13,10 14,10 15,10; i 10 17,0 18,0 19,0 20,0; i 10 17,16 18,16 19,16 20,16; s 0,2 0,7 0,14 0,19 3,5 3,17 6,0 6,9 6,12 6,21 7,4 7,6 7,16 7,18 11,9 11,13 12,1 12,19 12,21 13,10 15,2 15,8 15,14 15,20 17,9 18,8 18,9 20,0 20,16 21,6 21,9 21,12; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
|
||||
// endregion
|
||||
// region Checks on strings
|
||||
/**
|
||||
* Check if the string encoding of the game state is well-formed.
|
||||
@ -44,26 +38,27 @@ public class BlueLagoon {
|
||||
// For the stonesStatement use the following regex string
|
||||
matchArray[3] = "(s (\\d{1,2},\\d{1,2} )+\\d{1,2},\\d{1,2}; )";
|
||||
// For the resources and statuettes use the following regex string
|
||||
matchArray[4] = "r C (\\d{1,2},\\d{1,2} )*B (\\d{1,2},\\d{1,2} )*W (\\d{1,2},\\d{1,2} )*P (\\d{1,2},\\d{1,2} )*S( \\d{1,2},\\d{1,2})*;";
|
||||
matchArray[4] = "r C (\\d{1,2},\\d{1,2} )*B (\\d{1,2},\\d{1,2} )*W (\\d{1,2},\\d{1,2} )*P (\\d{1,2},\\d{1,2} " +
|
||||
")*S( \\d{1,2},\\d{1,2})*;";
|
||||
// For the playersStatement use the following regex string
|
||||
matchArray[5] = "( p \\d \\d{1,3} \\d{1,2} \\d{1,2} \\d{1,2} \\d{1,2} \\d{1,2} S (\\d{1,2},\\d{1,2} )*T( (\\d{1,2},\\d{1,2} ?)*)?;)*";
|
||||
matchArray[5] = "( p \\d \\d{1,3} \\d{1,2} \\d{1,2} \\d{1,2} \\d{1,2} \\d{1,2} S (\\d{1,2},\\d{1,2} )*T( " +
|
||||
"(\\d{1,2},\\d{1,2} ?)*)?;)*";
|
||||
|
||||
// Combine the regex strings into one string to match the state string
|
||||
String matchString = "";
|
||||
StringBuilder matchString = new StringBuilder();
|
||||
for (String match:matchArray) {
|
||||
matchString += match;
|
||||
matchString.append(match);
|
||||
}
|
||||
|
||||
// Check if the state string matches the regex string
|
||||
if (!stateString.matches(matchString)) return false;
|
||||
if (!stateString.matches(matchString.toString())) return false;
|
||||
|
||||
// Check that there is one and only one of each player id
|
||||
// This fixed test 2-3 of D2DTests.testIsStateStringWellFormed
|
||||
int numPlayers = Integer.parseInt(stateString.substring(stateString.indexOf(";") - 1, stateString.indexOf(";")));
|
||||
int numPlayers = Character.getNumericValue(stateString.charAt(stateString.indexOf(";")-1));
|
||||
for (int i = 0; i < numPlayers; i++) {
|
||||
if (stateString.length() - stateString.replaceAll("p "+i,"").length() != 3) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -155,9 +150,9 @@ public class BlueLagoon {
|
||||
// Coords of the island tiles
|
||||
ArrayList<String> coordsContainer = new ArrayList<>();
|
||||
|
||||
int numberOfPlayer = 0; // Number of player
|
||||
int numberOfPlayer; // Number of player
|
||||
String playerId = ""; // Player ID
|
||||
String pStatePlayerId = ""; // the current Player's move ID
|
||||
String pStatePlayerId; // the current Player's move ID
|
||||
ArrayList<String> settlerCoords = new ArrayList<>(); // Placed Settler Coordinates
|
||||
ArrayList<String> villageCoords = new ArrayList<>(); // Placed villages coordinates
|
||||
ArrayList<String> playerSettlerCoords = new ArrayList<>(); // The current Player's settler coords
|
||||
@ -334,18 +329,12 @@ public class BlueLagoon {
|
||||
Set<String> allMoves = new HashSet<>();
|
||||
|
||||
// Calculate number of pieces each player starts with
|
||||
int startNumSettlers = 0;
|
||||
switch (numPlayers) {
|
||||
case 2:
|
||||
startNumSettlers = 30;
|
||||
break;
|
||||
case 3:
|
||||
startNumSettlers = 25;
|
||||
break;
|
||||
case 4:
|
||||
startNumSettlers = 20;
|
||||
break;
|
||||
}
|
||||
int startNumSettlers = switch (numPlayers) {
|
||||
case 2 -> 30;
|
||||
case 3 -> 25;
|
||||
case 4 -> 20;
|
||||
default -> 0;
|
||||
};
|
||||
|
||||
|
||||
// Check if the player has placed all their settlers or villages
|
||||
@ -424,7 +413,7 @@ public class BlueLagoon {
|
||||
// if the settler is not adjacent with any of the pieces return false
|
||||
if ((isAdjacent(cord, playerVillageCoords) || isAdjacent(cord, playerSettlerCoords))) {
|
||||
// Add the move to the set
|
||||
if (hasSettler) allMoves.add("S " + cord);
|
||||
allMoves.add("S " + cord);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -464,9 +453,9 @@ public class BlueLagoon {
|
||||
State state = new State(stateString);
|
||||
char pieceType = moveString.charAt(0);
|
||||
String coordStr = moveString.substring(2);
|
||||
int x = Integer.parseInt(coordStr.split(",")[0]);
|
||||
int y = Integer.parseInt(coordStr.split(",")[1]);
|
||||
Coord coord = new Coord(x, y);
|
||||
int y = Integer.parseInt(coordStr.split(",")[0]);
|
||||
int x = Integer.parseInt(coordStr.split(",")[1]);
|
||||
Coord coord = new Coord(y, x);
|
||||
state.placePiece(coord, pieceType);
|
||||
return state.toString();
|
||||
}
|
||||
@ -488,10 +477,6 @@ public class BlueLagoon {
|
||||
* the score for each player
|
||||
*/
|
||||
|
||||
//"i 6 7,12 8,11 9,11 9,12 10,10 10,11 11,10 11,11 11,12 12,10 12,11; i 8 0,9 0,10 0,11 1,10 1,11 1,12 2,10 2,11 3,10 3,11 3,12 4,10 4,11 5,11 5,12; i 8 4,0 5,0 5,1 6,0 6,1 7,0 7,1 7,2 8,0 8,1 8,2 9,0 9,1 9,2;"
|
||||
|
||||
// "p 1 42 1 2 3 4 5 S 5,6 8,7 T 1,2;"
|
||||
|
||||
public static int[] calculateTotalIslandsScore(String stateString) {
|
||||
State state = new State(stateString);
|
||||
int[] scores = new int[state.getNumPlayers()];
|
||||
@ -523,9 +508,11 @@ public class BlueLagoon {
|
||||
public static int[] calculateIslandLinksScore(String stateString){
|
||||
State state = new State(stateString);
|
||||
int[] scores = new int[state.getNumPlayers()];
|
||||
|
||||
for (int i = 0; i < state.getNumPlayers(); i++) {
|
||||
scores[i] = state.scoreLinks(i);
|
||||
}
|
||||
|
||||
return scores;
|
||||
}
|
||||
|
||||
@ -638,6 +625,7 @@ public class BlueLagoon {
|
||||
return state.toString();
|
||||
}
|
||||
|
||||
// 2 phases, exploration and settlement
|
||||
/**
|
||||
* Given a state string and a move string, apply the move to the board.
|
||||
* <p>
|
||||
@ -651,24 +639,48 @@ public class BlueLagoon {
|
||||
* @return a string representing the new state after the move is applied to the board
|
||||
*/
|
||||
public static String applyMove(String stateString, String moveString){
|
||||
State state = new State(stateString);
|
||||
State state = new State(stateString);
|
||||
char pieceType = moveString.charAt(0);
|
||||
String coordStr = moveString.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);
|
||||
int y = Integer.parseInt(coordStr.split(",")[0]);
|
||||
int x = Integer.parseInt(coordStr.split(",")[1]);
|
||||
Coord coord = new Coord(y, x);
|
||||
|
||||
// if the move is valid, place it
|
||||
if ( isMoveValid(stateString, moveString)) state.placePiece(coord, pieceType);
|
||||
|
||||
// if the move ends the phase
|
||||
if (state.isPhaseOver()){
|
||||
state.scorePhase();
|
||||
|
||||
// Applying end of Phase rules
|
||||
// For Exploration Phase
|
||||
// Tally up the score, clean the board, distribute resources, change to next Phase
|
||||
if (state.getCurrentPhase() == 'E') {
|
||||
state.scorePhase();
|
||||
state.cleanBoard();
|
||||
state.distributeResources();
|
||||
state.nextPhase();
|
||||
}
|
||||
|
||||
// For Settlement Phase
|
||||
// Tally up the score
|
||||
else if (state.getCurrentPhase() == 'S') {
|
||||
state.scorePhase();
|
||||
}
|
||||
}
|
||||
|
||||
// After the endPhase is over, move to the next player
|
||||
state.nextPlayer();
|
||||
|
||||
// if the current player cannot play, go to the next player
|
||||
int players = state.getNumPlayers();
|
||||
|
||||
// the case where there are multiple players, while the current player cannot play the move,
|
||||
// move to the next player and skip each player once if that player cannot play a move.
|
||||
while (!state.getCurrentPlayer().canPlay(state)) {
|
||||
if (players == 1) break;
|
||||
state.nextPlayer();
|
||||
players--;
|
||||
}
|
||||
|
||||
return state.toString();
|
||||
|
@ -1,62 +1,46 @@
|
||||
package comp1110.ass2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Object to store coordinates
|
||||
* This stores the x and y coordinates of a point
|
||||
*/
|
||||
public class Coord {
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
public record Coord(int y, int x) {
|
||||
/**
|
||||
* Constructor for the Coord object
|
||||
*
|
||||
* @param x x coordinate
|
||||
* @param y y coordinate
|
||||
*/
|
||||
public Coord(int y, int x) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
public Coord {
|
||||
}
|
||||
|
||||
// region Getters and Setters
|
||||
|
||||
/**
|
||||
* Get the x coordinate
|
||||
*
|
||||
* @return int x coordinate
|
||||
*/
|
||||
public int getX() {
|
||||
@Override
|
||||
public int x() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the y coordinate
|
||||
*
|
||||
* @return int y coordinate
|
||||
*/
|
||||
public int getY() {
|
||||
@Override
|
||||
public int y() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the x coordinate
|
||||
* @param x int x coordinate
|
||||
*/
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the y coordinate
|
||||
* @param y int y coordinate
|
||||
*/
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* Check if two coordinates are equal
|
||||
*
|
||||
* @param coord Coord object to compare to
|
||||
* @return boolean true if equal, false otherwise
|
||||
*/
|
||||
@ -66,6 +50,7 @@ public class Coord {
|
||||
|
||||
/**
|
||||
* Check if two coordinates are adjacent (does not include diagonals)
|
||||
*
|
||||
* @param coord Coord object to compare to
|
||||
*/
|
||||
public boolean isAdjacent(Coord coord) {
|
||||
@ -80,18 +65,64 @@ public class Coord {
|
||||
|
||||
/**
|
||||
* Check if two coordinates are adjacent (includes diagonals)
|
||||
*
|
||||
* @param coord Coord object to compare to
|
||||
*/
|
||||
public boolean isAdjacentDiagonal(Coord coord){
|
||||
public boolean isAdjacentDiagonal(Coord coord) {
|
||||
if (isAdjacent(coord)) return true;
|
||||
if (this.x == coord.x - 1 && this.y == coord.y - 1) return true;
|
||||
if (this.x == coord.x - 1 && this.y == coord.y + 1) return true;
|
||||
if (this.x == coord.x + 1 && this.y == coord.y - 1) return true;
|
||||
return (this.x == coord.x + 1 && this.y == coord.y + 1);
|
||||
|
||||
// Consider hex offsets
|
||||
if (y%2 == 0){
|
||||
if (this.x == coord.x && this.y == coord.y + 1) return true;
|
||||
if (this.x == coord.x && this.y == coord.y - 1) return true;
|
||||
if (this.x == coord.x - 1 && this.y == coord.y + 1) return true;
|
||||
return (this.x == coord.x - 1 && this.y == coord.y - 1);
|
||||
}
|
||||
else {
|
||||
if (this.x == coord.x && this.y == coord.y + 1) return true;
|
||||
if (this.x == coord.x && this.y == coord.y - 1) return true;
|
||||
if (this.x == coord.x + 1 && this.y == coord.y + 1) return true;
|
||||
return (this.x == coord.x + 1 && this.y == coord.y - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player Player to check owned by
|
||||
* @return ArrayList of adjacent coordinates
|
||||
*/
|
||||
public Coord[] getClaimedAdjacent(Player player) {
|
||||
Coord[] adjacent = new Coord[8];
|
||||
adjacent[0] = new Coord(this.y, this.x + 1);
|
||||
adjacent[1] = new Coord(this.y, this.x - 1);
|
||||
adjacent[2] = new Coord(this.y + 1, this.x);
|
||||
adjacent[3] = new Coord(this.y - 1, this.x);
|
||||
adjacent[4] = new Coord(this.y + 1, this.x + 1);
|
||||
adjacent[5] = new Coord(this.y + 1, this.x - 1);
|
||||
adjacent[6] = new Coord(this.y - 1, this.x + 1);
|
||||
adjacent[7] = new Coord(this.y - 1, this.x - 1);
|
||||
|
||||
Coord[] adjacentOwned = new Coord[8];
|
||||
int ownedCount = 0;
|
||||
|
||||
for (Coord c : player.getPieces()) {
|
||||
for (int i = 0; i < adjacent.length; i++) {
|
||||
if (c.equals(adjacent[i])) {
|
||||
adjacentOwned[i] = c;
|
||||
ownedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Coord[] owned = new Coord[ownedCount];
|
||||
for (int i = 0; i < ownedCount; i++) {
|
||||
owned[i] = adjacentOwned[i];
|
||||
}
|
||||
return adjacentOwned;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a string representation of the coordinate (y,x)
|
||||
*
|
||||
* @return String representation of the coordinate
|
||||
*/
|
||||
@Override
|
||||
|
45
src/comp1110/ass2/GameData.java
Normal file
45
src/comp1110/ass2/GameData.java
Normal file
@ -0,0 +1,45 @@
|
||||
package comp1110.ass2;
|
||||
|
||||
public class GameData {
|
||||
public static final String DEFAULT_GAME = "a 13 2; c 0 E; i 6 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 1,4 2,0 2,1; " +
|
||||
"i 6 0,5 0,6 0,7 1,6 1,7 1,8 2,6 2,7 2,8 3,7 3,8; " +
|
||||
"i 6 7,12 8,11 9,11 9,12 10,10 10,11 11,10 11,11 11,12 12,10 12,11; " +
|
||||
"i 8 0,9 0,10 0,11 1,10 1,11 1,12 2,10 2,11 3,10 3,11 3,12 4,10 4,11 5,11 5,12; " +
|
||||
"i 8 4,0 5,0 5,1 6,0 6,1 7,0 7,1 7,2 8,0 8,1 8,2 9,0 9,1 9,2; " +
|
||||
"i 8 10,3 10,4 11,0 11,1 11,2 11,3 11,4 11,5 12,0 12,1 12,2 12,3 12,4 12,5; " +
|
||||
"i 10 3,3 3,4 3,5 4,2 4,3 4,4 4,5 5,3 5,4 5,5 5,6 6,3 6,4 6,5 6,6 7,4 7,5 7,6 8,4 8,5; " +
|
||||
"i 10 5,8 5,9 6,8 6,9 7,8 7,9 7,10 8,7 8,8 8,9 9,7 9,8 9,9 10,6 10,7 10,8 11,7 11,8 12,7 12,8; " +
|
||||
"s 0,0 0,5 0,9 1,4 1,8 1,12 2,1 3,5 3,7 3,10 3,12 4,0 4,2 5,9 5,11 6,3 6,6 7,0 7,8 7,12 8,2 8,5 9,0 9,9 " +
|
||||
"10,3 10,6 10,10 11,0 11,5 12,2 12,8 12,11; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String WHEELS_GAME = "a 13 2; c 0 E; i 5 0,1 0,2 0,3 0,4 1,1 1,5 2,0 2,5 3,0 3,6 4,0 4,5 5,1 " +
|
||||
"5,5 6,1 6,2 6,3 6,4; i 5 0,8 0,9 0,10 1,8 1,11 2,7 2,11 3,8 3,11 4,8 4,9 4,10; i 7 8,8 8,9 8,10 9,8 " +
|
||||
"9,11 10,7 10,11 11,8 11,11 12,8 12,9 12,10; i 7 10,0 10,1 10,4 10,5 11,0 11,2 11,3 11,4 11,6 12,0 12,1 " +
|
||||
"12,4 12,5; i 9 2,2 2,3 3,2 3,4 4,2 4,3; i 9 2,9; i 9 6,6 6,7 6,8 6,9 6,10 6,11 7,6 8,0 8,1 8,2 8,3 8,4 " +
|
||||
"8,5; i 9 10,9; s 0,1 0,4 0,10 2,2 2,3 2,9 2,11 3,0 3,2 3,4 3,6 4,2 4,3 4,10 6,1 6,4 6,6 6,11 8,0 8,5 8,8 " +
|
||||
"8,10 10,0 10,5 10,7 10,9 10,11 11,3 12,1 12,4 12,8 12,10; r C B W P S; " +
|
||||
"p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String FACE_GAME = "a 13 2; c 0 E; i 6 0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 0,10 0,11 " +
|
||||
"1,0 1,12 2,0 2,11 3,0 3,12 4,0 4,11 5,0 5,12 6,0 6,11 7,0 7,12 8,0 8,11 9,0 9,12 10,0 10,11 11,0 11,12 " +
|
||||
"12,0 12,1 12,2 12,3 12,4 12,5 12,6 12,7 12,8 12,9 12,10 12,11; i 6 2,4 2,5 2,6 2,7; i 9 4,4 4,5 4,6 4,7; " +
|
||||
"i 9 6,5 6,6 7,5 7,7 8,5 8,6; i 12 2,2 3,2 3,3 4,2 5,2 5,3 6,2 7,2 7,3; i 12 2,9 3,9 3,10 4,9 5,9 5,10 " +
|
||||
"6,9 7,9 7,10; i 12 9,2 9,10 10,2 10,3 10,4 10,5 10,6 10,7 10,8 10,9; s 0,3 0,8 1,0 1,12 2,2 2,4 2,7 " +
|
||||
"2,9 4,2 4,5 4,6 4,9 5,0 5,12 6,2 6,5 6,6 6,9 8,0 8,5 8,6 8,11 9,2 9,10 10,3 10,5 10,6 10,8 11,0 11,12 " +
|
||||
"12,4 12,7; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String SIDES_GAME = "a 7 2; c 0 E; i 4 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3 " +
|
||||
"3,0 3,1 3,2 3,3 4,0 4,1 4,2 4,3 5,0 5,1 5,2 5,3 6,0 6,1 6,2 6,3; i 20 0,5 1,5 1,6 2,5 3,5 3,6 4,5 " +
|
||||
"5,5 5,6 6,5; s 0,0 0,1 0,2 0,3 1,1 1,2 1,3 1,5 1,6 2,0 2,1 2,2 2,3 3,0 3,1 3,2 3,3 3,5 3,6 4,0 4,1 " +
|
||||
"4,2 4,3 5,1 5,2 5,3 5,5 5,6 6,0 6,1 6,2 6,3; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
public static final String SPACE_INVADERS_GAME = "a 23 2; c 0 E; i 6 0,2 0,7 1,3 1,7 2,2 2,3 2,4 2,5 2,6 2,7 " +
|
||||
"3,2 3,4 3,5 3,6 3,8 4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9 5,0 5,1 5,3 5,4 5,5 5,6 5,7 5,9 5,10 6,0 " +
|
||||
"6,2 6,7 6,9 7,3 7,4 7,6 7,7; i 6 0,14 0,19 1,15 1,19 2,14 2,15 2,16 2,17 2,18 2,19 3,14 3,16 3,17 3,18 " +
|
||||
"3,20 4,12 4,13 4,14 4,15 4,16 4,17 4,18 4,19 4,20 4,21 5,12 5,13 5,15 5,16 5,17 5,18 5,19 5,21 5,22 " +
|
||||
"6,12 6,14 6,19 6,21 7,15 7,16 7,18 7,19; i 6 17,9 18,8 18,9 19,6 19,7 19,8 19,9 19,10 19,11 19,12 20,5 " +
|
||||
"20,6 20,7 20,8 20,9 20,10 20,11 20,12 21,5 21,6 21,7 21,8 21,9 21,10 21,11 21,12 21,13 22,5 22,6 22,7 " +
|
||||
"22,8 22,9 22,10 22,11 22,12; i 8 12,3 12,5 13,3 13,4 13,5 13,6 14,1 14,2 14,3 14,4 14,5 15,1 15,2 15,3 " +
|
||||
"16,1 16,2; i 8 12,17 12,18 12,19 13,17 13,18 13,19 13,20 14,17 14,18 14,19 14,20 15,19 15,20 15,21 16,19 " +
|
||||
"16,20; i 8 13,14 14,13 14,14 15,13 15,14 15,15 16,13 16,14; i 8 14,7 15,7 15,8 16,7; i 10 8,9 9,9 10,9 " +
|
||||
"11,9; i 10 8,12 9,13 10,12 11,13; i 10 9,1 10,1 11,1 12,1; i 10 9,22 10,21 11,22 12,21; i 10 13,10 14,10 " +
|
||||
"15,10; i 10 17,0 18,0 19,0 20,0; i 10 17,16 18,16 19,16 20,16; s 0,2 0,7 0,14 0,19 3,5 3,17 6,0 6,9 6,12 " +
|
||||
"6,21 7,4 7,6 7,16 7,18 11,9 11,13 12,1 12,19 12,21 13,10 15,2 15,8 15,14 15,20 17,9 18,8 18,9 20,0 20,16 " +
|
||||
"21,6 21,9 21,12; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
}
|
@ -24,6 +24,7 @@ public class Player {
|
||||
private Coord[] settlers;
|
||||
private Coord[] villages;
|
||||
private Coord lastMove;
|
||||
private Boolean isAI;
|
||||
|
||||
/**
|
||||
* Constructor for Player class
|
||||
@ -40,6 +41,7 @@ public class Player {
|
||||
this.numStatuette = 0;
|
||||
this.settlers = new Coord[0];
|
||||
this.villages = new Coord[0];
|
||||
this.isAI = false;
|
||||
lastMove = new Coord(-1, -1);
|
||||
}
|
||||
// endregion
|
||||
@ -75,20 +77,14 @@ public class Player {
|
||||
* @return int number of the resource the player has
|
||||
*/
|
||||
public int getNumResource(char resourceType) {
|
||||
switch (resourceType) {
|
||||
case 'C':
|
||||
return numCoconuts;
|
||||
case 'B':
|
||||
return numBamboo;
|
||||
case 'W':
|
||||
return numWater;
|
||||
case 'P':
|
||||
return numPreciousStones;
|
||||
case 'S':
|
||||
return numStatuette;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return switch (resourceType) {
|
||||
case 'C' -> numCoconuts;
|
||||
case 'B' -> numBamboo;
|
||||
case 'W' -> numWater;
|
||||
case 'P' -> numPreciousStones;
|
||||
case 'S' -> numStatuette;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,21 +94,11 @@ public class Player {
|
||||
*/
|
||||
public void addResource(int numResource, char resourceType) {
|
||||
switch (resourceType) {
|
||||
case 'C':
|
||||
numCoconuts += numResource;
|
||||
break;
|
||||
case 'B':
|
||||
numBamboo += numResource;
|
||||
break;
|
||||
case 'W':
|
||||
numWater += numResource;
|
||||
break;
|
||||
case 'P':
|
||||
numPreciousStones += numResource;
|
||||
break;
|
||||
case 'S':
|
||||
numStatuette += numResource;
|
||||
break;
|
||||
case 'C' -> numCoconuts += numResource;
|
||||
case 'B' -> numBamboo += numResource;
|
||||
case 'W' -> numWater += numResource;
|
||||
case 'P' -> numPreciousStones += numResource;
|
||||
case 'S' -> numStatuette += numResource;
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,9 +137,7 @@ public class Player {
|
||||
*/
|
||||
public void addSettler(Coord coord) {
|
||||
Coord[] newSettlers = new Coord[settlers.length + 1];
|
||||
for (int i = 0; i < settlers.length; i++) {
|
||||
newSettlers[i] = settlers[i];
|
||||
}
|
||||
System.arraycopy(settlers, 0, newSettlers, 0, settlers.length);
|
||||
newSettlers[settlers.length] = coord;
|
||||
settlers = newSettlers;
|
||||
lastMove = coord;
|
||||
@ -170,9 +154,7 @@ public class Player {
|
||||
}
|
||||
|
||||
Coord[] newVillages = new Coord[villages.length + 1];
|
||||
for (int i = 0; i < villages.length; i++) {
|
||||
newVillages[i] = villages[i];
|
||||
}
|
||||
System.arraycopy(villages, 0, newVillages, 0, villages.length);
|
||||
newVillages[villages.length] = coord;
|
||||
villages = newVillages;
|
||||
lastMove = coord;
|
||||
@ -191,9 +173,9 @@ public class Player {
|
||||
public void removeVillage(Coord coord) {
|
||||
Coord[] newVillages = new Coord[villages.length - 1];
|
||||
int j = 0;
|
||||
for (int i = 0; i < villages.length; i++) {
|
||||
if (villages[i] != coord) {
|
||||
newVillages[j] = villages[i];
|
||||
for (Coord village : villages) {
|
||||
if (village != coord) {
|
||||
newVillages[j] = village;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
@ -207,18 +189,14 @@ public class Player {
|
||||
*/
|
||||
public Coord[] getPieces() {
|
||||
Coord[] pieces = new Coord[settlers.length + villages.length];
|
||||
for (int i = 0; i < settlers.length; i++) {
|
||||
pieces[i] = settlers[i];
|
||||
}
|
||||
for (int i = 0; i < villages.length; i++) {
|
||||
pieces[settlers.length + i] = villages[i];
|
||||
}
|
||||
System.arraycopy(settlers, 0, pieces, 0, settlers.length);
|
||||
System.arraycopy(villages, 0, pieces, settlers.length, villages.length);
|
||||
return pieces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of pieces on island
|
||||
* @param island Island island to check
|
||||
* @param island Island to check
|
||||
* @return int number of pieces on island
|
||||
*/
|
||||
public int getNumPiecesOnIsland(Island island) {
|
||||
@ -231,10 +209,31 @@ public class Player {
|
||||
return numPieces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player's last move coord
|
||||
* @return Coord last move coord
|
||||
*/
|
||||
public Coord getLastMove() {
|
||||
return lastMove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the player is an AI
|
||||
* @param ai boolean true if player is an AI, false otherwise
|
||||
*/
|
||||
public void setAI(boolean ai) {
|
||||
this.isAI = ai;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player is an AI
|
||||
* @return boolean true if player is an AI, false otherwise
|
||||
*/
|
||||
public boolean isAI() {
|
||||
return isAI;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if player is able to do any moves
|
||||
* @return true if player can do any moves, false otherwise
|
||||
@ -242,15 +241,14 @@ public class Player {
|
||||
public boolean canPlay(State state) {
|
||||
|
||||
// Check if the player has placed all their settlers or villages
|
||||
int startNumSettlers = switch (state.getNumPlayers()) {
|
||||
case 2 -> 30;
|
||||
case 3 -> 25;
|
||||
case 4 -> 20;
|
||||
default -> 0;
|
||||
};
|
||||
boolean hasSettler = (settlers.length < startNumSettlers);
|
||||
boolean hasVillage = (settlers.length < 5);
|
||||
if (!hasSettler && !(hasVillage && state.getCurrentPhase() == 'E')) return false;
|
||||
int numSettlers = 30 - ((state.getNumPlayers() - 2) * 5);
|
||||
boolean hasSettler = (settlers.length < numSettlers);
|
||||
boolean hasVillage = (villages.length < 5);
|
||||
if (!hasSettler && !hasVillage) return false;
|
||||
// if (state.getCurrentPhase() != 'E'){
|
||||
// if (!hasSettler && !hasVillage) return false;
|
||||
// }
|
||||
|
||||
|
||||
// Add used coords
|
||||
ArrayList<String> settlerCoords = new ArrayList<>(); // Placed Settler Coordinates
|
||||
@ -266,7 +264,6 @@ public class Player {
|
||||
villageCoords.add(c.toString());
|
||||
}
|
||||
}
|
||||
|
||||
for (Coord c: settlers){
|
||||
playerSettlerCoords.add(c.toString());
|
||||
}
|
||||
@ -306,24 +303,13 @@ public class Player {
|
||||
else if(y > state.boardHeight - 1) continue;
|
||||
switch (state.getCurrentPhase()) {
|
||||
case 'E' -> {
|
||||
if (!islandCoords.contains(cord)) {
|
||||
if (hasSettler) return true;
|
||||
break;
|
||||
}
|
||||
// If the Village is being placed on the sea return false
|
||||
if ((isAdjacent(cord, playerVillageCoords) || isAdjacent(cord, playerSettlerCoords))) {
|
||||
// Add the move to the set
|
||||
if (hasVillage) return true;
|
||||
if (hasSettler) return true;
|
||||
}
|
||||
if (!islandCoords.contains(cord) && hasSettler) return true;
|
||||
if ((isAdjacent(cord, playerVillageCoords) || isAdjacent(cord, playerSettlerCoords))) return true;
|
||||
}
|
||||
// Settlement Phase
|
||||
case 'S' -> {
|
||||
// if the settler is not adjacent with any of the pieces return false
|
||||
if ((isAdjacent(cord, playerVillageCoords) || isAdjacent(cord, playerSettlerCoords))) {
|
||||
// Add the move to the set
|
||||
if (hasSettler) return true;
|
||||
}
|
||||
// if the settler is adjacent with any of the pieces return true
|
||||
if ((isAdjacent(cord, playerVillageCoords) || isAdjacent(cord, playerSettlerCoords)) && hasSettler) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -353,9 +339,9 @@ public class Player {
|
||||
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);
|
||||
int y = Integer.parseInt(coordStr.split(",")[0]);
|
||||
int x = Integer.parseInt(coordStr.split(",")[1]);
|
||||
Coord coord = new Coord(y, x);
|
||||
lastMove = coord;
|
||||
state.placePiece(coord, pieceType);
|
||||
state.nextPlayer();
|
||||
@ -399,17 +385,22 @@ public class Player {
|
||||
/**
|
||||
* Do a calculated move
|
||||
*/
|
||||
public void doAIMove(State state){
|
||||
public Boolean doAIMove(State state){
|
||||
|
||||
String bestMove = createAIMove(state);
|
||||
if (bestMove.equals("")){
|
||||
System.out.println("No AI moves");
|
||||
return false;
|
||||
}
|
||||
char pieceType = bestMove.charAt(0);
|
||||
String coordStr = bestMove.substring(2);
|
||||
int x = Integer.parseInt(coordStr.split(",")[0]);
|
||||
int y = Integer.parseInt(coordStr.split(",")[1]);
|
||||
Coord coord = new Coord(x, y);
|
||||
int y = Integer.parseInt(coordStr.split(",")[0]);
|
||||
int x = Integer.parseInt(coordStr.split(",")[1]);
|
||||
Coord coord = new Coord(y, x);
|
||||
lastMove = coord;
|
||||
state.placePiece(coord, pieceType);
|
||||
state.nextPlayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -447,7 +438,6 @@ public class Player {
|
||||
}
|
||||
// Check if adding this piece will make player have the most pieces on the island
|
||||
int ties = 0;
|
||||
int wins = 0;
|
||||
int loses = 0;
|
||||
int myPieces = this.getNumPiecesOnIsland(island);
|
||||
for (int i = 0; i < state.getNumPlayers(); i++) {
|
||||
@ -457,9 +447,6 @@ public class Player {
|
||||
int otherPlayerPieces = state.getPlayer(i).getNumPiecesOnIsland(island);
|
||||
if (otherPlayerPieces > myPieces+1) {
|
||||
loses++;
|
||||
} else
|
||||
if (otherPlayerPieces == myPieces) {
|
||||
wins++;
|
||||
} else if (otherPlayerPieces == myPieces + 1) {
|
||||
ties++;
|
||||
}
|
||||
@ -480,10 +467,10 @@ public class Player {
|
||||
if (currentIslandCount < 8 ){
|
||||
// Check if there is an island adjacent to this move
|
||||
for (Island island : state.getIslands()) {
|
||||
if (island.containsCoord(new Coord(coord.getX() + 1, coord.getY()))
|
||||
|| island.containsCoord(new Coord(coord.getX() - 1, coord.getY()))
|
||||
|| island.containsCoord(new Coord(coord.getX(), coord.getY() + 1))
|
||||
|| island.containsCoord(new Coord(coord.getX(), coord.getY() - 1))) {
|
||||
if (island.containsCoord(new Coord(coord.x() + 1, coord.y()))
|
||||
|| island.containsCoord(new Coord(coord.x() - 1, coord.y()))
|
||||
|| island.containsCoord(new Coord(coord.x(), coord.y() + 1))
|
||||
|| island.containsCoord(new Coord(coord.x(), coord.y() - 1))) {
|
||||
score += 1;
|
||||
if (state.getCurrentPhase() == 'E'){
|
||||
score += 4;
|
||||
@ -506,8 +493,8 @@ public class Player {
|
||||
private int maxCol(Coord[] coords){
|
||||
int maxCol = 0;
|
||||
for (Coord coord : coords) {
|
||||
if (coord.getX() > maxCol) {
|
||||
maxCol = coord.getX();
|
||||
if (coord.x() > maxCol) {
|
||||
maxCol = coord.x();
|
||||
}
|
||||
}
|
||||
return maxCol;
|
||||
@ -545,7 +532,7 @@ public class Player {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = "p " + playerID + " " + score + " " + numCoconuts + " " + numBamboo + " " + numWater + " " + numPreciousStones + " " + numStatuette + " S";
|
||||
StringBuilder str = new StringBuilder("p " + playerID + " " + score + " " + numCoconuts + " " + numBamboo + " " + numWater + " " + numPreciousStones + " " + numStatuette + " S");
|
||||
|
||||
|
||||
// Get the coords of the player's pieces in row major order
|
||||
@ -558,7 +545,7 @@ public class Player {
|
||||
|
||||
while (settlersCoords[settlers.length - 1] == null) {
|
||||
for (Coord coord : settlers) {
|
||||
if (coord.getX() == col && coord.getY() == row) {
|
||||
if (coord.x() == col && coord.y() == row) {
|
||||
settlersCoords[i] = coord;
|
||||
i++;
|
||||
}
|
||||
@ -580,7 +567,7 @@ public class Player {
|
||||
|
||||
while (villagesCoords[villages.length-1] == null){
|
||||
for (Coord coord : villages) {
|
||||
if (coord.getX() == col && coord.getY() == row) {
|
||||
if (coord.x() == col && coord.y() == row) {
|
||||
villagesCoords[i] = coord;
|
||||
i++;
|
||||
}
|
||||
@ -597,13 +584,13 @@ public class Player {
|
||||
|
||||
|
||||
for (Coord coord : settlersCoords) {
|
||||
str += " " + coord.toString();
|
||||
str.append(" ").append(coord.toString());
|
||||
|
||||
}
|
||||
str += " T";
|
||||
str.append(" T");
|
||||
for (Coord coord : villagesCoords) {
|
||||
str += " " + coord.toString();
|
||||
str.append(" ").append(coord.toString());
|
||||
}
|
||||
return str;
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package comp1110.ass2;
|
||||
*/
|
||||
public class Resource {
|
||||
private char type;
|
||||
private Coord coord;
|
||||
private final Coord coord;
|
||||
private boolean claimed;
|
||||
|
||||
/**
|
||||
@ -35,20 +35,14 @@ public class Resource {
|
||||
* @return String type of the resource
|
||||
*/
|
||||
public String getTypeString() {
|
||||
switch (type){
|
||||
case 'C':
|
||||
return "Coconut";
|
||||
case 'B':
|
||||
return "Bamboo";
|
||||
case 'W':
|
||||
return "Water";
|
||||
case 'P':
|
||||
return "Precious Stone";
|
||||
case 'S':
|
||||
return "Statuette";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
return switch (type) {
|
||||
case 'C' -> "Coconut";
|
||||
case 'B' -> "Bamboo";
|
||||
case 'W' -> "Water";
|
||||
case 'P' -> "Precious Stone";
|
||||
case 'S' -> "Statuette";
|
||||
default -> "Invalid";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,17 +61,9 @@ public class Resource {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the coordinate of the resource
|
||||
* @param coord Coord coordinate of the resource
|
||||
*/
|
||||
public void setCoord(Coord coord) {
|
||||
this.coord = coord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the resource is equal to another resource
|
||||
* @param resource Resource resource to be compared
|
||||
* @param resource resource to be compared
|
||||
* @return boolean true if the resources are equal
|
||||
*/
|
||||
public boolean equals(Resource resource) {
|
||||
@ -96,8 +82,8 @@ public class Resource {
|
||||
* Check if the resource has been claimed
|
||||
* @return boolean true if the resource has been claimed
|
||||
*/
|
||||
public boolean isClaimed() {
|
||||
return this.claimed;
|
||||
public boolean isAvailable() {
|
||||
return !this.claimed;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,6 @@
|
||||
package comp1110.ass2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Object to store the game state
|
||||
@ -77,9 +75,8 @@ public class State {
|
||||
islandcount++;
|
||||
// Add the island to the array
|
||||
Island[] tmpislands = new Island[islandcount];
|
||||
for (int j=0; j<tmpislands.length-1; j++)
|
||||
{
|
||||
tmpislands[j] = islands[j];
|
||||
if (islands != null) {
|
||||
System.arraycopy(islands, 0, tmpislands, 0, tmpislands.length - 1);
|
||||
}
|
||||
tmpislands[islandcount-1] = tmpIsland;
|
||||
islands = tmpislands;
|
||||
@ -152,10 +149,7 @@ public class State {
|
||||
if (numPlayers >= maxPlayers) return; // There are already the maximum number of players
|
||||
Player[] oldPlayers = players;
|
||||
players = new Player[numPlayers+1];
|
||||
for (int i=0; i<numPlayers; i++)
|
||||
{
|
||||
players[i] = oldPlayers[i];
|
||||
}
|
||||
if (numPlayers >= 0) System.arraycopy(oldPlayers, 0, players, 0, numPlayers);
|
||||
players[numPlayers] = new Player(numPlayers);
|
||||
numPlayers++;
|
||||
}
|
||||
@ -181,7 +175,7 @@ public class State {
|
||||
// Create a temporary array to store the shuffled stone circles
|
||||
Coord[] tempStoneCircleRandom = new Coord[32];
|
||||
// Create a list to store the used cords (to avoid duplicates)
|
||||
List<Coord> usedCords = new ArrayList<Coord>();
|
||||
List<Coord> usedCords = new ArrayList<>();
|
||||
|
||||
// Shuffle the array
|
||||
for (int j = 0; j < 32; j++) {
|
||||
@ -339,9 +333,7 @@ public class State {
|
||||
}
|
||||
}
|
||||
Resource[] resources = new Resource[i];
|
||||
for (int j=0; j<i; j++) {
|
||||
resources[j] = tmpResources[j];
|
||||
}
|
||||
System.arraycopy(tmpResources, 0, resources, 0, i);
|
||||
return resources;
|
||||
}
|
||||
|
||||
@ -392,7 +384,7 @@ public class State {
|
||||
// Claim resource if it is a stone circle
|
||||
if (isStone(coord)) {
|
||||
for (Resource resource : resources) {
|
||||
if (resource.getCoord().equals(coord) && !resource.isClaimed()) {
|
||||
if (resource.getCoord().equals(coord) && resource.isAvailable()) {
|
||||
players[currentPlayer].addResource(1, resource.getType());
|
||||
resource.setClaimed();
|
||||
}
|
||||
@ -414,31 +406,21 @@ public class State {
|
||||
|
||||
/**
|
||||
* is the phase over?
|
||||
* Defaults to simple mode
|
||||
*/
|
||||
public boolean isPhaseOver() {
|
||||
return isPhaseOver(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* is the phase over?
|
||||
* @param simple boolean don't check all player moves
|
||||
*/
|
||||
public boolean isPhaseOver(boolean simple){
|
||||
boolean resourcesLeft = false;
|
||||
for (Resource r : resources) {
|
||||
if (!r.isClaimed() && r.getType() != 'S') resourcesLeft = true;
|
||||
if (r.isAvailable() && r.getType() != 'S') resourcesLeft = true;
|
||||
}
|
||||
|
||||
boolean moveLeft = false;
|
||||
if (simple) {
|
||||
if (getCurrentPlayer().canPlay(this)) moveLeft = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Player player : players) {
|
||||
if (player.canPlay(this)) moveLeft = true;
|
||||
int numSettlers = 30 - ((numPlayers - 2) * 5);
|
||||
for (Player p: players) {
|
||||
boolean canPlay = p.getVillages().length < 5;
|
||||
if (p.getSettlers().length < numSettlers) canPlay = true;
|
||||
if (canPlay) {
|
||||
if (p.canPlay(this)) moveLeft = true;
|
||||
}
|
||||
|
||||
}
|
||||
return !resourcesLeft || !moveLeft;
|
||||
}
|
||||
@ -568,215 +550,100 @@ public class State {
|
||||
* @return int score
|
||||
*/
|
||||
|
||||
// public boolean isAdjacent(Coord coord) {
|
||||
// if (this.y == coord.y) {
|
||||
// return (this.x == coord.x - 1 || this.x == coord.x + 1);
|
||||
// }
|
||||
// if (this.x == coord.x) {
|
||||
// return (this.y == coord.y - 1 || this.y == coord.y + 1);
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Check if two coordinates are adjacent (includes diagonals)
|
||||
// * @param coord Coord object to compare to
|
||||
// */
|
||||
// public boolean isAdjacentDiagonal(Coord coord){
|
||||
// if (isAdjacent(coord)) return true;
|
||||
// if (this.x == coord.x - 1 && this.y == coord.y - 1) return true;
|
||||
// if (this.x == coord.x - 1 && this.y == coord.y + 1) return true;
|
||||
// if (this.x == coord.x + 1 && this.y == coord.y - 1) return true;
|
||||
// return (this.x == coord.x + 1 && this.y == coord.y + 1);
|
||||
// }
|
||||
|
||||
// public Player(int playerID) {
|
||||
// this.playerID = playerID;
|
||||
// this.score = 0;
|
||||
// this.numCoconuts = 0;
|
||||
// this.numBamboo = 0;
|
||||
// this.numWater = 0;
|
||||
// this.numPreciousStones = 0;
|
||||
// this.numStatuette = 0;
|
||||
// this.settlers = new Coord[0];
|
||||
// this.villages = new Coord[0];
|
||||
// }
|
||||
// // endregion
|
||||
// // region Getters and Setters
|
||||
//
|
||||
// /**
|
||||
// * Get the player's ID
|
||||
// * @return int player ID
|
||||
// */
|
||||
// public int getPlayerID() {
|
||||
// return playerID;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Get the player's settlers
|
||||
// * @return Coord[] list of the player's settlers coords
|
||||
// */
|
||||
// public Coord[] getSettlers() {
|
||||
// return settlers;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get the player's villages
|
||||
// * @return Coord[] list of the player's villages coords
|
||||
// */
|
||||
// public Coord[] getVillages() {
|
||||
// return villages;
|
||||
// }
|
||||
|
||||
// public Coord[] getPieces() {
|
||||
// Coord[] pieces = new Coord[settlers.length + villages.length];
|
||||
// for (int i = 0; i < settlers.length; i++) {
|
||||
// pieces[i] = settlers[i];
|
||||
// }
|
||||
// for (int i = 0; i < villages.length; i++) {
|
||||
// pieces[settlers.length + i] = villages[i];
|
||||
// }
|
||||
// return pieces;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get number of pieces on island
|
||||
// * @param island Island island to check
|
||||
// * @return int number of pieces on island
|
||||
// */
|
||||
// public int getNumPiecesOnIsland(Island island) {
|
||||
// int numPieces = 0;
|
||||
// for (Coord piece : getPieces()) {
|
||||
// if (island.containsCoord(piece)) {
|
||||
// numPieces++;
|
||||
// }
|
||||
// }
|
||||
// return numPieces;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Get the coordinates of the island
|
||||
// * @return Coord[] coordinates of the island
|
||||
// */
|
||||
// public Coord[] getCoords() {
|
||||
// return coords;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Check if the island contains a coordinate
|
||||
// * @param coord the coordinate to be checked
|
||||
// * @return boolean true if the island contains the coordinate
|
||||
// */
|
||||
// public boolean containsCoord(Coord coord) {
|
||||
// for (Coord c : this.coords) {
|
||||
// if (c.equals(coord)) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
public int scoreLinks(int playerID) {
|
||||
int maxIslands = 0;
|
||||
int distinctIslandsCounter = 0;
|
||||
int score = 0;
|
||||
Coord[] playerCoords = players[playerID].getPieces();
|
||||
Set<Coord> playerCoordsSet = new HashSet<>(Arrays.asList(playerCoords));
|
||||
return findLongestLinkScore(playerCoordsSet, islands);
|
||||
}
|
||||
|
||||
Coord[] playerCoords = players[playerID].getPieces(); // playerCoords
|
||||
/**
|
||||
* Combines both the helper methods `DFSRecurssionLink` and `findScoreForLink` to find the link set that has the
|
||||
* highest score from a set all Player's pieces coordinates
|
||||
* @param allCoords all coordinates of a Player's pieces
|
||||
* @param islands the set of islands from the generated world
|
||||
* @return the highest score from a player's linked pieces
|
||||
*/
|
||||
public static int findLongestLinkScore ( Set<Coord> allCoords, Island[] islands) {
|
||||
Set<Coord> longestPath = new HashSet<>(); // Container for Longest Path
|
||||
Set<Coord> currentPath = new HashSet<>(); // Container for Current Path
|
||||
|
||||
for(Island island : islands) {
|
||||
Coord[] islandCoords = island.getCoords();
|
||||
Coord startingPoint; // Starting point of the DFS Algo
|
||||
int maxScore = findScoreForLink(longestPath,islands);
|
||||
|
||||
for ( Coord playerCoord : playerCoords ) {
|
||||
if (island.containsCoord(playerCoord)) {
|
||||
for(Island i : islands) {
|
||||
for ( Coord c : allCoords) {
|
||||
if(i.containsCoord(c)) {
|
||||
|
||||
startingPoint = c; // set starting Point with the current Coords in the Player's all pieces coords
|
||||
|
||||
// DFS Algo starts
|
||||
currentPath.add(startingPoint);
|
||||
DFSRecursionLink(allCoords, currentPath, longestPath, startingPoint);
|
||||
|
||||
// if the score is bigger, update the Set
|
||||
if(findScoreForLink(currentPath, islands) > maxScore) {
|
||||
longestPath.clear();
|
||||
longestPath.addAll(currentPath);
|
||||
|
||||
maxScore = findScoreForLink(longestPath, islands);
|
||||
}
|
||||
|
||||
// clear the currentPath as well
|
||||
currentPath = new HashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
// for(Island island : islands) {
|
||||
// Coord[] islandCoords = island.getCoords(); // Island Coords
|
||||
//
|
||||
// for ( Coord playerCoord : playerCoords) {
|
||||
// for( Coord islandCoord : islandCoords) {
|
||||
// if (playerCoord.areTwoCoordsLink(islandCoord) && )
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
return maxIslands * 5; //! TODO
|
||||
return maxScore;
|
||||
}
|
||||
|
||||
// public boolean areTwoCoordsLink ( Coord coord) {
|
||||
// if(isAdjacent(coord) || isAdjacentDiagonal(coord)) return true;
|
||||
// else return false;
|
||||
// }
|
||||
//
|
||||
// public Coord[] longestLink ( Coord coord) {
|
||||
// ArrayList<Coord> linkContainer = new ArrayList<>();
|
||||
// if (areTwoCoordsLink(coord)) {
|
||||
// linkContainer.add(coord);
|
||||
// }
|
||||
//
|
||||
// Coord[] endLinkContainer = new Coord[linkContainer.size()];
|
||||
// return endLinkContainer;
|
||||
// }
|
||||
/**
|
||||
* a DFS (Depth-First-Search) Recursion algorithm that traverses all the coordinates of a player's pieces, with
|
||||
* each step of the DFS algorithm determined if the current coordinate is adjacent with other coordinates
|
||||
* within the allCoords set and wether or not the currentPath is contained inside the allCoords.
|
||||
* @param allCoords all coordinates of a Player's pieces
|
||||
* @param currentPath a set to store the path that the algorithm has gone through
|
||||
* @param longestPath a set to store the longest path
|
||||
* @param startingPoint the starting point of each step of DFS
|
||||
*/
|
||||
public static void DFSRecursionLink(Set<Coord> allCoords, Set<Coord> currentPath, Set<Coord> longestPath, Coord startingPoint) {
|
||||
|
||||
// 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.
|
||||
// Add the staring point to the `history` of the path that has been taken by the algorithm
|
||||
currentPath.add(startingPoint);
|
||||
|
||||
// public int scoreTotalIslands(int playerID) {
|
||||
// int score = 0;
|
||||
// int islandCount = 0;
|
||||
// for (Island island : islands) {
|
||||
// // Get island coords
|
||||
// Coord[] islandCoords = island.getCoords();
|
||||
// // Get player's coords
|
||||
// Coord[] playerCoords = players[playerID].getPieces();
|
||||
// // Check if player has a piece on the island
|
||||
// boolean hasPiece = false;
|
||||
// for (Coord playerCoord : playerCoords) {
|
||||
// for (Coord islandCoord : islandCoords) {
|
||||
// if (playerCoord.equals(islandCoord)) {
|
||||
// hasPiece = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (hasPiece) break;
|
||||
// }
|
||||
// if (hasPiece) islandCount++;
|
||||
// }
|
||||
//
|
||||
// if (islandCount >= 8) score = 20;
|
||||
// else if (islandCount == 7) score = 10;
|
||||
//
|
||||
// return score;
|
||||
// }
|
||||
for(Coord c : allCoords) {
|
||||
|
||||
// public boolean isAdjacent(Coord coord) {
|
||||
// if (this.y == coord.y) {
|
||||
// return (this.x == coord.x - 1 || this.x == coord.x + 1);
|
||||
// }
|
||||
// if (this.x == coord.x) {
|
||||
// return (this.y == coord.y - 1 || this.y == coord.y + 1);
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Check if two coordinates are adjacent (includes diagonals)
|
||||
// * @param coord Coord object to compare to
|
||||
// */
|
||||
// public boolean isAdjacentDiagonal(Coord coord){
|
||||
// if (isAdjacent(coord)) return true;
|
||||
// if (this.x == coord.x - 1 && this.y == coord.y - 1) return true;
|
||||
// if (this.x == coord.x - 1 && this.y == coord.y + 1) return true;
|
||||
// if (this.x == coord.x + 1 && this.y == coord.y - 1) return true;
|
||||
// return (this.x == coord.x + 1 && this.y == coord.y + 1);
|
||||
// }
|
||||
// if the startingPoint of the step is adjacent with the coords from allCoords and currentPath
|
||||
// i.e. the `history tracker` of the path so far does not have `c` coords from allCoords
|
||||
if( startingPoint.isAdjacentDiagonal(c) && !currentPath.contains(c) ) {
|
||||
|
||||
// if the currentPath is bigger than the longestPath, update the longest Path
|
||||
if (currentPath.size() > longestPath.size() ) longestPath = currentPath;
|
||||
|
||||
DFSRecursionLink(allCoords, currentPath, longestPath, c); // Repeat the step for all coords
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for finding the scores for a link set. This helper method is purely to help the
|
||||
* `findLongestLink` method.
|
||||
* @param longestLink the link that wants to be searched the score for
|
||||
* @param islands the islands within the world
|
||||
* @return the score of the link set
|
||||
*/
|
||||
public static int findScoreForLink(Set<Coord> longestLink, Island[] islands) {
|
||||
Set<Island> connectedIslands = new HashSet<>(); // Container for connected Islands within the longest Link set
|
||||
|
||||
for (Coord c : longestLink) {
|
||||
for (Island i : islands) {
|
||||
if (i.containsCoord(c)) {
|
||||
connectedIslands.add(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return connectedIslands.size() * 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Score resources
|
||||
@ -825,42 +692,29 @@ public class State {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = "a " + boardHeight + " " + getNumPlayers() + "; c " + getCurrentPlayerID() + " " + getCurrentPhase() + "; ";
|
||||
StringBuilder str = new StringBuilder("a " + boardHeight + " " + getNumPlayers() + "; c " + getCurrentPlayerID() + " " + getCurrentPhase() + "; ");
|
||||
for (Island island : islands) {
|
||||
str += island.toString() + " ";
|
||||
str.append(island.toString()).append(" ");
|
||||
}
|
||||
str += "s";
|
||||
str.append("s");
|
||||
for (Coord s: stonesCoords) {
|
||||
str += " " + s.toString();
|
||||
str.append(" ").append(s.toString());
|
||||
}
|
||||
str += "; r";
|
||||
str.append("; r");
|
||||
|
||||
char[] types = {'C', 'B', 'W', 'P', 'S'};
|
||||
for (char type : types) {
|
||||
str += " " + type;
|
||||
str.append(" ").append(type);
|
||||
for (Resource resource : resources) {
|
||||
if (resource.getType() == type && !resource.isClaimed()) str += " " + resource.getCoord().toString();
|
||||
if (resource.getType() == type && resource.isAvailable()) str.append(" ").append(resource.getCoord().toString());
|
||||
}
|
||||
}
|
||||
str += ";";
|
||||
str.append(";");
|
||||
for (Player player : players) {
|
||||
str += " " + player.toString() + ";";
|
||||
str.append(" ").append(player.toString()).append(";");
|
||||
}
|
||||
return str;
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string representation of the score of each player
|
||||
* @return String scoreString
|
||||
*/
|
||||
public String scoreString() {
|
||||
String str = "";
|
||||
for (Player player : players) {
|
||||
str += "Player " + player.getPlayerID() + "'s score is " + player.getScore() + "\n";
|
||||
}
|
||||
return str.substring(0, str.length() - 1);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,9 @@ import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.paint.Color;
|
||||
@ -21,6 +24,8 @@ import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Game extends Application {
|
||||
|
||||
// region Variables
|
||||
@ -32,12 +37,10 @@ public class Game extends Application {
|
||||
String message;
|
||||
Boolean messageError;
|
||||
Coord selectedTile;
|
||||
Boolean AI;
|
||||
private final String DEFAULT_GAME = "a 13 2; c 0 E; i 6 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 1,4 2,0 2,1; i 6 0,5 0,6 0,7 1,6 1,7 1,8 2,6 2,7 2,8 3,7 3,8; i 6 7,12 8,11 9,11 9,12 10,10 10,11 11,10 11,11 11,12 12,10 12,11; i 8 0,9 0,10 0,11 1,10 1,11 1,12 2,10 2,11 3,10 3,11 3,12 4,10 4,11 5,11 5,12; i 8 4,0 5,0 5,1 6,0 6,1 7,0 7,1 7,2 8,0 8,1 8,2 9,0 9,1 9,2; i 8 10,3 10,4 11,0 11,1 11,2 11,3 11,4 11,5 12,0 12,1 12,2 12,3 12,4 12,5; i 10 3,3 3,4 3,5 4,2 4,3 4,4 4,5 5,3 5,4 5,5 5,6 6,3 6,4 6,5 6,6 7,4 7,5 7,6 8,4 8,5; i 10 5,8 5,9 6,8 6,9 7,8 7,9 7,10 8,7 8,8 8,9 9,7 9,8 9,9 10,6 10,7 10,8 11,7 11,8 12,7 12,8; s 0,0 0,5 0,9 1,4 1,8 1,12 2,1 3,5 3,7 3,10 3,12 4,0 4,2 5,9 5,11 6,3 6,6 7,0 7,8 7,12 8,2 8,5 9,0 9,9 10,3 10,6 10,10 11,0 11,5 12,2 12,8 12,11; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
private final String WHEELS_GAME = "a 13 2; c 0 E; i 5 0,1 0,2 0,3 0,4 1,1 1,5 2,0 2,5 3,0 3,6 4,0 4,5 5,1 5,5 6,1 6,2 6,3 6,4; i 5 0,8 0,9 0,10 1,8 1,11 2,7 2,11 3,8 3,11 4,8 4,9 4,10; i 7 8,8 8,9 8,10 9,8 9,11 10,7 10,11 11,8 11,11 12,8 12,9 12,10; i 7 10,0 10,1 10,4 10,5 11,0 11,2 11,3 11,4 11,6 12,0 12,1 12,4 12,5; i 9 2,2 2,3 3,2 3,4 4,2 4,3; i 9 2,9; i 9 6,6 6,7 6,8 6,9 6,10 6,11 7,6 8,0 8,1 8,2 8,3 8,4 8,5; i 9 10,9; s 0,1 0,4 0,10 2,2 2,3 2,9 2,11 3,0 3,2 3,4 3,6 4,2 4,3 4,10 6,1 6,4 6,6 6,11 8,0 8,5 8,8 8,10 10,0 10,5 10,7 10,9 10,11 11,3 12,1 12,4 12,8 12,10; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
private final String FACE_GAME = "a 13 2; c 0 E; i 6 0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 0,10 0,11 1,0 1,12 2,0 2,11 3,0 3,12 4,0 4,11 5,0 5,12 6,0 6,11 7,0 7,12 8,0 8,11 9,0 9,12 10,0 10,11 11,0 11,12 12,0 12,1 12,2 12,3 12,4 12,5 12,6 12,7 12,8 12,9 12,10 12,11; i 6 2,4 2,5 2,6 2,7; i 9 4,4 4,5 4,6 4,7; i 9 6,5 6,6 7,5 7,7 8,5 8,6; i 12 2,2 3,2 3,3 4,2 5,2 5,3 6,2 7,2 7,3; i 12 2,9 3,9 3,10 4,9 5,9 5,10 6,9 7,9 7,10; i 12 9,2 9,10 10,2 10,3 10,4 10,5 10,6 10,7 10,8 10,9; s 0,3 0,8 1,0 1,12 2,2 2,4 2,7 2,9 4,2 4,5 4,6 4,9 5,0 5,12 6,2 6,5 6,6 6,9 8,0 8,5 8,6 8,11 9,2 9,10 10,3 10,5 10,6 10,8 11,0 11,12 12,4 12,7; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
private final String SIDES_GAME = "a 7 2; c 0 E; i 4 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3 3,0 3,1 3,2 3,3 4,0 4,1 4,2 4,3 5,0 5,1 5,2 5,3 6,0 6,1 6,2 6,3; i 20 0,5 1,5 1,6 2,5 3,5 3,6 4,5 5,5 5,6 6,5; s 0,0 0,1 0,2 0,3 1,1 1,2 1,3 1,5 1,6 2,0 2,1 2,2 2,3 3,0 3,1 3,2 3,3 3,5 3,6 4,0 4,1 4,2 4,3 5,1 5,2 5,3 5,5 5,6 6,0 6,1 6,2 6,3; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
private final String SPACE_INVADERS_GAME = "a 23 2; c 0 E; i 6 0,2 0,7 1,3 1,7 2,2 2,3 2,4 2,5 2,6 2,7 3,2 3,4 3,5 3,6 3,8 4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9 5,0 5,1 5,3 5,4 5,5 5,6 5,7 5,9 5,10 6,0 6,2 6,7 6,9 7,3 7,4 7,6 7,7; i 6 0,14 0,19 1,15 1,19 2,14 2,15 2,16 2,17 2,18 2,19 3,14 3,16 3,17 3,18 3,20 4,12 4,13 4,14 4,15 4,16 4,17 4,18 4,19 4,20 4,21 5,12 5,13 5,15 5,16 5,17 5,18 5,19 5,21 5,22 6,12 6,14 6,19 6,21 7,15 7,16 7,18 7,19; i 6 17,9 18,8 18,9 19,6 19,7 19,8 19,9 19,10 19,11 19,12 20,5 20,6 20,7 20,8 20,9 20,10 20,11 20,12 21,5 21,6 21,7 21,8 21,9 21,10 21,11 21,12 21,13 22,5 22,6 22,7 22,8 22,9 22,10 22,11 22,12; i 8 12,3 12,5 13,3 13,4 13,5 13,6 14,1 14,2 14,3 14,4 14,5 15,1 15,2 15,3 16,1 16,2; i 8 12,17 12,18 12,19 13,17 13,18 13,19 13,20 14,17 14,18 14,19 14,20 15,19 15,20 15,21 16,19 16,20; i 8 13,14 14,13 14,14 15,13 15,14 15,15 16,13 16,14; i 8 14,7 15,7 15,8 16,7; i 10 8,9 9,9 10,9 11,9; i 10 8,12 9,13 10,12 11,13; i 10 9,1 10,1 11,1 12,1; i 10 9,22 10,21 11,22 12,21; i 10 13,10 14,10 15,10; i 10 17,0 18,0 19,0 20,0; i 10 17,16 18,16 19,16 20,16; s 0,2 0,7 0,14 0,19 3,5 3,17 6,0 6,9 6,12 6,21 7,4 7,6 7,16 7,18 11,9 11,13 12,1 12,19 12,21 13,10 15,2 15,8 15,14 15,20 17,9 18,8 18,9 20,0 20,16 21,6 21,9 21,12; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
|
||||
int AI;
|
||||
|
||||
Boolean darkMode = false;
|
||||
|
||||
// Store the selected map 0 = default, 1 = wheels, 2 = face, 3 = sides, 4 = space invaders
|
||||
private int game_selected = 0;
|
||||
Boolean game_over;
|
||||
@ -50,12 +53,12 @@ public class Game extends Application {
|
||||
*
|
||||
* @param stage the primary stage for this application, onto which
|
||||
* the application scene can be set.
|
||||
* @throws Exception
|
||||
* @throws Exception if there is an error
|
||||
*/
|
||||
@Override
|
||||
public void start(Stage stage) throws Exception {
|
||||
// Set some variables and create the scene
|
||||
AI = false;
|
||||
AI = 0;
|
||||
selectedTile = new Coord(-1,-1);
|
||||
message = "";
|
||||
messageError = false;
|
||||
@ -68,12 +71,14 @@ public class Game extends Application {
|
||||
// Set some app properties
|
||||
stage.setScene(scene);
|
||||
stage.setTitle("Blue Lagoon");
|
||||
stage.getIcons().add(new javafx.scene.image.Image(Game.class.getResourceAsStream("favicon.png")));
|
||||
stage.getIcons().add(new javafx.scene.image.Image(Objects.requireNonNull(
|
||||
Game.class.getResourceAsStream("favicon.png"))));
|
||||
stage.setResizable(false);
|
||||
|
||||
stage.show();
|
||||
// Create a new game
|
||||
newGame(2);
|
||||
|
||||
scene.setFill(Color.valueOf("#38AEF2"));
|
||||
}
|
||||
|
||||
|
||||
@ -85,35 +90,34 @@ public class Game extends Application {
|
||||
game_over = false;
|
||||
|
||||
// Get selected map
|
||||
switch (game_selected){
|
||||
case 1:
|
||||
currentGame = new State(WHEELS_GAME);
|
||||
break;
|
||||
case 2:
|
||||
currentGame = new State(FACE_GAME);
|
||||
break;
|
||||
case 3:
|
||||
currentGame = new State(SIDES_GAME);
|
||||
break;
|
||||
case 4:
|
||||
currentGame = new State(SPACE_INVADERS_GAME);
|
||||
break;
|
||||
default:
|
||||
currentGame = new State(DEFAULT_GAME);
|
||||
break;
|
||||
String DEFAULT_GAME = GameData.DEFAULT_GAME;
|
||||
switch (game_selected) {
|
||||
case 1 -> currentGame = new State(GameData.WHEELS_GAME);
|
||||
case 2 -> currentGame = new State(GameData.FACE_GAME);
|
||||
case 3 -> currentGame = new State(GameData.SIDES_GAME);
|
||||
case 4 -> currentGame = new State(GameData.SPACE_INVADERS_GAME);
|
||||
default -> currentGame = new State(DEFAULT_GAME);
|
||||
}
|
||||
|
||||
// Add additional players as needed
|
||||
switch (numPlayers){
|
||||
case 3:
|
||||
currentGame.addPlayer();
|
||||
break;
|
||||
case 4:
|
||||
switch (numPlayers) {
|
||||
case 3 -> currentGame.addPlayer();
|
||||
case 4 -> {
|
||||
currentGame.addPlayer();
|
||||
currentGame.addPlayer();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
|
||||
if (AI >= numPlayers){
|
||||
for (int i = 0; i < numPlayers; i++){
|
||||
currentGame.getPlayer(i).setAI(true);
|
||||
}
|
||||
} else if (AI > 0) {
|
||||
for (int i = 0; i < AI; i++){
|
||||
currentGame.getPlayer(i+1).setAI(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Distribute resources
|
||||
@ -121,11 +125,23 @@ public class Game extends Application {
|
||||
|
||||
// Send intro message
|
||||
message = "Welcome to Blue Lagoon\nYou have started a new game for " + numPlayers + " players.";
|
||||
if (AI) message += "\nAI is playing";
|
||||
sendMessage(message);
|
||||
switch (AI){
|
||||
case 0 -> message += "\nAll players are human";
|
||||
case 1 -> message += "\nThere is 1 AI";
|
||||
default -> message += "\nThere are " + AI + " AIs";
|
||||
}
|
||||
message += """
|
||||
|
||||
To place a settler, left click on a tile
|
||||
To place a village, right click on a tile""";
|
||||
sendMessage(message);
|
||||
// Refresh the GUI (render the game)
|
||||
refresh();
|
||||
|
||||
// Play the game if all players are AI
|
||||
if (AI >= numPlayers){
|
||||
AIGame();
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
// region Game Play
|
||||
@ -153,6 +169,9 @@ public class Game extends Application {
|
||||
sendMessage("You have placed all your villages");
|
||||
return;
|
||||
}
|
||||
} else if (currentGame.getCurrentPlayer().getSettlers().length >= (40-(currentGame.getNumPlayers()*5))){
|
||||
sendMessage("You have placed all your settlers");
|
||||
return;
|
||||
}
|
||||
|
||||
// If the move is valid, do it
|
||||
@ -163,11 +182,11 @@ public class Game extends Application {
|
||||
|
||||
// If the move was a stone, send a message about it
|
||||
Coord lastMove = selectedTile;
|
||||
String message = "";
|
||||
StringBuilder message = new StringBuilder();
|
||||
if (currentGame.isStone(lastMove)){
|
||||
for (Resource resource : currentGame.getResources()) {
|
||||
if (resource.getCoord().equals(lastMove) ) {
|
||||
message = "Player " + currentGame.getCurrentPlayerID() +" picked up a " + resource.getTypeString().toLowerCase();
|
||||
message = new StringBuilder("Player " + currentGame.getCurrentPlayerID() + " picked up a " + resource.getTypeString().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -175,12 +194,12 @@ public class Game extends Application {
|
||||
// Go to the next player and if it is an AI, do a move for it
|
||||
currentGame.nextPlayer();
|
||||
selectedTile = new Coord(-1,-1);
|
||||
if (AI && currentGame.getCurrentPlayerID() == 1) {
|
||||
message += "\n"+ doAIMove();
|
||||
while (currentGame.getCurrentPlayer().isAI()) {
|
||||
message.append("\n").append(doAIMove());
|
||||
}
|
||||
|
||||
// Send the message to the user
|
||||
sendMessage(message);
|
||||
sendMessage(message.toString());
|
||||
}
|
||||
else {
|
||||
sendMessage("Invalid move",true);
|
||||
@ -193,10 +212,11 @@ public class Game extends Application {
|
||||
if (currentGame.getCurrentPhase() == 'E') {
|
||||
currentGame.cleanBoard();
|
||||
currentGame.distributeResources();
|
||||
if (AI && currentGame.getCurrentPlayerID() == 1){
|
||||
String AI = doAIMove();
|
||||
sendMessage("Next phase!\n" + AI);
|
||||
StringBuilder AI = new StringBuilder();
|
||||
while (currentGame.getCurrentPlayer().isAI()) {
|
||||
AI.append("\n").append(doAIMove());
|
||||
}
|
||||
sendMessage("Next phase!\n" + AI);
|
||||
}
|
||||
else {
|
||||
sendMessage("Game over!",true);
|
||||
@ -215,23 +235,26 @@ public class Game extends Application {
|
||||
String message = "";
|
||||
if (!currentGame.isPhaseOver()){
|
||||
Player player = currentGame.getCurrentPlayer();
|
||||
player.doAIMove(currentGame);
|
||||
if (player.doAIMove(currentGame)) {
|
||||
|
||||
if (currentGame.isPhaseOver()){
|
||||
message = "Starting next phase";
|
||||
}
|
||||
if (!player.getLastMove().equals(new Coord(-1,-1))){
|
||||
Coord lastMove = player.getLastMove();
|
||||
if (currentGame.isStone(lastMove)){
|
||||
for (Resource resource : currentGame.getResources()) {
|
||||
if (resource.getCoord().equals(lastMove) ) {
|
||||
message = "AI picked up a " + resource.getTypeString().toLowerCase();
|
||||
if (currentGame.isPhaseOver()) {
|
||||
message = "Starting next phase";
|
||||
}
|
||||
if (!player.getLastMove().equals(new Coord(-1, -1))) {
|
||||
Coord lastMove = player.getLastMove();
|
||||
if (currentGame.isStone(lastMove)) {
|
||||
for (Resource resource : currentGame.getResources()) {
|
||||
if (resource.getCoord().equals(lastMove)) {
|
||||
message = "AI " + player.getPlayerID() + " picked up " + resource.getTypeString().toLowerCase();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message = "AI " + player.getPlayerID() + " placed at " + lastMove.toString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
message = "AI placed at " + lastMove.toString();
|
||||
}
|
||||
} else {
|
||||
message += "AI " + player.getPlayerID() + " passed";
|
||||
currentGame.nextPlayer();
|
||||
}
|
||||
}
|
||||
if (currentGame.isPhaseOver()){
|
||||
@ -240,10 +263,11 @@ public class Game extends Application {
|
||||
currentGame.cleanBoard();
|
||||
currentGame.distributeResources();
|
||||
currentGame.nextPhase();
|
||||
if (AI && currentGame.getCurrentPlayerID() == 1){
|
||||
String AI = doAIMove();
|
||||
sendMessage("Next phase!\n" + AI);
|
||||
StringBuilder AI = new StringBuilder("Next phase!\n");
|
||||
while (currentGame.getCurrentPlayer().isAI()) {
|
||||
AI.append("\n").append(doAIMove());
|
||||
}
|
||||
message = AI.toString();
|
||||
}
|
||||
else {
|
||||
message = "Game over!";
|
||||
@ -258,19 +282,23 @@ public class Game extends Application {
|
||||
* Do a full AI game. This is good to visualize the AI
|
||||
*/
|
||||
void AIGame(){
|
||||
while (!currentGame.isPhaseOver()){
|
||||
currentGame.getCurrentPlayer().doAIMove(currentGame);
|
||||
while (!game_over){
|
||||
if (!currentGame.getCurrentPlayer().doAIMove(currentGame)){
|
||||
currentGame.nextPlayer();
|
||||
}
|
||||
if (currentGame.isPhaseOver()){
|
||||
if (currentGame.getCurrentPhase() == 'E') {
|
||||
currentGame.scorePhase();
|
||||
currentGame.cleanBoard();
|
||||
currentGame.distributeResources();
|
||||
currentGame.nextPhase();
|
||||
}
|
||||
else {
|
||||
game_over = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
currentGame.scorePhase();
|
||||
currentGame.cleanBoard();
|
||||
currentGame.distributeResources();
|
||||
currentGame.nextPhase();
|
||||
while (!currentGame.isPhaseOver()){
|
||||
currentGame.getCurrentPlayer().doAIMove(currentGame);
|
||||
}
|
||||
currentGame.scorePhase();
|
||||
sendMessage("Game over!",true);
|
||||
game_over = true;
|
||||
refresh();
|
||||
|
||||
}
|
||||
@ -301,15 +329,19 @@ public class Game extends Application {
|
||||
/**
|
||||
* When a tile is clicked, it will be selected
|
||||
* @param coordString the coordinate of the tile
|
||||
* @param button the button that was clicked
|
||||
*/
|
||||
|
||||
private void tileClick(String coordString){
|
||||
|
||||
private void tileClick(String coordString, MouseButton button){
|
||||
int y = Integer.parseInt(coordString.split(",")[0]);
|
||||
int x = Integer.parseInt(coordString.split(",")[1]);
|
||||
|
||||
selectedTile = new Coord(y,x);
|
||||
sendMessage("Tile " + selectedTile.toString() + " selected");
|
||||
|
||||
if (button == MouseButton.PRIMARY) doMove(0);
|
||||
else if (button == MouseButton.SECONDARY) doMove(1);
|
||||
|
||||
selectedTile = new Coord(-1,-1);
|
||||
refresh();
|
||||
}
|
||||
|
||||
@ -318,20 +350,32 @@ public class Game extends Application {
|
||||
* It will clear the whole thing and then render it again
|
||||
*/
|
||||
private void refresh() {
|
||||
|
||||
if (darkMode){
|
||||
// Make the background black of the scene
|
||||
Scene scene = root.getScene();
|
||||
scene.setFill(Color.BLACK);
|
||||
} else {
|
||||
Scene scene = root.getScene();
|
||||
scene.setFill(Color.valueOf("#38AEF2"));
|
||||
}
|
||||
|
||||
|
||||
// When refreshing, it clears the whole thing and update it
|
||||
root.getChildren().clear();
|
||||
root.getChildren().add(controls);
|
||||
|
||||
// Add the message
|
||||
Label messageLabel = new Label(message);
|
||||
messageLabel.setLayoutX(0);
|
||||
messageLabel.setLayoutX(35);
|
||||
messageLabel.setLayoutY(250);
|
||||
messageLabel.setFont(Font.font("Sans Serif",FontWeight.BOLD, 20));
|
||||
if (messageError){
|
||||
messageLabel.setTextFill(Color.RED);
|
||||
}
|
||||
else {
|
||||
messageLabel.setTextFill(Color.BLACK);
|
||||
if (darkMode) messageLabel.setTextFill(Color.WHITE);
|
||||
else messageLabel.setTextFill(Color.BLACK);
|
||||
}
|
||||
|
||||
root.getChildren().add(messageLabel);
|
||||
@ -353,7 +397,7 @@ public class Game extends Application {
|
||||
for(int i = 0; i < boardHeight; i++){
|
||||
for(int j = 0; j < boardHeight - (-1 * i % 2 + 1); j++){
|
||||
addBoardTile(viewerGrid, boardHeightPx/boardHeight,
|
||||
String.format("%s,%s", i, j), Color.DARKBLUE);
|
||||
String.format("%s,%s", i, j), Color.valueOf("#387CFF"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,23 +407,19 @@ public class Game extends Application {
|
||||
// Getting the two mode of current state either Exploration
|
||||
// or settler
|
||||
char currentPhaseChar = currentGame.getCurrentPhase();
|
||||
String currentPhase = "";
|
||||
switch (currentPhaseChar) {
|
||||
case 'E':
|
||||
currentPhase = "Exploration";
|
||||
break;
|
||||
case 'S':
|
||||
currentPhase = "Settlement";
|
||||
break;
|
||||
}
|
||||
String currentPhase = switch (currentPhaseChar) {
|
||||
case 'E' -> "Exploration";
|
||||
case 'S' -> "Settlement";
|
||||
default -> "";
|
||||
};
|
||||
|
||||
// Making the Current State Statement text on the window
|
||||
Text currentStateText = new Text();
|
||||
currentStateText.setText("The current player to move is player " +
|
||||
playerId + "\nCurrent Phase: " + currentPhase);
|
||||
currentStateText.setFont(Font.font("Sans Serif", FontWeight.BOLD, 20));
|
||||
currentStateText.setX(WINDOW_WIDTH / 2 + (WINDOW_WIDTH/5) - 175);
|
||||
currentStateText.setY(25);
|
||||
currentStateText.setX((double) WINDOW_WIDTH / 2 + ((double) WINDOW_WIDTH /5) - 175);
|
||||
currentStateText.setY(30);
|
||||
currentStateText.setTextAlignment(TextAlignment.CENTER);
|
||||
root.getChildren().add(currentStateText);
|
||||
currentStateText.setFill(Color.GREEN);
|
||||
@ -387,7 +427,7 @@ public class Game extends Application {
|
||||
// For each island render the island
|
||||
for (Island island: currentGame.getIslands()){
|
||||
for (Coord c: island.getCoords()){
|
||||
addBoardTile(viewerGrid, tileSize, c.toString(), Color.GREEN);
|
||||
addBoardTile(viewerGrid, tileSize, c.toString(), Color.valueOf("#64CA00"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,14 +435,13 @@ public class Game extends Application {
|
||||
for (Coord stoneCircle: currentGame.getStones()){
|
||||
addStoneTileToBoard(viewerGrid, tileSize, stoneCircle.toString(), Color.GRAY);
|
||||
}
|
||||
|
||||
String playerData = "Scores:";
|
||||
StringBuilder playerData = new StringBuilder("Scores:");
|
||||
// For each player add their settlements and roads
|
||||
for (int i = 0; i < currentGame.getNumPlayers(); i++){
|
||||
Player currentPlayer = currentGame.getPlayer(i);
|
||||
// Add the player's score to the playerData string
|
||||
if (AI && i == 1) playerData += "\nAI: " + currentPlayer.getScore();
|
||||
else playerData += "\nPlayer " + i + ": " + currentPlayer.getScore();
|
||||
if (currentPlayer.isAI()) playerData.append("\nAI ").append(i).append(": ").append(currentPlayer.getScore());
|
||||
else playerData.append("\nPlayer ").append(i).append(": ").append(currentPlayer.getScore());
|
||||
|
||||
// Settler tile generator
|
||||
for (Coord c: currentPlayer.getSettlers()){
|
||||
@ -410,7 +449,10 @@ public class Game extends Application {
|
||||
addStoneTileToBoard(viewerGrid, tileSize, c.toString(), Color.PINK);
|
||||
|
||||
// Label generator
|
||||
addLabelToTile(viewerGrid, tileSize, c.toString(), Color.BLACK, "P"+i);
|
||||
if (currentPlayer.isAI())
|
||||
addLabelToTile(viewerGrid, tileSize, c.toString(), Color.GREEN, "AI "+i);
|
||||
else
|
||||
addLabelToTile(viewerGrid, tileSize, c.toString(), Color.BLACK, "P "+i);
|
||||
}
|
||||
// Village tile generator
|
||||
for (Coord c: currentPlayer.getVillages()){
|
||||
@ -418,21 +460,26 @@ public class Game extends Application {
|
||||
addStoneTileToBoard(viewerGrid, tileSize, c.toString(), Color. LIGHTGOLDENRODYELLOW);
|
||||
|
||||
// Label generator
|
||||
addLabelToTile(viewerGrid, tileSize, c.toString(), Color.BLACK, "P"+i);
|
||||
if (currentPlayer.isAI())
|
||||
addLabelToTile(viewerGrid, tileSize, c.toString(), Color.BLACK, "AI "+i);
|
||||
else
|
||||
addLabelToTile(viewerGrid, tileSize, c.toString(), Color.BLACK, "P "+i);
|
||||
}
|
||||
}
|
||||
// Adding the player Statement Text to the window
|
||||
Text playerStateText = new Text();
|
||||
playerStateText.setText(playerData);
|
||||
playerStateText.setText(playerData.toString());
|
||||
playerStateText.setFont(Font.font("Sans Serif", FontWeight.BOLD, 25));
|
||||
playerStateText.setX(0);
|
||||
playerStateText.setX(35);
|
||||
playerStateText.setY(100);
|
||||
playerStateText.setFill(Color.BLACK);
|
||||
|
||||
if (darkMode) playerStateText.setFill(Color.WHITE);
|
||||
else playerStateText.setFill(Color.BLACK);
|
||||
root.getChildren().add(playerStateText);
|
||||
|
||||
// Add the grid to the root
|
||||
viewerGrid.relocate((WINDOW_WIDTH/2-viewerGrid.getPrefWidth()/2) + (WINDOW_WIDTH/5),
|
||||
((WINDOW_HEIGHT+100)/2-viewerGrid.getPrefHeight()/2));
|
||||
viewerGrid.relocate(((double) WINDOW_WIDTH /2-viewerGrid.getPrefWidth()/2) + ((double) WINDOW_WIDTH /5),
|
||||
((double) (WINDOW_HEIGHT + 100) /2-viewerGrid.getPrefHeight()/2));
|
||||
root.getChildren().add(viewerGrid);
|
||||
|
||||
// Add selected tile
|
||||
@ -449,15 +496,52 @@ public class Game extends Application {
|
||||
* It will create the controls variable
|
||||
*/
|
||||
private void makeControls() {
|
||||
Label newLabel = new Label("New Game:");
|
||||
Label newLabel = new Label("Start New Game:");
|
||||
Button twoPlayer = new Button("2 Player");
|
||||
Button threePlayer = new Button("3 Player");
|
||||
Button fourPlayer = new Button("4 Player");
|
||||
Label mapLabel = new Label("Select Map:");
|
||||
Label playLabel = new Label("Place piece:");
|
||||
Button placeVillage = new Button("Village");
|
||||
Button placeSettler = new Button("Settler");
|
||||
CheckBox isAI = new CheckBox("AI");
|
||||
Label aiLabel = new Label("How many AI players:");
|
||||
Label stuckLabel = new Label("Stuck?");
|
||||
Button stuckButton = new Button("Skip my turn");
|
||||
|
||||
// Button styling
|
||||
twoPlayer.setStyle("-fx-padding: 3 10 10 10; -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0; -fx-background-radius: 8; -fx-background-color: linear-gradient(from 0% 93% to 0% 100%, #69CC00 0%, #83CA00 100%), #69CC00, #83CA00, radial-gradient(center 50% 50%, radius 100%, #83CA00, #A1DF00); -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.75) , 4,0,0,1 ); -fx-font-weight: bold; -fx-font-size: 1.0em;");
|
||||
threePlayer.setStyle("-fx-padding: 3 10 10 10; -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0; -fx-background-radius: 8; -fx-background-color: linear-gradient(from 0% 93% to 0% 100%, #69CC00 0%, #83CA00 100%), #69CC00, #83CA00, radial-gradient(center 50% 50%, radius 100%, #83CA00, #A1DF00); -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.75) , 4,0,0,1 ); -fx-font-weight: bold; -fx-font-size: 1.0em;");
|
||||
fourPlayer.setStyle("-fx-padding: 3 10 10 10; -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0; -fx-background-radius: 8; -fx-background-color: linear-gradient(from 0% 93% to 0% 100%, #69CC00 0%, #83CA00 100%), #69CC00, #83CA00, radial-gradient(center 50% 50%, radius 100%, #83CA00, #A1DF00); -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.75) , 4,0,0,1 ); -fx-font-weight: bold; -fx-font-size: 1.0em;");
|
||||
stuckButton.setStyle("-fx-padding: 3 10 10 10; -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0; -fx-background-radius: 8; -fx-background-color: linear-gradient(from 0% 93% to 0% 100%, #a34313 0%, #903b12 100%), #9d4024, #d86e3a, radial-gradient(center 50% 50%, radius 100%, #d86e3a, #c54e2c); -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.75) , 4,0,0,1 ); -fx-font-weight: bold; -fx-font-size: 1.0em;");
|
||||
|
||||
CheckBox darkToggle = new CheckBox("Dark Mode");
|
||||
darkToggle.setSelected(darkMode);
|
||||
|
||||
darkToggle.setOnAction(e -> {
|
||||
darkMode = !darkMode;
|
||||
makeControls();
|
||||
refresh();
|
||||
});
|
||||
|
||||
// Make everything white if dark mode is on
|
||||
if (darkMode) {
|
||||
newLabel.setTextFill(Color.WHITE);
|
||||
mapLabel.setTextFill(Color.WHITE);
|
||||
aiLabel.setTextFill(Color.WHITE);
|
||||
stuckLabel.setTextFill(Color.WHITE);
|
||||
stuckButton.setTextFill(Color.BLACK);
|
||||
twoPlayer.setTextFill(Color.BLACK);
|
||||
threePlayer.setTextFill(Color.BLACK);
|
||||
fourPlayer.setTextFill(Color.BLACK);
|
||||
darkToggle.setTextFill(Color.WHITE);
|
||||
}
|
||||
|
||||
|
||||
// Numeric select for AI
|
||||
ComboBox aiSelector = new ComboBox();
|
||||
aiSelector.getItems().add("0");
|
||||
aiSelector.getItems().add("1");
|
||||
aiSelector.getItems().add("2");
|
||||
aiSelector.getItems().add("3");
|
||||
aiSelector.getItems().add("4");
|
||||
aiSelector.setValue("0");
|
||||
|
||||
// Store the selected map 0 = default, 1 = wheels, 2 = face, 3 = sides, 4 = space invaders
|
||||
ComboBox mapSelector = new ComboBox();
|
||||
@ -468,29 +552,21 @@ public class Game extends Application {
|
||||
mapSelector.getItems().add("Space Invaders");
|
||||
mapSelector.setPromptText("Default");
|
||||
|
||||
// Combobox styling
|
||||
aiSelector.setStyle("-fx-padding: -1 5 5 5; -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0; -fx-background-radius: 8; -fx-background-color: linear-gradient(from 0% 93% to 0% 100%, #69CC00 0%, #83CA00 100%), #69CC00, #83CA00, radial-gradient(center 50% 50%, radius 100%, #83CA00, #A1DF00); -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.75) , 4,0,0,1 ); -fx-font-weight: bold; -fx-font-size: 1.0em;");
|
||||
mapSelector.setStyle("-fx-padding: -1 5 5 5; -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0; -fx-background-radius: 8; -fx-background-color: linear-gradient(from 0% 93% to 0% 100%, #69CC00 0%, #83CA00 100%), #69CC00, #83CA00, radial-gradient(center 50% 50%, radius 100%, #83CA00, #A1DF00); -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.75) , 4,0,0,1 ); -fx-font-weight: bold; -fx-font-size: 1.0em;");
|
||||
|
||||
// Set the map when the map is selected
|
||||
mapSelector.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent event) {
|
||||
switch (mapSelector.getValue().toString()){
|
||||
case "Default":
|
||||
game_selected = 0;
|
||||
break;
|
||||
case "Wheels":
|
||||
game_selected = 1;
|
||||
break;
|
||||
case "Face":
|
||||
game_selected = 2;
|
||||
break;
|
||||
case "Sides":
|
||||
game_selected = 3;
|
||||
break;
|
||||
case "Space Invaders":
|
||||
game_selected = 4;
|
||||
break;
|
||||
default:
|
||||
game_selected = 0;
|
||||
break;
|
||||
switch (mapSelector.getValue().toString()) {
|
||||
case "Default" -> game_selected = 0;
|
||||
case "Wheels" -> game_selected = 1;
|
||||
case "Face" -> game_selected = 2;
|
||||
case "Sides" -> game_selected = 3;
|
||||
case "Space Invaders" -> game_selected = 4;
|
||||
default -> game_selected = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -498,7 +574,7 @@ public class Game extends Application {
|
||||
twoPlayer.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
AI = isAI.isSelected();
|
||||
AI = Integer.parseInt(aiSelector.getValue().toString());
|
||||
newGame(2);
|
||||
}
|
||||
});
|
||||
@ -506,46 +582,38 @@ public class Game extends Application {
|
||||
threePlayer.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
AI = isAI.isSelected();
|
||||
AI = Integer.parseInt(aiSelector.getValue().toString());
|
||||
newGame(3);
|
||||
}
|
||||
});
|
||||
fourPlayer.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
AI = isAI.isSelected();
|
||||
AI = Integer.parseInt(aiSelector.getValue().toString());
|
||||
newGame(4);
|
||||
}
|
||||
});
|
||||
|
||||
placeVillage.setOnAction(new EventHandler<ActionEvent>() {
|
||||
stuckButton.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
doMove(1);
|
||||
currentGame.nextPlayer();
|
||||
StringBuilder message = new StringBuilder("You skipped your turn");
|
||||
while (currentGame.getCurrentPlayer().isAI() && !game_over) {
|
||||
message.append("\n").append(doAIMove());
|
||||
}
|
||||
sendMessage(message.toString());
|
||||
refresh();
|
||||
}
|
||||
});
|
||||
|
||||
placeSettler.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
doMove(0);
|
||||
}
|
||||
});
|
||||
|
||||
// Run AI Game if keypress is a
|
||||
isAI.setOnKeyPressed(event -> {
|
||||
if (event.getCode().toString() == "A"){
|
||||
newGame(currentGame.getNumPlayers());
|
||||
AIGame();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
HBox hb = new HBox();
|
||||
hb.getChildren().addAll(newLabel, twoPlayer,threePlayer,fourPlayer, isAI,mapLabel,mapSelector,playLabel,placeVillage,placeSettler);
|
||||
hb.getChildren().addAll(mapLabel,mapSelector,aiLabel,aiSelector,newLabel, twoPlayer,threePlayer,fourPlayer,
|
||||
stuckLabel,stuckButton,darkToggle);
|
||||
hb.setSpacing(10);
|
||||
hb.setLayoutX(50);
|
||||
hb.setLayoutY(WINDOW_HEIGHT - 50);
|
||||
controls.getChildren().clear();
|
||||
controls.getChildren().add(hb);
|
||||
}
|
||||
|
||||
@ -564,7 +632,7 @@ public class Game extends Application {
|
||||
Hexagon hex = new Hexagon(tileSize, color);
|
||||
|
||||
// if the row is even, translate the tile to the right by tileSize/2
|
||||
if (Integer.parseInt(coords[0]) % 2 == 0) hex.setTranslateX(tileSize/2);
|
||||
if (Integer.parseInt(coords[0]) % 2 == 0) hex.setTranslateX((double) tileSize /2);
|
||||
|
||||
// Translate the whole tile's Y axis downwards so they connect and there's no gap
|
||||
hex.setTranslateY(Integer.parseInt(coords[0]) * -0.25 * tileSize);
|
||||
@ -572,7 +640,7 @@ public class Game extends Application {
|
||||
|
||||
// Add a mouse click event to the tile
|
||||
hex.setOnMouseClicked(event -> {
|
||||
tileClick(coordString);
|
||||
tileClick(coordString,event.getButton());
|
||||
});
|
||||
|
||||
}
|
||||
@ -594,7 +662,7 @@ public class Game extends Application {
|
||||
Hexagon hex = new Hexagon(tileSize2, color);
|
||||
|
||||
// if the row is even, translate the tile to the right by tileSize/2
|
||||
if (Integer.parseInt(coords[0]) % 2 == 0) hex.setTranslateX(tileSize/2);
|
||||
if (Integer.parseInt(coords[0]) % 2 == 0) hex.setTranslateX((double) tileSize /2);
|
||||
// Translate the whole tile's Y axis downwards so they connect and there's no gap
|
||||
hex.setTranslateY(Integer.parseInt(coords[0]) * -0.25 * tileSize);
|
||||
|
||||
@ -604,7 +672,7 @@ public class Game extends Application {
|
||||
|
||||
// Add a mouse click event to the tile
|
||||
hex.setOnMouseClicked(event -> {
|
||||
tileClick(coordString);
|
||||
tileClick(coordString,event.getButton());
|
||||
});
|
||||
}
|
||||
|
||||
@ -625,16 +693,16 @@ public class Game extends Application {
|
||||
newLabel.setFont(Font.font("Sans Serif", 12));
|
||||
|
||||
// Following the tile's pos format
|
||||
if (Integer.parseInt(coords[0]) % 2 == 0) newLabel.setTranslateX(tileSize/2);
|
||||
if (Integer.parseInt(coords[0]) % 2 == 0) newLabel.setTranslateX((double) tileSize /2);
|
||||
newLabel.setTranslateY(Integer.parseInt(coords[0]) * -0.25 * tileSize);
|
||||
|
||||
// Making the label center
|
||||
newLabel.setTranslateX(19.5 + newLabel.getTranslateX());
|
||||
newLabel.setTranslateX(18.5 + newLabel.getTranslateX());
|
||||
board.add(newLabel, Integer.parseInt(coords[1]), Integer.parseInt(coords[0]));
|
||||
|
||||
// Add a mouse click event to the tile
|
||||
newLabel.setOnMouseClicked(event -> {
|
||||
tileClick(coordString);
|
||||
tileClick(coordString,event.getButton());
|
||||
});
|
||||
}
|
||||
|
||||
@ -665,7 +733,7 @@ public class Game extends Application {
|
||||
|
||||
// Adjust the label's position
|
||||
if (Integer.parseInt(coords[0]) % 2 == 0){
|
||||
newLabel.setTranslateX(tileSize/2 + width);
|
||||
newLabel.setTranslateX((double) tileSize /2 + width);
|
||||
} else
|
||||
{
|
||||
newLabel.setTranslateX(width);
|
||||
@ -676,7 +744,7 @@ public class Game extends Application {
|
||||
board.add(newLabel, Integer.parseInt(coords[1]), Integer.parseInt(coords[0]));
|
||||
// Add a mouse click event to the tile
|
||||
newLabel.setOnMouseClicked(event -> {
|
||||
tileClick(coordString);
|
||||
tileClick(coordString,event.getButton());
|
||||
});
|
||||
}
|
||||
|
||||
@ -684,7 +752,7 @@ public class Game extends Application {
|
||||
* A hexagon shape with a given side length and fill.
|
||||
* Used to create the tiles on the board.
|
||||
*/
|
||||
class Hexagon extends Polygon {
|
||||
static class Hexagon extends Polygon {
|
||||
/**
|
||||
* Create a hexagon with a given side length and fill.
|
||||
* @param side double The length of a side of the hexagon.
|
||||
|
@ -30,7 +30,7 @@ public class ApplyMoveTest implements TestMapNamePlayerCount {
|
||||
String result = BlueLagoon.applyMove(game.get(i-2), game.get(i-1));
|
||||
List<String> errors = sc.compare(game.get(i), result);
|
||||
if(errors.size() > 0){
|
||||
Assertions.fail("\n"+"expected: " + game.get(i) + "\nactual: " + result + "\nerrors:\n" + String.join("\n", errors));
|
||||
Assertions.fail("\nError on input game: " + game.get(i-2) + "\nMove: " + game.get(i-1) + "\nexpected: " + game.get(i) + "\nactual: " + result + "\nerrors:\n" + String.join("\n", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class EndPhaseTest implements TestMapNamePlayerCount {
|
||||
String result = BlueLagoon.endPhase(pre.get(i));
|
||||
List<String> errors = sc.compare(post.get(i), result);
|
||||
if(errors.size() > 0){
|
||||
Assertions.fail("\n"+"expected: " + post.get(i) + "\nactual: " + result + "\nerrors:\n" + String.join("\n", errors));
|
||||
Assertions.fail("\nError ending phase on input: " + pre.get(i) + "\nexpected: " + post.get(i) + "\nactual: " + result + "\nerrors:\n" + String.join("\n", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,5 +77,6 @@ public class IsPhaseOverTest implements TestMapNamePlayerCount {
|
||||
for(int game = 0; game < games.size(); game++){
|
||||
testGame(games.get(game), preEndPhase.get(game), solutions.get(game));
|
||||
}
|
||||
testFalse("a 13 2; c 1 S; i 6 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 1,4 2,0 2,1; i 6 0,5 0,6 0,7 1,6 1,7 1,8 2,6 2,7 2,8 3,7 3,8; i 6 7,12 8,11 9,11 9,12 10,10 10,11 11,10 11,11 11,12 12,10 12,11; i 8 0,9 0,10 0,11 1,10 1,11 1,12 2,10 2,11 3,10 3,11 3,12 4,10 4,11 5,11 5,12; i 8 4,0 5,0 5,1 6,0 6,1 7,0 7,1 7,2 8,0 8,1 8,2 9,0 9,1 9,2; i 8 10,3 10,4 11,0 11,1 11,2 11,3 11,4 11,5 12,0 12,1 12,2 12,3 12,4 12,5; i 10 3,3 3,4 3,5 4,2 4,3 4,4 4,5 5,3 5,4 5,5 5,6 6,3 6,4 6,5 6,6 7,4 7,5 7,6 8,4 8,5; i 10 5,8 5,9 6,8 6,9 7,8 7,9 7,10 8,7 8,8 8,9 9,7 9,8 9,9 10,6 10,7 10,8 11,7 11,8 12,7 12,8; s 0,0 0,5 0,9 1,4 1,8 1,12 2,1 3,5 3,7 3,10 3,12 4,0 4,2 5,9 5,11 6,3 6,6 7,0 7,8 7,12 8,2 8,5 9,0 9,9 10,3 10,6 10,10 11,0 11,5 12,2 12,8 12,11; r C 0,5 1,12 10,6 B 0,0 1,4 2,1 6,6 11,5 W 3,7 3,10 4,2 7,12 8,5 P 1,8 3,12 5,9 7,8 9,9 10,10 S 0,9 3,5 4,0 5,11 6,3 7,0 12,8 12,11; p 0 38 2 0 1 0 0 S 7,3 7,4 8,2 8,4 9,0 9,3 9,4 9,5 10,3 T 9,1 9,2 11,4 12,4; p 1 79 1 1 0 0 0 S 10,0 10,1 10,2 11,0 11,1 11,2 11,3 12,2 12,3 T 12,0 12,1;");
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public class PlacePieceTest implements TestMapNamePlayerCount {
|
||||
String result = BlueLagoon.placePiece(game.get(i-2), game.get(i-1));
|
||||
List<String> errors = sc.compare(solutions.get(i / 2 - 1), result);
|
||||
if(errors.size() > 0){
|
||||
Assertions.fail("\n"+"expected: " + solutions.get(i / 2 - 1) + "\nactual: " + result + "\nerrors:\n" + String.join("\n", errors));
|
||||
Assertions.fail("\nError on input game: " + game.get(i-2) + "\nMove: " + game.get(i-1) + "\nexpected: " + solutions.get(i / 2 - 1) + "\nactual: " + result + "\nerrors:\n" + String.join("\n", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user