Compare commits

...

58 Commits

Author SHA1 Message Date
7c8dac2aff
game: Squashed various bugs 2023-05-11 12:36:08 +10:00
Immanuel Alvaro Bhirawa
a19f6e371c Removed some warnings for the whole code
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-10 19:21:52 +10:00
Immanuel Alvaro Bhirawa
bad42dd8e8 Fixed some documentation for Score Link
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-10 19:19:40 +10:00
Justin Ryu
7fcf6d3a1b Game.java changed gui colours
admin: signed F-originality
2023-05-09 22:22:29 +10:00
20e6c9e3c1
admin: F Best Nathan 2023-05-09 14:06:24 +10:00
6f727478be
admin: originality signed Nathan 2023-05-09 14:06:13 +10:00
5ba6fc5d76
game: Added darkmode toggle 2023-05-09 14:06:00 +10:00
1f73ffcab9
admin: Features added feature list 2023-05-09 14:05:47 +10:00
6edfd9266a
game: fixed AI can't play and freezes game bug 2023-05-09 13:37:38 +10:00
Immanuel Alvaro Bhirawa
dd4e360d8e Merge branch 'master' of https://gitlab.cecs.anu.edu.au/u7156831/comp1110-ass2 2023-05-09 10:53:47 +10:00
Immanuel Alvaro Bhirawa
d99b63c82b added some docs for task 13
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 10:53:28 +10:00
55933ae49e
Merge remote-tracking branch 'origin/master' 2023-05-09 10:46:56 +10:00
519e9e840e
player: Fixed canPlay bug 2023-05-09 10:46:51 +10:00
77aaa07984
state: Remove old comment 2023-05-09 10:46:38 +10:00
Immanuel Alvaro Bhirawa
56b29a3301 task 13 optimized for multiple players
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 10:46:24 +10:00
Immanuel Alvaro Bhirawa
bf38979834 Upstream Pull
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 10:32:45 +10:00
Immanuel Alvaro Bhirawa
6da9b06e9b Merge branch 'master' of https://gitlab.cecs.anu.edu.au/comp1110/comp1110-ass2 2023-05-09 10:32:08 +10:00
Immanuel Alvaro Bhirawa
227f4f8e3a Task 13 done with the help of Nathan
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 10:30:49 +10:00
Paul Scott
ec4d3b938c Improved the error messages for some tests 2023-05-09 10:25:24 +10:00
Immanuel Alvaro Bhirawa
c4db86793c Task 13 done with the help of Nathan
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 10:25:20 +10:00
Immanuel Alvaro Bhirawa
bd2b3477b6 cleaned task 13 but still dont know what caused the testEdgeCaseGames test to fail.
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 02:50:23 +10:00
Immanuel Alvaro Bhirawa
28b0288e8a cleaned task 13 a bit but still dont know what this edge case error is lol
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 01:54:22 +10:00
Immanuel Alvaro Bhirawa
0f203df939 task 13 progress, 3 task passed this point
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-09 01:48:33 +10:00
9381eedf5f
state: isPhaseOver cleaned up code 2023-05-08 13:25:28 +10:00
8a4e83b9a7
player: Fixed isPhaseOver bug 2023-05-08 13:25:08 +10:00
f6f3f4a6a1
state: isPhaseOver sped up code 2023-05-08 13:07:03 +10:00
Immanuel Alvaro Bhirawa
73293edb43 Added more documentation and optimization for scoreLink
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-06 21:10:48 +10:00
Immanuel Alvaro Bhirawa
90674de713 Added documentation and Optimized task 11 scoreLink #2
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-06 20:55:55 +10:00
Immanuel Alvaro Bhirawa
199a50b088 Optimized task 11 scoreLink #1
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-06 20:12:30 +10:00
Immanuel Alvaro Bhirawa
3d84fa1e83 Merge branch 'master' of https://gitlab.cecs.anu.edu.au/u7156831/comp1110-ass2
# Conflicts:
#	src/comp1110/ass2/State.java
2023-05-06 20:02:09 +10:00
Immanuel Alvaro Bhirawa
6e6bf69bdf yes
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-06 20:01:25 +10:00
506c2bb395
state: cleaned & optimized linking 2023-05-06 18:53:42 +10:00
bdaaf35a88
coord: Fixed adjacency calculation 2023-05-06 18:35:45 +10:00
d0c3d0faee
admin: Added empty code review to pass compliance 2023-05-06 14:34:46 +10:00
Immanuel Alvaro Bhirawa
ad3a9c4a00 Task 11 Linking progress for now.
NOTE: Yeah idk if this is correct or not, but that's it for now

Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-04 13:05:56 +10:00
cf4bb47c8f
game: Added more intro description 2023-05-02 15:43:40 +10:00
8fdf5a2cdb
state: Fix assertion errors 2023-05-02 15:43:11 +10:00
025d5af907
game: Fixed mouse controls 2023-05-02 14:52:23 +10:00
91d9721855
player: cleaned code for Coord implementation 2023-05-02 14:52:08 +10:00
329a65176b
state: cleaned code 2023-05-02 14:51:26 +10:00
7aa5605ed2
BlueLagoon: cleaned code 2023-05-02 14:49:34 +10:00
b4e3afb867
coord: Changed to record type 2023-05-02 14:45:05 +10:00
3c343d002a
resource: cleaned code 2023-05-02 14:39:08 +10:00
e52d16d01a
player: Cleaned up code 2023-05-02 14:28:03 +10:00
a13e93c339
BlueLagoon: cleaned up code 2023-05-02 14:14:58 +10:00
d436cdb138
game: Cleaned up code 2023-05-02 14:14:28 +10:00
649481583a
Merge remote-tracking branch 'origin/master' 2023-05-02 14:03:20 +10:00
2f0964b26b
game: cleaned up code and use GameData class 2023-05-02 14:03:13 +10:00
dd56bbfdd7
game: Added GameData class to store game stateStrings 2023-05-02 14:02:46 +10:00
Immanuel Alvaro Bhirawa
8f0be1948f E Originality
Signed-off-by: Immanuel Alvaro Bhirawa <u7280427@anu.edu.au>
2023-05-02 12:52:07 +10:00
52630951f0
game: Added support for any number of AI players 2023-05-02 12:43:54 +10:00
035d3bf022
player: Added storing if the player is AI 2023-05-02 12:43:41 +10:00
Justin Ryu
98e98e496c admin: signed E-contribution Justin 2023-05-01 20:28:33 +10:00
Justin Ryu
2cb2a46b01 admin: signed E-originality Justin 2023-05-01 20:26:39 +10:00
e6b4f9fd89
Merge branch 'generateAll_Fix' 2023-05-01 19:43:21 +10:00
aa0bbb146d
Fix timeout on generateAllMoves and isPhaseOver
generateMove: Removed unused code and sped up computation


moved generate moves to player to increase speed
2023-05-01 19:42:26 +10:00
355af7e358
Merge branch 'generateAll_Fix' 2023-05-01 19:39:44 +10:00
8b142ad434
admin: Changed links to still work after fixes 2023-05-01 19:39:09 +10:00
18 changed files with 675 additions and 638 deletions

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

53
admin/F-best-u7156831.yml Normal file
View 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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View 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;";
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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.

View File

@ -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));
}
}
}

View File

@ -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));
}
}
}

View File

@ -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;");
}
}

View File

@ -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));
}
}
}