├── .gitignore
├── .settings
└── .gitignore
├── README.md
├── config
├── .gitignore
├── Boss.java
├── config.ini
├── level1
│ └── Boss.py3
├── level2
│ ├── Boss.py3
│ ├── welcome_en.html
│ └── welcome_fr.html
├── level3
│ ├── welcome_en.html
│ └── welcome_fr.html
├── statement_en.html.tpl
├── statement_fr.html.tpl
└── stub.txt
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── codingame
│ │ ├── game
│ │ ├── InputActions
│ │ │ ├── Action.java
│ │ │ ├── InvalidAction.java
│ │ │ ├── MoveAction.java
│ │ │ ├── PassAction.java
│ │ │ └── PushAction.java
│ │ ├── Model
│ │ │ ├── AbstractModel.java
│ │ │ ├── CardModel.java
│ │ │ ├── GameBoard.java
│ │ │ ├── Item.java
│ │ │ ├── MovingModel.java
│ │ │ ├── PlayerModel.java
│ │ │ ├── StateUpdates
│ │ │ │ ├── CardPositionUpdate.java
│ │ │ │ ├── FlipCardUpdate.java
│ │ │ │ ├── PoppedUpdate.java
│ │ │ │ ├── PushedUpdate.java
│ │ │ │ ├── RemoveCardUpdate.java
│ │ │ │ ├── RemoveItemUpdate.java
│ │ │ │ └── ShowFrameUpdate.java
│ │ │ └── TileModel.java
│ │ ├── Player.java
│ │ ├── Referee.java
│ │ ├── Utils
│ │ │ ├── Constants.java
│ │ │ └── Vector2.java
│ │ └── View
│ │ │ ├── AbstractView.java
│ │ │ ├── ArrowView.java
│ │ │ ├── BoardView.java
│ │ │ ├── CardDeckView.java
│ │ │ ├── CardView.java
│ │ │ ├── MovingView.java
│ │ │ ├── PlayerTextView.java
│ │ │ ├── PlayerView.java
│ │ │ ├── TileView.java
│ │ │ ├── TurnTextView.java
│ │ │ └── ViewController.java
│ │ └── view
│ │ ├── endscreen
│ │ └── EndScreenModule.java
│ │ ├── nicknameshandler
│ │ └── NicknamesHandlerModule.java
│ │ └── tooltip
│ │ └── TooltipModule.java
└── resources
│ └── view
│ ├── assets
│ ├── arrow_0.png
│ ├── arrow_1.png
│ ├── arrow_2.png
│ ├── background.jpg
│ ├── background_name_0.png
│ ├── background_name_1.png
│ ├── cardBack_0.png
│ ├── cardBack_1.png
│ ├── cardFront_0.png
│ ├── cardFront_1.png
│ ├── elf_0.png
│ ├── elf_1.png
│ ├── frame.png
│ ├── items_sheet.json
│ ├── items_sheet.png
│ ├── logo.png
│ ├── tile_background.png
│ ├── tile_decorators.json
│ ├── tile_decorators.png
│ ├── tile_paths.json
│ └── tile_paths.png
│ ├── config.js
│ ├── demo.js
│ └── modules
│ ├── endScreen
│ └── EndScreenModule.js
│ ├── nicknamesHandlerModule
│ └── NicknamesHandlerModule.js
│ ├── toggleModule
│ └── ToggleModule.js
│ └── tooltip
│ └── TooltipModule.js
└── test
├── java
├── Main.java
├── Player1.java
├── Player2.java
└── com
│ └── codingame
│ └── game
│ ├── InputActions
│ ├── MoveActionTest.java
│ ├── PassActionTest.java
│ └── PushActionTest.java
│ ├── Model
│ ├── CardModelTest.java
│ ├── ItemTest.java
│ ├── PlayerModelTest.java
│ └── TileModelTest.java
│ ├── PlayerTest.java
│ └── Utils
│ └── Vector2Test.java
└── resources
└── log4j2.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | .factorypath
2 | .settings/
3 | /target/
4 | /.project
5 | /.classpath
6 | .idea/
7 | *.DS_Store
8 | *.iml
--------------------------------------------------------------------------------
/.settings/.gitignore:
--------------------------------------------------------------------------------
1 | /org.eclipse.jdt.core.prefs
2 | /org.eclipse.m2e.core.prefs
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Repo for the Xmas Rush contest on CodinGame
2 |
--------------------------------------------------------------------------------
/config/.gitignore:
--------------------------------------------------------------------------------
1 | statement_en.html
2 | statement_fr.html
--------------------------------------------------------------------------------
/config/Boss.java:
--------------------------------------------------------------------------------
1 | import java.util.Scanner;
2 |
3 | class Player {
4 | public static void main(String args[]) {
5 | Scanner in = new Scanner(System.in);
6 | int boardWidth = 7;
7 | int boardHeight = 7;
8 |
9 | int turn = 0;
10 | // game loop
11 | while (true) {
12 | int turnType = in.nextInt();
13 | for (int i = 0; i < boardHeight; i++) {
14 | for (int j = 0; j < boardWidth; j++) {
15 | String tile = in.next();
16 | System.err.print(tile + " ");
17 | }
18 | System.err.println();
19 | }
20 | for (int i = 0; i < 2; i++) {
21 | int numPlayerCards = in.nextInt(); // the number of cards in the stack for each player
22 | int playerX = in.nextInt();
23 | int playerY = in.nextInt();
24 | String playerTile = in.next();
25 | System.err.println(numPlayerCards + " " + playerX + "," + playerY + " " + playerTile);
26 | }
27 | int numItems = in.nextInt(); // the total number of items available on board and on player tiles (does not include quest cards)
28 | for (int i = 0; i < numItems; i++) {
29 | String itemName = in.next();
30 | int itemX = in.nextInt();
31 | int itemY = in.nextInt();
32 | int itemPlayerId = in.nextInt();
33 | System.err.println(itemName + itemPlayerId + " " + itemX + "," + itemY);
34 | }
35 | int numQuests = in.nextInt(); // the total number of available quest cards for both players
36 | for (int i = 0; i < numQuests; i++) {
37 | String questItemName = in.next();
38 | int questPlayerId = in.nextInt();
39 | System.err.println(questItemName + questPlayerId);
40 | }
41 |
42 | if (turnType == 0) {
43 | System.out.println("PUSH 3 DOWN");
44 | } else {
45 | System.out.println("PASS");
46 | }
47 | turn++;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/config/config.ini:
--------------------------------------------------------------------------------
1 | title=Xmas Rush
2 | type=multi
3 | min_players=2
4 | max_players=2
5 |
--------------------------------------------------------------------------------
/config/level1/Boss.py3:
--------------------------------------------------------------------------------
1 | import sys
2 | import math
3 | from collections import namedtuple
4 | from collections import deque
5 |
6 | Vector = namedtuple('Vector', ['x', 'y'])
7 | Step = namedtuple('Step', ['direction', 'tile'])
8 | Item = namedtuple('Item', ['name','position'])
9 |
10 | boardWidth, boardHeight = 7, 7
11 |
12 | # Here are my global variables, these keep their values between turns
13 | column = 0
14 | row = 0
15 | toggle = True
16 | moveType = 0
17 |
18 | # I don't know if i'm player one or not yet
19 | player = -1
20 |
21 | # A dictionnary linking directions to their vectors
22 | moves = {
23 | 'LEFT': Vector(-1, 0),
24 | 'UP': Vector(0, -1),
25 | 'RIGHT': Vector(1, 0),
26 | 'DOWN': Vector(0, 1)
27 | }
28 | # A dictionnary linking directions to their opposite
29 | oppositeMove = {
30 | 'LEFT': 'RIGHT',
31 | 'UP': 'DOWN',
32 | 'RIGHT': 'LEFT',
33 | 'DOWN': 'UP'
34 | }
35 |
36 | # Here is a function allowing me to add two vectors
37 | def addPositions(v1, v2):
38 | return Vector(v1.x + v2.x, v1.y + v2.y)
39 |
40 | # Now we're going to create our tile object
41 | class Tile:
42 |
43 | # This function allows us to pass parameters when creating the object
44 | def __init__(self, pos, code):
45 | self.pos = pos # the coordinates of the tile
46 | # the directions that you can take from this tile
47 | self.availableMoves = self.parseCode(code)
48 |
49 | # this function allows us to use the '0101' code of the tile and turn it into a list of directions
50 | def parseCode(self, code):
51 | moves = []
52 | if code[0] == '1':
53 | moves.append('UP')
54 | if code[1] == '1':
55 | moves.append('RIGHT')
56 | if code[2] == '1':
57 | moves.append('DOWN')
58 | if code[3] == '1':
59 | moves.append('LEFT')
60 | return moves
61 | # Returns the tile in direction direction
62 | def getTileInDirection(self, board, direction):
63 | vect = moves.get(direction)
64 | pos = addPositions(self.pos, vect)
65 | return board[pos]
66 |
67 | # Returns all the direction you can take from a tile
68 | def getAccessibleDirections(self, board):
69 | steps = self.getPossibleSteps(board)
70 | return list(map(lambda x: x.direction, steps))
71 |
72 | # Returns all the accessible tiles from this tile in one move
73 | def getPossibleSteps(self, board):
74 | direc = []
75 | for move in self.availableMoves:
76 | vect = moves.get(move)
77 | dest = addPositions(self.pos, vect)
78 |
79 | if dest in board and oppositeMove.get(move) in board[dest].availableMoves:
80 | direc.append(Step(move, board[dest]))
81 |
82 | return direc
83 |
84 | # Returns the path from this tile to the tile you want
85 | def findPath(self, board, pos):
86 | currentTile = self
87 | visited = {currentTile}
88 | toVisit = deque()
89 | toVisit.append((currentTile, []))
90 | while toVisit:
91 | currentTile, path = toVisit.popleft()
92 | if currentTile.pos == pos:
93 | return path
94 | else:
95 | for step in currentTile.getPossibleSteps(board):
96 | if step.tile not in visited:
97 | toVisit.append((step.tile, path + [step.direction]))
98 | visited.add(step.tile)
99 |
100 |
101 | # game loop
102 | while True:
103 | # Here are my local variables, these are reset at each turn
104 | myHeroPos = Vector(0,0)
105 | quests = []
106 | items = []
107 |
108 | board = {} # The board is a dictionnary linking the position of a tile to the tile object
109 |
110 | # Here we get the type of turn : 0 for push and 1 for move
111 | turnType = int(input())
112 |
113 | # Here we create our representation of the board
114 | for y in range(boardHeight):
115 | x = 0
116 | for tile in input().split():
117 | temp = Tile([x, y], tile)
118 | board[Vector(x, y)] = Tile(Vector(x, y), tile)
119 | x += 1
120 |
121 | # Here we get our position (and ignore all the other infos)
122 | for i in range(2):
123 | numPlayerCards, playerX, playerY, playerTile = input().split()
124 | numPlayerCards = int(numPlayerCards)
125 | playerX = int(playerX)
126 | playerY = int(playerY)
127 | if i == 0:
128 | myHeroPos = Vector(playerX, playerY)
129 |
130 | # Here we get the position of our items (and ignore the ones of the other player)
131 | numItems = int(input())
132 | for i in range(numItems):
133 | itemName, itemX, itemY, itemPlayerId = input().split()
134 | itemPlayerId = int(itemPlayerId)
135 | if itemPlayerId == 0:
136 | items.append(Item(itemName, Vector(int(itemX), int(itemY))))
137 |
138 | # Here we get the list of the items we want (and ignore the ones of the other player)
139 | numQuests = int(input())
140 | for i in range(numQuests):
141 | questItemName, questPlayerId = input().split()
142 | questPlayerId = int(questPlayerId)
143 | if questPlayerId == 0:
144 | quests.append(questItemName)
145 |
146 | myHeroTile = board[myHeroPos]
147 | goalPos = Vector(0,0)
148 |
149 | # Now we detect if we are player one or two (just to avoid having boring draws against ourself)
150 | if player == -1:
151 | if myHeroPos[0] == 0:
152 | player = 0
153 | else:
154 | player = 1
155 | toggle = player # to avoid boring draws we start our push phase differently
156 |
157 | # We select the item we want to search
158 | for item in items:
159 | if item.name == quests[0]:
160 | goalPos = item.position
161 |
162 | # If it's a push turn
163 | if turnType == 0:
164 | # We will alternate between vertical and horizontal push to shuffle the grid
165 | # and change the line or the column we want to push at each push
166 | if toggle:
167 | print("PUSH", column, "RIGHT")
168 | column = (column + 1) % boardHeight
169 | else:
170 | print("PUSH", row, "DOWN")
171 | row = (row + 1) % boardHeight
172 | toggle = not(toggle)
173 |
174 | # If it's a move turn
175 | else:
176 | # default value: we do nothing
177 | action = 'PASS'
178 |
179 | # if we can go somewhere select one of the available directions
180 | if len(myHeroTile.getAccessibleDirections(board)) != 0:
181 | action = "MOVE " + myHeroTile.getAccessibleDirections(board)[moveType % len(myHeroTile.getAccessibleDirections(board))]
182 |
183 | # if we can go to our goal item go for it (but we don't want to be too strong so we don't go for more that 2 tiles at once)
184 | path = myHeroTile.findPath(board,goalPos)
185 | if path:
186 | action = 'MOVE ' + " ".join(path[:2])
187 |
188 | # output the move we chose
189 | print(action)
190 |
191 | # Change the index of the next direction we'll chose if we can go somewhere but not get item
192 | moveType = (moveType+1) % len(moves)
--------------------------------------------------------------------------------
/config/level2/Boss.py3:
--------------------------------------------------------------------------------
1 | import sys
2 | import math
3 | import random
4 |
5 | random.seed('Help the Christmas elves fetch presents in a magical labyrinth!')
6 |
7 | board_width, board_height = [7,7]
8 |
9 |
10 | def approach(target_x, player_x, target_y, player_y):
11 | if target_x < player_x:
12 | return 'LEFT'
13 | elif target_x > player_x:
14 | return 'RIGHT'
15 | elif target_y < player_y:
16 | return 'UP'
17 | else:
18 | return 'DOWN'
19 |
20 |
21 | spinner = {
22 | (-1, -1): 'RIGHT',
23 | (0, -1): 'RIGHT',
24 | (1, -1): 'DOWN',
25 | (1, 0): 'DOWN',
26 | (1, 1): 'LEFT',
27 | (0, 1): 'LEFT',
28 | (-1, 1): 'UP',
29 | (-1, 0): 'UP'
30 | }
31 | moves = {
32 | 'LEFT': [-1,0],
33 | 'UP':[0,-1],
34 | 'RIGHT':[1,0],
35 | 'DOWN':[0,1]
36 | }
37 | oppositeMove = {
38 | 'LEFT': 'RIGHT',
39 | 'UP':'DOWN',
40 | 'RIGHT':'LEFT',
41 | 'DOWN':'UP'
42 | }
43 | def addPositions(pos1,pos2):
44 | return [pos1[0]+pos2[0],pos1[1]+pos2[1]]
45 | class Tile:
46 | def __init__(self, pos, code):
47 | self.pos = pos
48 | self.availableMoves = self.transcribeCode(code)
49 | def transcribeCode(self,code):
50 | tilemoves = []
51 | if (code[0] == '1'):
52 | tilemoves.append('UP')
53 | if (code[1] == '1'):
54 | tilemoves.append('RIGHT')
55 | if (code[2] == '1'):
56 | tilemoves.append('DOWN')
57 | if (code[3] == '1'):
58 | tilemoves.append('LEFT')
59 | return tilemoves
60 | def getAccessibleDirections(self,board):
61 | direc = []
62 | for move in self.availableMoves:
63 | vect = moves.get(move)
64 | dest = addPositions(self.pos,vect)
65 | try :
66 | if (oppositeMove.get(move) in board[dest[0],dest[1]].availableMoves):
67 | direc.append(move)
68 | except KeyError:
69 | pass
70 | return direc
71 | # game loop
72 | while True:
73 | target_x = 0
74 | target_y = 0
75 | player_x = 0
76 | player_y = 0
77 |
78 | turn_type = int(input())
79 | board = {}
80 | for y in range(board_height):
81 | x=0
82 | for tile in input().split():
83 | temp = Tile([x,y],tile)
84 | board[x,y] = Tile([x,y],tile)
85 | x += 1
86 | for i in range(2):
87 | # num_player_cards: the number of cards in the stack for each player
88 | num_player_cards, x, y, player_tile = input().split()
89 | num_player_cards = int(num_player_cards)
90 | x = int(x)
91 | y = int(y)
92 | if i == 0:
93 | player_x = x
94 | player_y = y
95 | print(x, y, file=sys.stderr)
96 | # the total number of items available on board and on player tiles (does not include quest cards)
97 | items = {}
98 | num_items = int(input())
99 | for i in range(num_items):
100 | item_name, item_x, item_y, item_player_id = input().split()
101 | # print(item_name, file=sys.stderr)
102 | item_x = int(item_x)
103 | item_y = int(item_y)
104 | item_player_id = int(item_player_id)
105 | items[item_name + str(item_player_id)] = (item_x, item_y)
106 |
107 | # the total number of available quest cards for both players
108 | num_quests = int(input())
109 | for i in range(num_quests):
110 | quest_item_name, quest_player_id = input().split()
111 | quest_player_id = int(quest_player_id)
112 | if quest_player_id == 0:
113 | target_x = items[quest_item_name + str(quest_player_id)][0]
114 | target_y = items[quest_item_name + str(quest_player_id)][1]
115 |
116 | if turn_type == 0:
117 | if target_x < 0:
118 | direction = random.choice(('RIGHT', 'UP', 'LEFT', 'DOWN'))
119 | to_push = random.randint(0, 6)
120 | print(f'PUSH {to_push} {direction}')
121 | else:
122 | diff = (target_x - player_x, target_y - player_y)
123 | if diff in spinner:
124 | direction = spinner[diff]
125 | to_push = target_y if (direction in (
126 | 'RIGHT', 'LEFT')) else target_x
127 | print(f'PUSH {to_push} {direction}')
128 | else:
129 | if abs(diff[0]) != 1 and player_y != target_y:
130 | direction = 'LEFT' if player_x < target_x else 'RIGHT'
131 | to_push = target_y
132 | print(f'PUSH {to_push} {direction}')
133 | elif abs(diff[1]) != 1 and player_x != target_x:
134 | direction = 'UP' if player_y < target_y else 'DOWN'
135 | to_push = target_x
136 | print(f'PUSH {to_push} {direction}')
137 | else:
138 | direction = random.choice(('RIGHT', 'UP', 'LEFT', 'DOWN'))
139 | to_push = random.randint(0, 6)
140 | print(f'PUSH {to_push} {direction}')
141 | else:
142 | tcheby = max(abs(target_x - player_x), abs(target_y - player_y))
143 | manhat = abs(target_x - player_x) + abs(target_y - player_y)
144 | currTile = board[player_x,player_y]
145 | nextMove = approach(target_x, player_x, target_y, player_y)
146 | if (tcheby != 1 or manhat == 1) and nextMove in currTile.getAccessibleDirections(board):
147 | print("MOVE " + approach(target_x, player_x, target_y, player_y))
148 | else:
149 | print("PASS")
150 |
--------------------------------------------------------------------------------
/config/level2/welcome_en.html:
--------------------------------------------------------------------------------
1 |
2 |
You've made it to the next league
3 |
You will have to complete 6 quests while having 1 revealed!
4 |
See the updated statement for details.
5 |
6 |
--------------------------------------------------------------------------------
/config/level2/welcome_fr.html:
--------------------------------------------------------------------------------
1 |
2 |
Vous avez atteint la ligue Bois 1
3 |
Vous devrez terminer 6 quêtes en connaissant 1 quête à la fois !
4 |
Pour en savoir plus, allez voir l'énoncé.
5 |
6 |
--------------------------------------------------------------------------------
/config/level3/welcome_en.html:
--------------------------------------------------------------------------------
1 |
2 |
You've made it to the next league
3 |
You will have to complete 12 quests while having 3 revealed!
4 |
See the updated statement for details.
5 |
6 |
--------------------------------------------------------------------------------
/config/level3/welcome_fr.html:
--------------------------------------------------------------------------------
1 |
2 |
Vous avez atteint la ligue Bronze.
3 |
Vous devrez terminer 12 quêtes en connaissant au maximum 3 quête à la fois !
4 |
Pour en savoir plus, allez voir l'énoncé.
5 |
6 |
--------------------------------------------------------------------------------
/config/statement_en.html.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |

13 |
14 |
15 |
16 | This is a league based challenge.
17 |
18 |
19 | Welcome to the Wood1 league!
20 |
21 |
22 | Welcome to the Bronze league!
23 |
24 |
25 |
26 |
27 | Wood leagues should be considered as a tutorial which lets players discover the different rules of the game.
28 | In Bronze league, all rules will be unlocked and the real challenge will begin.
29 |
30 |
31 | In Wood 1, players must complete 6 quests. At most 1 quest is revealed.
32 |
33 |
34 | In Bronze, players must complete 12 quests. At most 3 quests are revealed.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | The Goal
45 |
46 |
47 | Make your way to the items on the board and be the first to complete your quests!
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | Rules
56 |
57 |
58 |
59 | The game is played by 2 players on a 7x7 board with 49 square tiles. The (0,0) coordinate corresponds to the top
60 | left corner.
61 |
62 |
63 | Each player has 1 tile placed outside the board which they can use to push a row or a column on the board,
64 | trying to make a path toward their quest items. When a user pushes a tile into the board, the tile that gets
65 | pushed out will become the new player's tile.
66 |
67 |
68 | The board
69 |
70 |
71 | -
72 | The board contains square tiles with paths on them. A path can lead to one of the four directions
73 | (UP, RIGHT, DOWN and LEFT).
74 |
75 | -
76 | Some tiles have an item on them.
77 |
78 |
79 |
80 | Quest
81 |
82 |
83 | -
84 | Each quest corresponds to an item on the board. Quests are the same for both players, but each item is unique in the deck.
85 |
86 | -
87 | To complete a quest, a player must move to the tile containing the corresponding item. The quest must be
88 | revealed to be able to complete it.
89 |
90 |
91 | -
92 | For this league, each player has 1 quest to complete.
93 |
94 |
95 |
96 | -
99 | For this league, each player has 6 quests to complete. At most 1 quest is
100 | revealed.
101 |
102 | -
105 | When an item is collected, it is removed from the tile and the quest is marked as completed and removed
106 | from the player's quest deck. After the turn ends, a new quest is revealed (if available).
107 |
108 |
109 |
110 | -
113 | For this league, each player has 12 quests to complete. At most 3 quests are
114 | revealed. They can be collected in any order.
115 |
116 | -
119 | A player can complete multiple quests in one turn.
120 |
121 |
122 |
123 | -
124 | For this league, each player has 12 quests to complete. At most 3 quests are
125 | revealed. They can be collected in any order.
126 |
127 | -
128 | A player can complete multiple quests in one turn.
129 |
130 |
131 |
132 | -
133 | When an item is collected, it is removed from the tile and the quest is marked as completed and removed
134 | from the player's quest deck. After the turn ends, a new quest is revealed (if available).
135 |
136 |
137 |
138 |
139 |
140 |
141 | The game turns
142 |
143 |
144 | Each game turn alternates between a PUSH turn and a MOVE turn.
145 | The first turn is always a PUSH turn.
146 |
147 |
148 | Rules for pushing
149 |
150 |
151 | -
152 | Each player can choose to push any row or column on the board. Rows can only be pushed horizontally
153 | (LEFT or RIGHT), while columns can only be pushed vertically
154 | (UP or DOWN).
155 |
156 | -
157 | If both players push the same row or column, no matter the direction, nothing happens.
158 |
159 | -
160 | If push commands intersect (one is horizontal and the other one vertical), the row is pushed first,
161 | followed by the column. Otherwise, they get pushed simultaneously.
162 |
163 | -
164 | If a player is on a tile which gets pushed out of the map, the player is wrapped on the other end of the line.
165 |
166 |
167 |
168 | Rules for moving
169 |
170 |
171 | -
172 | To allow a player to move between two adjacent tiles, the tiles' respective paths must connect to form a longer
173 | path. Moving to an adjacent tile counts as 1 step.
174 |
175 | -
176 | Each player can move at most 20 steps during this turn via connected paths.
177 |
178 |
179 |
180 | Actions
181 |
182 | Every
PUSH turn the player must:
183 |
184 | -
185 | PUSH id direction: to push a row id
186 | (direction LEFT or RIGHT) or a column id
187 | (direction UP or DOWN).
188 |
189 |
190 | Every
MOVE turn the player must either:
191 |
192 | -
193 | MOVE direction: to move one step towards direction
194 | LEFT, RIGHT, UP or DOWN.
195 |
196 | -
197 | PASS: to do nothing.
198 |
199 |
200 |
201 | A MOVE can contain up to 20 directions, each direction separated by a
202 | space .
203 |
204 |
205 | Note: You may toggle tile scenery on/off in the settings panel (

).
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
Victory Conditions
214 |
215 |
216 | -
217 | You complete all your quests before your opponent (if both players complete their quests in the same turn, the
218 | game will end as a draw).
219 |
220 | -
221 | After 150 turns, you complete more quests than your opponent.
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
Loss Conditions
233 |
234 |
235 | -
236 | Your program times out.
237 |
238 | -
239 | Your program provides invalid output for the active turn type.
240 |
241 | -
242 | You complete fewer quests than your opponent.
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | Advanced Details
255 |
256 |
257 |
258 | You can see the game's source code here: https://github.com/CodinGameCommunity/XmasRush.
259 |
260 |
261 |
262 | -
263 | Players don't need to finish their turn on an item to collect it. Moving over it during a longer movement
264 | sequence is sufficient to complete revealed quests.
265 |
266 | -
267 | An invalid move ends the current movement. Moving to a direction without a connected path in that direction
268 | is considered as invalid.
269 |
270 | -
271 | It is possible to complete a quest during a push turn. If a push command warps a player onto a quest item,
272 | the quest, if revealed, is completed and another one is revealed at the end of the turn.
273 |
274 | -
275 | If no modification of the labyrinth happens for 10 successive turns of modification, the game ends, independently of both players' movement actions.
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 | Game Input
286 |
287 |
288 |
289 |
290 |
Input for one game turn
291 |
292 |
First line: Integer
turnType: the game turn type:
293 |
294 | -
295 | 0: a PUSH turn.
296 |
297 | -
298 | 1: a MOVE turn.
299 |
300 |
301 |
Next 7 lines:
7 space-separated strings
302 | representing each tile on a row, starting from the top. Each tile is represented by a 4 digit group, each digit
303 | corresponding to a directional path: up, right, down, left.
1 means the tile has a path for the
304 | respective direction,
0 means the tile doesn't.
305 |
Next 2 lines: for each player,
numPlayerCards,
306 |
playerX,
playerY,
playerTile:
307 |
308 | -
309 | Integer numPlayerCards: the total number of quests for a player (hidden and revealed).
310 |
311 | -
312 | Integer playerX: the player's x position on the board (the column).
313 |
314 | -
315 | Integer playerY: the player's y position on the board (the row).
316 |
317 | -
318 | String playerTile: the player's tile in 4 digit format.
319 |
320 |
321 |
Note: The player's input always comes
first, the opponent's input comes
second.
322 |
Next line: Integer
numItems: the total number of items
323 | available on board and on player tiles.
324 |
Next numItems lines:
itemName,
itemX,
325 |
itemY,
itemPlayerId:
326 |
327 | -
328 | String itemName: the item's name.
329 |
330 | -
331 | Integer itemX: the item's x position on the board (the column).
332 |
333 | -
334 | Integer itemY: the item's y position on the board (the row).
335 |
336 | -
337 | Integer itemPlayerId: the id of the player who can collect the item.
338 |
339 |
340 |
Note: If an item is on a player's tile,
itemX and
itemY will both be
341 |
-1 for the player and
-2 for the opponent.
342 |
Next line: Integer
numQuests: the total number of revealed quests
343 | for both players.
344 |
Next numQuests lines:
questItemName,
345 |
questPlayerId:
346 |
347 | -
348 | String questItemName: the item's name.
349 |
350 | -
351 | Integer questPlayerId: the id of the player the quest belongs to.
352 |
353 |
354 |
Note: The player's id is always
0 and the opponent's
1.
355 |
356 |
357 |
358 |
359 |
360 |
Output for one PUSH game turn
361 |
362 |
363 | -
364 | PUSH id direction where id is between 0
365 | and 6, and direction can be UP, DOWN,
366 | LEFT or RIGHT.
367 |
368 |
369 | Example:
PUSH 3 UP will push the fourth column upwards.
370 |
371 |
Output for one MOVE game turn
372 |
373 |
374 | -
375 | MOVE direction where direction can be UP,
376 | DOWN, LEFT or RIGHT.
377 |
378 | -
379 | PASS to skip moving this turn.
380 |
381 |
382 | A
MOVE can contain up to
20 directions, each direction separated by a
383 | space
.
384 | Example:
MOVE LEFT UP RIGHT will make the player move left, then up, then right.
385 |
386 |
387 |
388 |
389 |
390 |
Constraints
391 |
392 |
board width =
7
393 |
board height =
7
394 |
395 |
numPlayerCards =
1
396 |
0 ≤
numItems ≤
2
397 |
0 ≤
numQuests ≤
2
398 |
399 |
400 |
403 | 0 ≤ numPlayerCards ≤ 6
404 | 0 ≤ numItems ≤ 12
405 | 0 ≤ numQuests ≤ 2
406 |
407 |
408 |
409 |
412 | 0 ≤ numPlayerCards ≤ 12
413 | 0 ≤ numItems ≤ 24
414 | 0 ≤ numQuests ≤ 6
415 |
416 |
417 |
418 |
0 ≤
numPlayerCards ≤
12
419 |
0 ≤
numItems ≤
24
420 |
0 ≤
numQuests ≤
6
421 |
422 |
423 |
424 | Response time for the first turn ≤
1s
425 | Response time per turn ≤
50ms
426 |
427 |
428 |
429 |
430 |
435 |
436 |

437 |
438 |
439 | What is in store in the higher leagues?
440 |
441 |
442 | The extra rules available in higher leagues are:
443 |
444 |
445 | - In Wood 1, players must complete 6 quests. At most 1 quest is revealed.
446 |
447 |
448 | - In Bronze, players must complete 12 quests. At most 3 quests are revealed.
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
--------------------------------------------------------------------------------
/config/statement_fr.html.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |

13 |
14 |
15 |
16 | Ce puzzle se déroule en ligues.
17 |
18 |
19 | Bienvenue en ligue Bois 1 !
20 |
21 |
22 | Bienvenue en ligue Bronze !
23 |
24 |
25 |
26 |
27 | Les ligues Bois doivent être considérées comme un tutoriel pour apprendre les différentes règles du jeu.
28 | En ligue Bronze, toutes les règles sont débloquées et alors débute le challenge, le vrai.
29 |
30 |
31 | En ligue Bois 1, chaque joueur doit terminer 6 quêtes. 1 quête au maximum est révélée.
32 |
33 |
34 | En ligue Bronze, chaque joueur doit terminer 12 quêtes. 3 quêtes au maximum sont révélées.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Objectif
45 |
46 |
47 | Faites-vous un chemin vers les objets disséminés dans le labyrinthe et soyez le premier à terminer vos quêtes !
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | Règles du jeu
56 |
57 |
58 |
59 | Une partie est jouée par 2 joueurs sur un plateau 7x7 de 49 tuiles carrées. Les coordonnées (0,0) correspondent à la tuile dans le coin en haut à gauche.
60 |
61 |
62 | Chaque joueur possède une tuile qu'il utilise pour pousser une ligne ou une colonne du plateau, de façon à créer un chemin vers les objets de leurs quêtes.
63 | Quand un joueur utilise sa tuile pour déplacer une colonne ou une ligne, il récupère la tuile qui est poussée hors du plateau.
64 |
65 |
66 | Le plateau de jeu
67 |
68 |
69 | -
70 | Chaque tuile contient des chemins. Un chemin peut mener à 1 des 4 directions possibles :
71 | UP (vers le haut), RIGHT (vers la droite), DOWN (vers le bas) et LEFT(vers la gauche).
72 |
73 | -
74 | Certaines tuiles contiennent des objets.
75 |
76 |
77 |
78 | Les quêtes
79 |
80 |
81 | -
82 | Chaque quête correspond à un objet sur le plateau.
83 |
84 | -
85 | Pour terminer une quête, un joueur doit se déplacer sur la tuile contenant l'objet correspondant. La quête doit être révélée pour qu'un joueur puisse la terminer.
86 |
87 |
88 | -
89 | Dans cette ligue, chaque joueur n'a qu' 1 quête à terminer.
90 |
91 |
92 |
93 | -
96 | Dans cette ligue, chaque joueur a 6 quêtes à terminer. 1 quête au maximum est révélée.
97 |
98 | -
101 | Quand un objet est récupéré par un joueur, l'objet est retiré du jeu et la quête est terminée.
102 | Après la fin du tour, une nouvelle quête est révélée (si disponible).
103 |
104 |
105 |
106 | -
109 | Dans cette ligue, chaque joueur a 12 quêtes à terminer. 3 quête au maximum est révélée. Elles peuvent êtres terminées dans n'importe quel ordre.
110 |
111 | -
114 | Un joueur peut terminer plusieurs quêtes dans un même tour.
115 |
116 |
117 |
118 | -
119 | Dans cette ligue, chaque joueur a 12 quêtes à terminer. 3 quête au maximum est révélée. Elles peuvent êtres terminées dans n'importe quel ordre.
120 |
121 | -
122 | Un joueur peut terminer plusieurs quêtes dans un même tour.
123 |
124 |
125 |
126 | -
127 | Quand un objet est récupéré par un joueur, l'objet est retiré du jeu et la quête est terminée.
128 | Après la fin du tour, une nouvelle quête est révélée (si disponible).
129 |
130 |
131 |
132 |
133 |
134 |
135 | Les différents tours de jeu
136 |
137 |
138 | Il y a deux types de tours qui s'alternent l'un après l'autre : un tour de modification (PUSH) et un tour de déplacement (MOVE).
139 | Le premier tour de jeu est toujours un tour de modification (PUSH).
140 |
141 |
142 | Règles pour modifier le labyrinthe
143 |
144 |
145 | -
146 | Chaque joueur peut choisir de pousser n'importe quelle ligne ou colonne du plateau. Les lignes sont poussées horizontalement
147 | (LEFT ou RIGHT), tandis que les colonnes sont poussées verticalement
148 | (UP ou DOWN).
149 |
150 | -
151 | Si les deux joueurs choisissent de pousser la même ligne ou la même colonne, rien ne se passe.
152 |
153 | -
154 | Si deux actions de modification s'intersectent (l'une horizontale et l'autre verticale) la ligne est poussée en premier, suivie par la colonne.
155 | Dans le cas contraire, les deux lignes ou deux colonnes sont poussées simultanément.
156 |
157 | -
158 | Si un joueur est poussé hors du plateau de jeu, il se retrouve sur la tuile qui a servi à pousser la ligne ou la colonne.
159 |
160 |
161 |
162 | Règles pour se déplacer
163 |
164 |
165 | -
166 | Pour qu'un joueur puisse se déplacer entre deux tuiles, les chemins des deux tuiles doivent se connecter pour en former un plus long.
167 | Se déplacer sur une tuile adjacente compte pour 1 pas.
168 |
169 | -
170 | Chaque joueur peut se déplacer de 20 pas au maximum par tour.
171 |
172 |
173 |
174 | Actions possibles
175 |
176 | Chaque tour de
PUSH, le joueur doit :
177 |
178 | -
179 | PUSH id direction: pour modifier une ligne id
180 | (direction LEFT ou RIGHT) ou une colonne id
181 | (direction UP ou DOWN).
182 |
183 |
184 | Chaque tour de
MOVE, le joueur doit :
185 |
186 | -
187 | MOVE direction: pour se déplacer vers la direction
188 | LEFT, RIGHT, UP ou DOWN.
189 |
190 | -
191 | PASS: pour ne rien faire et passer son tour.
192 |
193 |
194 |
195 | Une action MOVE doit contenir jusqu'à 20 directions, chaque direction séparée par un
196 | space .
197 |
198 |
199 | Note : Vous pouvez activer ou désactiver le décor tile dans les options de la vidéo (

).
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
Conditions de victoire
208 |
209 |
210 | -
211 | Vous terminez toutes vos quêtes avant votre adversaire. Si les deux joueurs terminent leur quêtes au même tour de jeu, la partie se termine en match nul.
212 |
213 | -
214 | Après 150 tours, vous terminez plus de quêtes que votre adversaire.
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
Conditions de défaite
226 |
227 |
228 | -
229 | Votre programme ne répond pas dans le temps imparti.
230 |
231 | -
232 | Votre programme répond avec une sortie invalide pour le type de tour.
233 |
234 | -
235 | Vous terminez moins de quêtes que votre adversaire.
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 | Détails de règles
248 |
249 |
250 |
251 | Vous pouvez retrouver le code source du jeu ici : https://github.com/CodinGameCommunity/XmasRush.
252 |
253 |
254 |
255 | -
256 | Les joueurs n'ont pas besoin de terminer leur tour sur un objet pour le récupérer.
257 | Se déplacer sur une tuile avec un objet pendant une séquence de mouvement est suffisant pour terminer une quête révélée.
258 |
259 | -
260 | Une action de déplacement invalide termine le déplacement en cours. Est considérée comme invalide, une commande de déplacement vers une direction sans connection de chemins.
261 |
262 | -
263 | Il est possible de terminer une quête pendant un tour de modification. Si la commande déplace le joueur hors du jeu puis sur la tuile utilisée qui contient l'objet d'une quête révélée, alors cette quête est terminée et une nouvelle est révélée à la fin du tour.
264 |
265 | -
266 | L'ordre des quêtes est le même pour les deux joueurs. Tous les objets d'un joueur sont uniques.
267 |
268 | -
269 | Si le labyrinthe n'est pas modifié pendant 10 tours consécutifs de modification, la partie se termine, indépendamment des actions de mouvement des joueurs.
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 | Protocole du jeu
280 |
281 |
282 |
283 |
284 |
Entrée pour un tour de jeu
285 |
286 |
Première ligne: un entier
turnType pour le type de tour de jeu
287 |
288 | -
289 | 0: un tour de modification (PUSH).
290 |
291 | -
292 | 1: un tour de déplacement (MOVE).
293 |
294 |
295 |
Les 7 lignes suivantes:
7 chaînes de caractères
296 | representant chaque tuile d'une ligne each, en démarrant à partir du haut. Chaque tuile est représentée par 4 chiffres, chaque chiffre représentant une direction :
297 | en haut, à droite, en bas, à gauche.
1 signifie que la tuile contient un chemin vers cette direction,
0 qu'elle n'en contient pas.
298 |
Les 2 lignes suivantes: pour chaque joueur,
numPlayerCards,
299 |
playerX,
playerY,
playerTile:
300 |
301 | -
302 | Un entier numPlayerCards: le nombre total de quêtes non terminées d'un joueur (cachée ou révélée).
303 |
304 | -
305 | Un entier playerX: la position x du joueur sur le plateau (sa colonne).
306 |
307 | -
308 | Un entier playerY: la position y du joueur sur le plateau (sa ligne).
309 |
310 | -
311 | Une chaîne de caractères playerTile: la tuile du joueur dans le format à 4 chiffres.
312 |
313 |
314 |
Note: L'entrée du joueur est toujours donnée en
premier, celle de son adversaire en
second.
315 |
Ligne suivante: un entier
numItems pour le nombre total d'objets disponibles sur le plateau et sur les tuiles des joueurs.
316 |
Les numItems lignes suivantes:
itemName,
itemX,
317 |
itemY,
itemPlayerId:
318 |
319 | -
320 | Une chaîne de caractères itemName: le nom de l'objet.
321 |
322 | -
323 | Un entier itemX: la position x de l'objet sur le plateau (sa colonne).
324 |
325 | -
326 | Un entier itemY: la position y de l'objet sur le plateau (sa ligne).
327 |
328 | -
329 | Un entier itemPlayerId: l'identifiant du joueur à qui l'objet appartient.
330 |
331 |
332 |
Note: Si un objet se trouve sur la tuile d'un joueur,
itemX et
itemY serons égaux à
333 |
-1 pour ce joueur, et
-2 pour son adversaire.
334 |
Ligne suivante: un entier
numQuests pour le nombre total de quêtes révélées pour les deux joueurs.
335 |
Les numQuests lignes suivantes:
questItemName,
336 |
questPlayerId:
337 |
338 | -
339 | Une chaîne de caractères questItemName: le nom de l'objet associé à la quête.
340 |
341 | -
342 | Un entier questPlayerId: l'idientifiant du joueur qui possède cette quête.
343 |
344 |
345 |
Note: l'identifiant du joueur est toujours
0 et celui de son adversaire
1.
346 |
347 |
348 |
349 |
350 |
351 |
Sortie pour un tour de modification
352 |
353 |
354 | -
355 | PUSH id direction où id est compris entre 0
356 | et 6, et où direction vaut UP, DOWN,
357 | LEFT ou RIGHT.
358 |
359 |
360 | Exemple:
PUSH 3 UP poussera la quatrième colonne vers le haut.
361 |
362 |
Sortie pour un tour de déplacement
363 |
364 |
365 | -
366 | MOVE direction où direction vaut UP,
367 | DOWN, LEFT ou RIGHT.
368 |
369 | -
370 | PASS pour passer ton tour.
371 |
372 |
373 | Une action de déplacement (
MOVE) peut inclure jusqu'à
20 directions, les directions étant séparées par un
374 | espace
.
375 | Exemple:
MOVE LEFT UP RIGHT déplacera le joueur à gauche, puis vers le haut, puis vers la droite.
376 |
377 |
378 |
379 |
380 |
381 |
Contraintes
382 |
383 |
largeur du plateau =
7
384 |
hauteur du plateau =
7
385 |
386 |
numPlayerCards =
1
387 |
0 ≤
numItems ≤
2
388 |
0 ≤
numQuests ≤
2
389 |
390 |
391 |
394 | 0 ≤ numPlayerCards ≤ 6
395 | 0 ≤ numItems ≤ 12
396 | 0 ≤ numQuests ≤ 2
397 |
398 |
399 |
400 |
403 | 0 ≤ numPlayerCards ≤ 12
404 | 0 ≤ numItems ≤ 24
405 | 0 ≤ numQuests ≤ 6
406 |
407 |
408 |
409 |
0 ≤
numPlayerCards ≤
12
410 |
0 ≤
numItems ≤
24
411 |
0 ≤
numQuests ≤
6
412 |
413 |
414 |
415 | Temps de réponse pour le premier tour ≤
1s
416 | Temps de réponse pour un tour de jeu ≤
50ms
417 |
418 |
419 |
420 |
421 |
426 |
427 |

428 |
429 |
430 | Qu'est-ce qui vous attend dans les ligues supérieures ?
431 |
432 |
433 | Voici les règles supplémentaires à débloquer dans les ligues supérieures :
434 |
435 |
436 | - En ligue Bois 1, chaque joueur doit terminer 6 quêtes. 1 quête au maximum est révélée.
437 |
438 |
439 | - En ligue Bronze, chaque joueur doit terminer 12 quêtes. 3 quêtes au maximum sont révélées.
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
--------------------------------------------------------------------------------
/config/stub.txt:
--------------------------------------------------------------------------------
1 | gameloop
2 | read turnType:int
3 | loop 7
4 | loopline 7 tile:word(4)
5 | loop 2
6 | read numPlayerCards:int playerX:int playerY:int playerTile:word(4)
7 | read numItems:int
8 | loop numItems
9 | read itemName:word(10) itemX:int itemY:int itemPlayerId:int
10 | read numQuests:int
11 | loop numQuests
12 | read questItemName:word(10) questPlayerId:int
13 | write PUSH 3 RIGHT
14 |
15 | INPUT
16 | numPlayerCards: the total number of quests for a player (hidden and revealed)
17 | numItems: the total number of items available on board and on player tiles
18 | numQuests: the total number of revealed quests for both players
19 |
20 | STATEMENT
21 | Help the Christmas elves fetch presents in a magical labyrinth!
22 |
23 | OUTPUT
24 | PUSH | MOVE | PASS
25 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.codingame.game
6 | Xmas-Rush
7 | 1.0-SNAPSHOT
8 |
9 |
10 | 2.15
11 | 1.8
12 | 1.8
13 |
14 |
15 |
16 |
17 | com.codingame.gameengine
18 | core
19 | ${gamengine.version}
20 |
21 |
22 |
23 | com.codingame.gameengine
24 | module-entities
25 | ${gamengine.version}
26 |
27 |
28 |
29 | com.codingame.gameengine
30 | runner
31 | ${gamengine.version}
32 |
33 |
34 |
35 | junit
36 | junit
37 | 4.12
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/InputActions/Action.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | public abstract class Action {
4 | private final Type type;
5 |
6 | public Action(Type type) {
7 | this.type = type;
8 | }
9 |
10 | //The type of an input action.
11 | public enum Type {
12 | PUSH(0),
13 | MOVE(1),
14 | PASS(2);
15 |
16 | private int value;
17 |
18 | Type(int value) {
19 | this.value = value;
20 | }
21 |
22 | public int getValue() {
23 | return value;
24 | }
25 | }
26 |
27 | public Type getType() {
28 | return type;
29 | }
30 |
31 | public boolean isLegalAction(Action.Type turnType) {
32 | return turnType.equals(type) ||
33 | turnType.equals(Type.MOVE) && type.equals(Type.PASS);
34 | }
35 |
36 | public boolean isPassAction(){
37 | return type.equals(Type.PASS);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/InputActions/InvalidAction.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | /**
4 | * Invalid action input exception
5 | */
6 | public class InvalidAction extends Exception {
7 | /**
8 | * The fatal value says if a player should be disqualified then the exception happens.
9 | */
10 | private boolean isFatal;
11 |
12 | /**
13 | * Creates an invalid action exception that is fatal by default.
14 | * @param message The exception message.
15 | */
16 | public InvalidAction(String message) {
17 | super(message);
18 | this.isFatal = true;
19 | }
20 |
21 | /**
22 | * Creates an invalid action exception with fatal information.
23 | * @param message The exception message.
24 | * @param isFatal Says if the exception is fatal and the player should be disqualified.
25 | */
26 | public InvalidAction(String message, boolean isFatal) {
27 | super(message);
28 | this.isFatal = isFatal;
29 | }
30 |
31 | /**
32 | * @return true if the exception is fatal and the player should be disqualified.
33 | * false otherwise.
34 | */
35 | public boolean isFatal() {
36 | return isFatal;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/InputActions/MoveAction.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | import com.codingame.game.Utils.Constants;
4 |
5 | import java.util.ArrayDeque;
6 | import java.util.Deque;
7 |
8 | public class MoveAction extends Action {
9 | private Deque steps;
10 |
11 | public MoveAction(Action.Type type) {
12 | super(type);
13 | this.steps = new ArrayDeque<>(Constants.MAX_MOVE_STEPS);
14 | }
15 |
16 | public void addStep(Constants.Direction direction) {
17 | steps.add(direction);
18 | }
19 |
20 | public Constants.Direction getStep() {
21 | return steps.pollFirst();
22 | }
23 |
24 | public void setEmpty() {
25 | steps.clear();
26 | }
27 |
28 | public boolean isEmpty() {
29 | return steps.isEmpty();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/InputActions/PassAction.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | public class PassAction extends Action {
4 |
5 | public PassAction(Action.Type type) {
6 | super(type);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/InputActions/PushAction.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | import com.codingame.game.Utils.Constants;
4 |
5 | import java.util.List;
6 |
7 | public class PushAction extends Action {
8 | private int line;
9 | private Constants.Direction direction;
10 |
11 | public PushAction(int line, Constants.Direction direction, Action.Type type) {
12 | super(type);
13 | assert line >= 0 && line < Constants.MAP_SIZE;
14 | this.line = line;
15 | this.direction = direction;
16 | }
17 |
18 | public int getLine() {
19 | return line;
20 | }
21 |
22 | public Constants.Direction getDirection() {
23 | return direction;
24 | }
25 |
26 | public boolean isHorizontal() {
27 | return direction == Constants.Direction.RIGHT ||
28 | direction == Constants.Direction.LEFT;
29 | }
30 |
31 | //assumes actions is a list of size two
32 | //and both actions are either horizontal or vertical
33 | public static boolean pushSameLine(List actions) {
34 | assert actions.size() == 2;
35 | assert (actions.get(0).isHorizontal() && actions.get(1).isHorizontal()) ||
36 | (!actions.get(0).isHorizontal() && !actions.get(1).isHorizontal());
37 | return actions.get(0).line == actions.get(1).line;
38 | }
39 |
40 | //used for arrow updates
41 | public String toString() {
42 | return line + "" + direction.asValue();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/AbstractModel.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import java.util.Observable;
4 |
5 | import com.codingame.game.Utils.Vector2;
6 |
7 | public abstract class AbstractModel extends Observable {
8 | private Vector2 pos;
9 |
10 | public AbstractModel(Vector2 pos) {
11 | this.pos = new Vector2(pos);
12 | }
13 |
14 | public void setPos(Vector2 pos) {
15 | this.pos = new Vector2(pos);
16 | }
17 |
18 | public Vector2 getPos() {
19 | return new Vector2(pos);
20 | }
21 |
22 | public void updateState(Object update) {
23 | this.setChanged();
24 | this.notifyObservers(update);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/CardModel.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import com.codingame.game.Model.StateUpdates.CardPositionUpdate;
4 | import com.codingame.game.Model.StateUpdates.FlipCardUpdate;
5 | import com.codingame.game.Model.StateUpdates.RemoveCardUpdate;
6 | import com.codingame.game.Utils.Constants;
7 | import com.codingame.game.Utils.Vector2;
8 |
9 | public class CardModel extends MovingModel {
10 | private final Item item;
11 | public int cardLayer = -1;
12 |
13 | private void checkRep() {
14 | assert getPos().getX() >= 0 && getPos().getX() < Constants.SCREEN_WIDTH;
15 | assert getPos().getY() >= 0 && getPos().getY() < Constants.SCREEN_HEIGHT;
16 | }
17 |
18 | public CardModel(Item item, Vector2 pos) {
19 | super(pos);
20 | this.item = item;
21 | checkRep();
22 | }
23 |
24 | public Item getItem() {
25 | return item;
26 | }
27 |
28 | public void flip() {
29 | updateState(new FlipCardUpdate());
30 | item.setHighlight();
31 | }
32 |
33 | public void updatePosition() {
34 | updateState(new CardPositionUpdate());
35 | }
36 |
37 | public void setCardLayer(int layer) {
38 | cardLayer = layer;
39 | }
40 |
41 | public void remove() {
42 | updateState(new RemoveCardUpdate());
43 | }
44 |
45 | public String cardToString() {
46 | return item.itemToString();
47 | }
48 |
49 | public String opponentCardToString() {
50 | return item.opponentItemToString();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/GameBoard.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import com.codingame.game.Player;
4 | import com.codingame.game.Utils.Constants;
5 | import com.codingame.game.Utils.Vector2;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | public class GameBoard {
13 | private final Vector2 centerTilePos = new Vector2(Constants.MAP_WIDTH / 2, Constants.MAP_HEIGHT / 2);
14 | private final String[] centerTilePatterns = new String[]{"1111", "1010", "0101"};
15 | private final Vector2 playerBasePos = Constants.PLAYER_POSITIONS.get(Constants.PLAYER_INDEX);
16 | private final String playerBasePattern = "0110";
17 |
18 | private TileModel[][] tiles = new TileModel[Constants.MAP_WIDTH][Constants.MAP_HEIGHT];
19 | private List tilesWithItems = new ArrayList<>();
20 |
21 | private List availablePatterns;
22 |
23 | public GameBoard(List availablePatterns) {
24 | this.availablePatterns = availablePatterns;
25 | String centerTilePattern = centerTilePatterns[Constants.random.nextInt(centerTilePatterns.length)];
26 | setTile(centerTilePos, new TileModel(centerTilePattern, centerTilePos));
27 | setTile(playerBasePos, new TileModel(playerBasePattern, playerBasePos));
28 |
29 | fillEmptyTiles();
30 | }
31 |
32 | //GameBoard generation methods
33 | private void fillEmptyTiles() {
34 | // set up tiles above the secondary diagonal
35 | for (int y = 0; y < Constants.MAP_HEIGHT; y++) {
36 | for (int x = 0; x < Constants.MAP_WIDTH - y; x++) {
37 | Vector2 pos = new Vector2(x, y);
38 | if (getTile(pos) == null) {
39 | String pattern = getRandomAvailablePattern();
40 | TileModel tile = new TileModel(pattern, pos);
41 | int rotTimes = Constants.random.nextInt(3);
42 | tile.rotate(rotTimes);
43 | setTile(x, y, tile);
44 | }
45 | Vector2 oppositePos = getOppositeTilePos(pos);
46 | TileModel oppositeTile = new TileModel(getTile(pos).getPattern(), oppositePos);
47 | oppositeTile.rotate(2); // rotate 180 deg to be symmetric
48 | setTile(oppositePos, oppositeTile);
49 | }
50 | }
51 | }
52 |
53 | private String getRandomAvailablePattern() {
54 | int index = Constants.random.nextInt(availablePatterns.size());
55 | String pattern = availablePatterns.get(index);
56 | availablePatterns.remove(index);
57 | return pattern;
58 | }
59 |
60 | private Vector2 getOppositeTilePos(Vector2 pos) {
61 | return new Vector2(Constants.MAP_WIDTH - pos.getX() - 1,
62 | Constants.MAP_HEIGHT - pos.getY() - 1);
63 | }
64 |
65 | //Item methods
66 | private TileModel getRandomEmptyTile(boolean threeWayTiles) {
67 | int index = Constants.random.nextInt(Constants.MAP_WIDTH * Constants.MAP_HEIGHT);
68 | int x = index / Constants.MAP_WIDTH;
69 | int y = index % Constants.MAP_HEIGHT;
70 | Vector2 pos = new Vector2(x, y);
71 | while (isCenterOrPlayerBase(pos) || getTile(pos).hasItem() ||
72 | //only checks if the tile is 3+ when required
73 | (!getTile(pos).isThreeWayPlus() && threeWayTiles))
74 | return getRandomEmptyTile(threeWayTiles);
75 | return getTile(pos);
76 | }
77 |
78 | public void placeItems(List> itemList, boolean threeWayTiles) {
79 | assert itemList.size() == 2;
80 | assert itemList.get(0).size() == itemList.get(1).size();
81 |
82 | int numItems = itemList.get(0).size();
83 |
84 | for (int i = 0; i < numItems; i++) {
85 | TileModel playerTile = getRandomEmptyTile(threeWayTiles);
86 | TileModel opponentTile = getTile(getOppositeTilePos(playerTile.getPos()));
87 | playerTile.setItem(itemList.get(Constants.PLAYER_INDEX).get(i));
88 | opponentTile.setItem(itemList.get(Constants.OPPONENT_INDEX).get(i));
89 | tilesWithItems.addAll(Arrays.asList(playerTile, opponentTile));
90 | }
91 | Collections.shuffle(tilesWithItems, Constants.random);
92 | }
93 |
94 | public void removeItem(TileModel tile) {
95 | assert tile.hasItem();
96 | tile.removeItem();
97 | tilesWithItems.remove(tile);
98 | }
99 |
100 | //Tile methods
101 | private void setTile(int x, int y, TileModel tile) {
102 | tiles[x][y] = tile;
103 | }
104 |
105 | private void setTile(Vector2 pos, TileModel tile) {
106 | setTile(pos.getX(), pos.getY(), tile);
107 | }
108 |
109 | public TileModel getTile(int x, int y) {
110 | return isValidPos(new Vector2(x, y)) ? tiles[x][y] : null;
111 | }
112 |
113 | public TileModel getTile(Vector2 pos) {
114 | return getTile(pos.getX(), pos.getY());
115 | }
116 |
117 | //Pushing methods
118 | public TileModel pushLine(TileModel pushedTile, int lineId, Constants.Direction dir) {
119 | pushedTile.push(dir);
120 | TileModel popped;
121 | if (dir == Constants.Direction.UP) popped = pushUp(pushedTile, lineId);
122 | else if (dir == Constants.Direction.RIGHT) popped = pushRight(pushedTile, lineId);
123 | else if (dir == Constants.Direction.DOWN) popped = pushDown(pushedTile, lineId);
124 | else popped = pushLeft(pushedTile, lineId);
125 | popped.pop(dir);
126 | return popped;
127 | }
128 |
129 | private TileModel pushUp(TileModel pushedTile, int col) {
130 | int maxRow = Constants.MAP_HEIGHT - 1;
131 | TileModel poppedTile = getTile(col, 0);
132 |
133 | for (int i = 0; i < maxRow; i++) {
134 | setTile(col, i, getTile(col,i + 1));
135 | getTile(col, i).move(Constants.Direction.UP);
136 | }
137 | setTile(col, maxRow, pushedTile);
138 | getTile(col, maxRow).move(new Vector2(col, maxRow));
139 |
140 | return poppedTile;
141 | }
142 |
143 | private TileModel pushRight(TileModel pushedTile, int row) {
144 | int maxCol = Constants.MAP_WIDTH - 1;
145 | TileModel poppedTile = getTile(maxCol, row);
146 |
147 | for (int i = maxCol; i > 0; i--) {
148 | setTile(i, row, getTile(i - 1, row));
149 | getTile(i, row).move(Constants.Direction.RIGHT);
150 | }
151 | setTile(0, row, pushedTile);
152 | getTile(0, row).move(new Vector2(0, row));
153 | return poppedTile;
154 | }
155 |
156 | private TileModel pushDown(TileModel pushedTile, int col) {
157 | int maxRow = Constants.MAP_HEIGHT - 1;
158 | TileModel poppedTile = getTile(col, maxRow);
159 |
160 | for (int i = maxRow; i > 0; i--) {
161 | setTile(col, i, getTile(col,i - 1));
162 | getTile(col, i).move(Constants.Direction.DOWN);
163 | }
164 | setTile(col, 0, pushedTile);
165 | getTile(col, 0).move(new Vector2(col, 0));
166 | return poppedTile;
167 | }
168 |
169 | private TileModel pushLeft(TileModel pushedTile, int row) {
170 | int maxCol = Constants.MAP_WIDTH - 1;
171 | TileModel poppedTile = getTile(0, row);
172 | for (int i = 0; i < maxCol; i++) {
173 | setTile(i, row, getTile(i + 1, row));
174 | getTile(i, row).move(Constants.Direction.LEFT);
175 | }
176 | setTile(maxCol, row, pushedTile);
177 | getTile(maxCol, row).move(new Vector2(maxCol, row));
178 | return poppedTile;
179 | }
180 |
181 | //Checkers
182 | public boolean isValidMove(Vector2 pos, Constants.Direction direction) {
183 | Vector2 newPos = new Vector2(pos);
184 | if (getTile(newPos).hasDirection(direction)) {
185 | newPos.add(direction.asVector());
186 | if (isValidPos(newPos) && getTile(newPos).hasDirection(direction.getOpposite()))
187 | return true;
188 | }
189 | return false;
190 | }
191 |
192 | private boolean isValidPos(Vector2 pos) {
193 | return (pos.getX() >= 0 && pos.getY() >= 0 &&
194 | pos.getX() < Constants.MAP_WIDTH && pos.getY() < Constants.MAP_HEIGHT);
195 | }
196 |
197 | private boolean isCenterOrPlayerBase(Vector2 pos) {
198 | return pos.equals(centerTilePos) ||
199 | Constants.PLAYER_POSITIONS.contains(pos);
200 | }
201 |
202 | //Player input methods
203 | public void sendMapToPlayer(Player player) {
204 | for (int y = 0; y < Constants.MAP_HEIGHT; y++) {
205 | StringBuilder sb = new StringBuilder();
206 | sb.append(getTile(0, y).patternToString());
207 | for (int x = 1; x < Constants.MAP_WIDTH; x++) {
208 | sb.append(" " + getTile(x, y).patternToString());
209 | }
210 | player.sendInputLine(sb.toString());
211 | }
212 | }
213 |
214 | public void sendItemsToPlayer(Player player) {
215 | int numItems = tilesWithItems.size();
216 |
217 | player.sendInputLine(Integer.toString(numItems));
218 | for (TileModel tile : tilesWithItems) {
219 | if (player.getIndex() == Constants.PLAYER_INDEX)
220 | player.sendInputLine(tile.tileToString());
221 | else
222 | player.sendInputLine(tile.opponentTileToString());
223 | }
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/Item.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import com.codingame.game.Utils.Constants;
4 |
5 | /**
6 | * Item is an immutable type representing the icon that can appear on a tile or card.
7 | * Each item is uniquely identified by its name and id of the player it can be acquired by.
8 | */
9 | public class Item {
10 | private final String name;
11 | private final int playerId;
12 | private boolean highlight = false;
13 | private int highlightColor;
14 |
15 | private void checkRep() {
16 | assert name != null;
17 | assert Constants.ITEM_NAMES.contains(name);
18 | assert playerId == Constants.PLAYER_INDEX || playerId == Constants.OPPONENT_INDEX;
19 | }
20 |
21 | public Item(String name, int playerId) {
22 | this.name = name;
23 | this.playerId = playerId;
24 | checkRep();
25 | }
26 |
27 | public String getName() {
28 | return this.name;
29 | }
30 |
31 | public int getPlayerId() {
32 | return this.playerId;
33 | }
34 |
35 | public int getOpponentId() {
36 | return (playerId == Constants.PLAYER_INDEX) ? Constants.OPPONENT_INDEX : Constants.PLAYER_INDEX;
37 | }
38 |
39 | //highlight methods
40 | public boolean getHighlight() {
41 | return highlight;
42 | }
43 |
44 | public void setHighlight() {
45 | highlight = true;
46 | }
47 |
48 | public int getHighlightColor() {
49 | return highlightColor;
50 | }
51 |
52 | public void setHighlightColor(int color) {
53 | highlightColor = color;
54 | }
55 |
56 |
57 | public boolean equals(Object obj) {
58 | if (!(obj instanceof Item)) {
59 | return false;
60 | }
61 | Item other = (Item)obj;
62 | return this.name.equals(other.name) &&
63 | this.playerId == other.playerId;
64 | }
65 |
66 | public int hashCode() {
67 | int result = 17;
68 | result = 37 * result + playerId;
69 | result = 37 * result + name.hashCode();
70 | return result;
71 | }
72 |
73 | public String itemToString() {
74 | return name + " " + playerId;
75 | }
76 |
77 | public String toTooltip() {
78 | return "item: " + itemToString();
79 | }
80 |
81 | public String opponentItemToString() {
82 | return name + " " + getOpponentId();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/MovingModel.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import com.codingame.game.Utils.Constants;
4 | import com.codingame.game.Utils.Vector2;
5 |
6 | public abstract class MovingModel extends AbstractModel{
7 |
8 | public MovingModel(Vector2 pos) {
9 | super(pos);
10 | }
11 |
12 | //move to a pos
13 | public void move(Vector2 pos) {
14 | super.setPos(pos);
15 | }
16 |
17 | //move in the specified direction
18 | public void move(Constants.Direction direction) {
19 | Vector2 pos = getPos();
20 | pos.add(direction.asVector());
21 | move(pos);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/PlayerModel.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import com.codingame.game.Player;
4 | import com.codingame.game.Utils.Constants;
5 | import com.codingame.game.Utils.Vector2;
6 |
7 | import java.util.*;
8 |
9 | public class PlayerModel extends MovingModel {
10 | public final int id;
11 | public final int orientation;
12 | private final Vector2 tilePos;
13 | private final Stack hiddenCards = new Stack<>();
14 | private final List visibleCards = new ArrayList<>();
15 |
16 | private final int maxNumCards = 3; //max number of cards to show
17 | private int numVisibleCards;
18 | private final Vector2 deckPosition;
19 | private final Vector2 cardPosition;
20 |
21 | private TileModel tile;
22 |
23 | public PlayerModel(int id) {
24 | super(Constants.PLAYER_POSITIONS.get(id));
25 | this.id = id;
26 | orientation = (id == 0) ? 1 : -1;
27 | deckPosition = new Vector2(Constants.DECK_POSITIONS.get(id));
28 | cardPosition = new Vector2(Constants.CARD_POSITIONS.get(id));
29 | tilePos = Constants.TILE_MODEL_POSITIONS.get(id);
30 | }
31 |
32 | //Tile methods
33 | public void setTile(TileModel tile) {
34 | removeTile();
35 | this.tile = tile;
36 | this.tile.setPos(tilePos);
37 | tile.setPlayerId(id);
38 | }
39 |
40 | private void removeTile() {
41 | if (tile != null)
42 | tile.setPlayerId(null);
43 | }
44 |
45 | public TileModel getTile() {
46 | return this.tile;
47 | }
48 |
49 | //Card methods
50 | public void setCards(List- itemList) {
51 | //check if all items are unique
52 | assert itemList.size() == new HashSet<>(itemList).size();
53 |
54 | Vector2 cardPos = new Vector2(deckPosition);
55 | for (Item item : itemList) {
56 | CardModel card = new CardModel(item, cardPos);
57 | //check if item belongs to the player
58 | assert card.getItem().getPlayerId() == id;
59 | hiddenCards.add(card);
60 | }
61 | }
62 |
63 | public List getCards() {
64 | return Collections.unmodifiableList(hiddenCards);
65 | }
66 |
67 | public void setNumVisibleCards(int numVisibleCards) {
68 | this.numVisibleCards = (numVisibleCards <= maxNumCards) ? numVisibleCards : maxNumCards;
69 | }
70 |
71 | private void adjustCardsPosition() {
72 | if (visibleCards.isEmpty()) {
73 | return;
74 | }
75 | int orientation = (id == 0) ? 1 : -1;
76 | Vector2 cardPos = new Vector2(cardPosition);
77 | int layer = 0;
78 | for (int i = 0; i < visibleCards.size(); i++) {
79 | CardModel card = visibleCards.get(i);
80 | card.move(cardPos);
81 | card.updatePosition();
82 | layer++;
83 | card.setCardLayer(layer);
84 | cardPos.setX(cardPos.getX() + orientation * (Constants.CARD_SIZE + Constants.CARDS_OFFSET_X));
85 | }
86 | }
87 |
88 | private int getNumCards() {
89 | return hiddenCards.size() + visibleCards.size();
90 | }
91 |
92 | public int getNumDeckCards() {
93 | return hiddenCards.size();
94 | }
95 |
96 | public int getNumQuestCards() {
97 | return visibleCards.size();
98 | }
99 |
100 | public boolean removeCard(Item item){
101 | for (CardModel card : visibleCards) {
102 | if (item.equals(card.getItem())) {
103 | card.remove();
104 | visibleCards.remove(card);
105 | adjustCardsPosition();
106 | return true;
107 | }
108 | }
109 | return false;
110 | }
111 |
112 | private void flipCard() {
113 | if (!hiddenCards.isEmpty()) {
114 | CardModel card = hiddenCards.pop();
115 | card.flip();
116 | visibleCards.add(card);
117 | }
118 | }
119 |
120 | //Flip the number of cards required to have the specified number of visible cards
121 | public void flipCards() {
122 | if (visibleCards.size() < numVisibleCards) {
123 | int availableCards = Math.min(numVisibleCards - visibleCards.size(), hiddenCards.size());
124 | for (int i = 0; i < availableCards; i++) {
125 | flipCard();
126 | }
127 | adjustCardsPosition();
128 | }
129 | }
130 |
131 | //Player input methods
132 | public String playerToString() {
133 | return getNumCards() + " " + getPos().toString() + " " + tile.patternToString();
134 | }
135 |
136 | public void sendCardsToPlayer(Player player) {
137 | for (CardModel card : visibleCards) {
138 | if (player.getIndex() == Constants.PLAYER_INDEX)
139 | player.sendInputLine(card.cardToString());
140 | else
141 | player.sendInputLine(card.opponentCardToString());
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/StateUpdates/CardPositionUpdate.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model.StateUpdates;
2 |
3 | public class CardPositionUpdate {}
4 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/StateUpdates/FlipCardUpdate.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model.StateUpdates;
2 |
3 | public class FlipCardUpdate {}
4 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/StateUpdates/PoppedUpdate.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model.StateUpdates;
2 |
3 | import com.codingame.game.Utils.Constants.Direction;
4 |
5 | public class PoppedUpdate {
6 | private Direction direction;
7 |
8 | public PoppedUpdate(Direction direction) {
9 | this.direction = direction;
10 | }
11 |
12 | public Direction getDirection() {
13 | return direction;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/StateUpdates/PushedUpdate.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model.StateUpdates;
2 |
3 | import com.codingame.game.Utils.Constants.Direction;
4 |
5 | public class PushedUpdate {
6 | private Direction direction;
7 |
8 | public PushedUpdate(Direction direction) {
9 | this.direction = direction;
10 | }
11 |
12 | public Direction getDirection() {
13 | return direction;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/StateUpdates/RemoveCardUpdate.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model.StateUpdates;
2 |
3 | public class RemoveCardUpdate {}
4 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/StateUpdates/RemoveItemUpdate.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model.StateUpdates;
2 |
3 | public class RemoveItemUpdate {}
4 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/StateUpdates/ShowFrameUpdate.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model.StateUpdates;
2 |
3 | public class ShowFrameUpdate {}
4 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Model/TileModel.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import com.codingame.game.Model.StateUpdates.PoppedUpdate;
4 | import com.codingame.game.Model.StateUpdates.PushedUpdate;
5 | import com.codingame.game.Model.StateUpdates.RemoveItemUpdate;
6 | import com.codingame.game.Model.StateUpdates.ShowFrameUpdate;
7 | import com.codingame.game.Utils.Constants;
8 | import com.codingame.game.Utils.Constants.Direction;
9 | import com.codingame.game.Utils.Vector2;
10 |
11 | public class TileModel extends MovingModel{
12 | private static final int PATTERN_LENGTH = 4;
13 |
14 | private String pattern;
15 | private Item item;
16 |
17 | private Integer playerId;
18 |
19 | //pattern represents path directions (up, right, down, left) as 4 binary digits (1 for path, 0 for no path)
20 | private void checkRep() {
21 | assert pattern != null && pattern.matches("[0-1]{" + PATTERN_LENGTH + "}");
22 | }
23 |
24 | public TileModel(String pattern, Vector2 pos) {
25 | super(pos);
26 | this.pattern = pattern;
27 | checkRep();
28 | }
29 |
30 | //Player-related methods
31 | public void setPlayerId(Integer id) {
32 | playerId = id;
33 | }
34 |
35 | public Integer getPlayerId() {
36 | return playerId;
37 | }
38 |
39 | //Item methods
40 | public void setItem(Item item) {
41 | assert this.item == null;
42 | this.item = item;
43 | }
44 |
45 | public Item getItem() {
46 | return item;
47 | }
48 |
49 | public void removeItem() {
50 | assert item != null;
51 | item = null;
52 | updateState(new RemoveItemUpdate());
53 | }
54 |
55 | public boolean hasItem() {
56 | return item != null;
57 | }
58 |
59 | //Pattern methods
60 | public String getPattern() {
61 | return pattern;
62 | }
63 |
64 | public boolean hasDirection(Constants.Direction direction) {
65 | return pattern.charAt(direction.asValue()) == '1';
66 | }
67 |
68 | public void rotate(int numTimes) {
69 | int num = numTimes % PATTERN_LENGTH;
70 | pattern = pattern.substring(PATTERN_LENGTH - num)
71 | + pattern.substring(0, PATTERN_LENGTH - num);
72 | }
73 |
74 | //check if it's a 3- or 4-way tile
75 | public boolean isThreeWayPlus() {
76 | return this.getPattern().chars().filter(ch -> ch == '1').count() >= 3;
77 | }
78 |
79 | //Player input methods
80 | public String patternToString() {
81 | return pattern;
82 | }
83 |
84 | public String tileToString() {
85 | return item != null ? item.getName() + " " + getTilePos().toString() + " " + item.getPlayerId() : "";
86 | }
87 |
88 | public String opponentTileToString() {
89 | assert item != null;
90 | return item.getName() + " " + getOpponentTilePos().toString() + " " + item.getOpponentId();
91 | }
92 |
93 | private Vector2 getOpponentTilePos() {
94 | if (playerId != null)
95 | return Constants.TILE_MODEL_POSITIONS.get(1 - playerId);
96 | return this.getPos();
97 | }
98 |
99 | private Vector2 getTilePos() {
100 | if (playerId != null)
101 | return Constants.TILE_MODEL_POSITIONS.get(playerId);
102 | return this.getPos();
103 | }
104 |
105 | @Override
106 | public void move(Vector2 pos) {
107 | super.setPos(pos);
108 | updateState(new ShowFrameUpdate());
109 | }
110 | public void push(Direction direction) {
111 | updateState(new PushedUpdate(direction));
112 | }
113 | public void pop(Direction direction) {
114 | updateState(new PoppedUpdate(direction));
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Player.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game;
2 |
3 | import com.codingame.game.Model.PlayerModel;
4 | import com.codingame.gameengine.core.AbstractMultiplayerPlayer;
5 |
6 | public class Player extends AbstractMultiplayerPlayer {
7 | private int expectedOutputLines;
8 | private PlayerModel player;
9 |
10 | @Override
11 | public int getExpectedOutputLines() {
12 | return expectedOutputLines;
13 | }
14 |
15 | public void setExpectedOutputLines(int expectedOutputLines) {
16 | this.expectedOutputLines = expectedOutputLines;
17 | }
18 |
19 | public PlayerModel createPlayer() {
20 | player = new PlayerModel(this.getIndex());
21 | return player;
22 | }
23 |
24 | public PlayerModel getPlayer() {
25 | return player;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Utils/Constants.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Utils;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.Random;
7 | import java.util.regex.Pattern;
8 |
9 | public class Constants {
10 | public static Random random;
11 |
12 | public static final int SCREEN_WIDTH = 1920;
13 | public static final int SCREEN_HEIGHT = 1080;
14 |
15 | public static final int TILE_SIZE = 128;
16 | public static final int TILES_OFFSET = 5;
17 |
18 | public static final int MAP_SIZE = 7;
19 | public static final int MAP_WIDTH = MAP_SIZE;
20 | public static final int MAP_HEIGHT = MAP_SIZE;
21 |
22 | public static final int MAP_POS_X = SCREEN_WIDTH / 2 - (MAP_HEIGHT * TILE_SIZE) / 2
23 | + TILE_SIZE / 2 - TILES_OFFSET / 2 * MAP_HEIGHT;
24 | public static final int MAP_POS_Y = SCREEN_HEIGHT / 2 - (MAP_WIDTH * TILE_SIZE) / 2
25 | + TILE_SIZE / 2 - TILES_OFFSET / 2 * MAP_WIDTH;
26 |
27 | public static final int DECK_OFFSET = 13;
28 | public static final int CARD_SIZE = 100;
29 | public static final int CARDS_OFFSET_X = 5;
30 |
31 | //horizontal coordinates for players' stuff
32 | public static final int PLAYER_CARD_POS_X = (MAP_POS_X - TILE_SIZE / 2) / 2;
33 | public static final int OPPONENT_CARD_POS_X = SCREEN_WIDTH - PLAYER_CARD_POS_X;
34 |
35 | public static final int PLAYER_CARD_POS_Y = MAP_POS_Y;
36 | public static final int OPPONENT_CARD_POS_Y = SCREEN_HEIGHT - PLAYER_CARD_POS_Y;
37 |
38 | public static final int PLAYER_DECK_POS_X = (MAP_POS_X - TILE_SIZE / 2) / 2;
39 | public static final int OPPONENT_DECK_POS_X = SCREEN_WIDTH - PLAYER_DECK_POS_X;
40 |
41 | public static final int PLAYER_DECK_POS_Y = PLAYER_CARD_POS_Y + CARD_SIZE + DECK_OFFSET;
42 | public static final int OPPONENT_DECK_POS_Y = SCREEN_HEIGHT - PLAYER_DECK_POS_Y;
43 |
44 | public static final int PLAYER_TILE_POS_Y = SCREEN_HEIGHT / 2;
45 | public static final int OPPONENT_TILE_POS_Y = SCREEN_HEIGHT - PLAYER_TILE_POS_Y;
46 |
47 | public static final List ITEM_NAMES = Arrays.asList(
48 | "ARROW", "BOOK", "CANE", "CANDY", "DIAMOND", "FISH", "MASK", "KEY", "POTION", "SCROLL", "SHIELD", "SWORD"
49 | );
50 |
51 | public static final List
> TILE_PATTERNS = new ArrayList<>(Arrays.asList(
52 | Arrays.asList("1111", "1111", "1111", "1111", "1111", "1111", "1111", "1111",
53 | "1111", "1111", "1111", "1111", "1111", "1111", "1111", "1111",
54 | "1111", "1111", "1111", "1111", "1111", "1111", "1111", "1111"),
55 |
56 | Arrays.asList("0110", "0110", "0110", "0110", "0110", "0110", "0110", "0110",
57 | "1101", "1101", "1101", "0111", "0111", "0111", "0111", "0111", "0111",
58 | "1010", "1010", "1010", "1010", "1010", "1010",
59 | "1111"),
60 |
61 | Arrays.asList("0110", "0110", "0110", "0110", "0110", "0110", "0110", "0110",
62 | "1101", "1101", "1101", "0111", "0111", "0111", "0111",
63 | "1010", "1010", "1010", "1010", "1010", "1010", "1010", "1010", "1010"),
64 |
65 | Arrays.asList("0110", "0110", "0110", "0110", "0110", "0110", "0110", "0110", "0110", "0110",
66 | "1101", "1101", "1101", "0111", "0111",
67 | "1010", "1010", "1010", "1010", "1010", "1010", "1010", "1010", "1010")
68 | ));
69 |
70 | public static final int PLAYER_INDEX = 0;
71 | public static final int OPPONENT_INDEX = 1;
72 | public static final int NUM_PLAYERS = 2;
73 |
74 | public static final List PLAYER_POSITIONS = Arrays.asList(
75 | new Vector2(0, 0),
76 | new Vector2(MAP_WIDTH - 1, MAP_HEIGHT - 1)
77 | );
78 |
79 | public static final List DECK_POSITIONS = Arrays.asList(
80 | new Vector2(PLAYER_DECK_POS_X, PLAYER_DECK_POS_Y),
81 | new Vector2(OPPONENT_DECK_POS_X, OPPONENT_DECK_POS_Y)
82 | );
83 |
84 | public static final List CARD_POSITIONS = Arrays.asList(
85 | new Vector2(PLAYER_CARD_POS_X, PLAYER_CARD_POS_Y),
86 | new Vector2(OPPONENT_CARD_POS_X, OPPONENT_CARD_POS_Y)
87 | );
88 |
89 | public static final List TILE_POSITIONS = Arrays.asList(
90 | new Vector2(PLAYER_DECK_POS_X, PLAYER_TILE_POS_Y),
91 | new Vector2(OPPONENT_DECK_POS_X, OPPONENT_TILE_POS_Y)
92 | );
93 |
94 | public static final List TILE_MODEL_POSITIONS = Arrays.asList(
95 | Vector2.MINUS_ONE, Vector2.MINUS_TWO);
96 |
97 | //make sure the number of GAME turns is EVEN for equal number of PUSH and MOVE turns
98 | public static final int MAX_GAME_TURNS = 150;
99 | public static final int MAX_MOVE_STEPS = 20;
100 | public static final int MAX_INPUT_LENGTH = 124;
101 |
102 | public static final Pattern PLAYER_INPUT_PUSH_PATTERN = Pattern
103 | .compile("(?\\bPUSH\\b) (?[ 0-" + (MAP_SIZE - 1) + "]) (?(\\bUP\\b|\\bRIGHT\\b|\\bDOWN\\b|\\bLEFT\\b))");
104 | public static final Pattern PLAYER_INPUT_MOVE_PATTERN = Pattern
105 | .compile(String.format("(?:\\bMOVE\\b)((?: )(?(\\bUP\\b|\\bRIGHT\\b|\\bDOWN\\b|\\bLEFT\\b))){1,%d}", MAX_MOVE_STEPS));
106 | public static final Pattern PLAYER_INPUT_MOVE_MAX_STEPS_PATTERN = Pattern
107 | .compile(String.format("(?:\\bMOVE\\b)((?: )(?(\\bUP\\b|\\bRIGHT\\b|\\bDOWN\\b|\\bLEFT\\b))){%d,}", MAX_MOVE_STEPS));
108 | public static final Pattern PLAYER_INPUT_MOVE_STEPS_PATTERN = Pattern
109 | .compile("(?(?:\\bUP\\b|\\bRIGHT\\b|\\bDOWN\\b|\\bLEFT\\b))");
110 | public static final Pattern PLAYER_INPUT_PASS_PATTERN = Pattern
111 | .compile("PASS");
112 |
113 | public enum Direction {
114 | UP(Vector2.UP, 0),
115 | RIGHT(Vector2.RIGHT, 1),
116 | DOWN(Vector2.DOWN, 2),
117 | LEFT(Vector2.LEFT, 3);
118 |
119 | private final Vector2 vector;
120 | private final int value;
121 |
122 | Direction(Vector2 vector, int value) {
123 | this.vector = vector;
124 | this.value = value;
125 | }
126 | public Vector2 asVector() {
127 | return vector;
128 | }
129 |
130 | public int asValue() {
131 | return value;
132 | }
133 |
134 | public Direction getOpposite() {
135 | switch(this) {
136 | case UP: return DOWN;
137 | case DOWN: return UP;
138 | case LEFT: return RIGHT;
139 | case RIGHT: return LEFT;
140 | }
141 | return null;
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/Utils/Vector2.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Utils;
2 |
3 | /**
4 | * Vector2 is a mutable type representing a position in x,y coordinates.
5 | */
6 | public class Vector2 {
7 | private int x;
8 | private int y;
9 |
10 | /**
11 | * Constants to be used when sending item positions as input,
12 | * MINUS_ONE for item on player's tile, MINUS_TWO for item on opponent's tile.
13 | */
14 | public static final Vector2 MINUS_ONE = new Vector2(-1, -1);
15 | public static final Vector2 MINUS_TWO = new Vector2(-2, -2);
16 |
17 | /**
18 | * Constants to be used when moving on the map.
19 | */
20 | public static final Vector2 UP = new Vector2(0, -1);
21 | public static final Vector2 DOWN = new Vector2(0, 1);
22 | public static final Vector2 LEFT = new Vector2(-1, 0);
23 | public static final Vector2 RIGHT = new Vector2(1, 0);
24 |
25 | public Vector2(int x, int y) {
26 | this.x = x;
27 | this.y = y;
28 | }
29 |
30 | public Vector2(Vector2 other) {
31 | this.x = other.x;
32 | this.y = other.y;
33 | }
34 |
35 | public void setX(int x) {
36 | this.x = x;
37 | }
38 |
39 | public int getX() {
40 | return x;
41 | }
42 |
43 | public void setY(int y) {
44 | this.y = y;
45 | }
46 |
47 | public int getY() {
48 | return y;
49 | }
50 |
51 | public void add(Vector2 other) {
52 | this.x += other.x;
53 | this.y += other.y;
54 | }
55 |
56 | /**
57 | * Adds all attributes of a given Vector2 object to the current one and wraps around map borders when required.
58 | * @param other the Vector2 object to add to the current one.
59 | */
60 | public void wrap(Vector2 other) {
61 | this.x = (this.x + other.x + Constants.MAP_WIDTH) % Constants.MAP_WIDTH;
62 | this.y = (this.y + other.y + Constants.MAP_HEIGHT) % Constants.MAP_HEIGHT;
63 | }
64 |
65 | public String toString() {
66 | return x + " " + y;
67 | }
68 |
69 | public String toTooltip() {
70 | return "pos: (" + x + ", " + y + ")";
71 | }
72 |
73 | public boolean equals(Object obj) {
74 | if (!(obj instanceof Vector2))
75 | return false;
76 | Vector2 other = (Vector2) obj;
77 | return this.x == other.x && this.y == other.y;
78 | }
79 | public static Vector2 fromMapSpaceToViewSpace(Vector2 pos) {
80 | int x = Constants.MAP_POS_X + pos.getX() * (Constants.TILE_SIZE + Constants.TILES_OFFSET);
81 | int y = Constants.MAP_POS_Y + pos.getY() * (Constants.TILE_SIZE + Constants.TILES_OFFSET);
82 | return new Vector2(x,y);
83 | }
84 | public static Vector2 fromViewSpaceToMapSpace(Vector2 pos) {
85 | int x = (pos.getX() - Constants.MAP_POS_X) / (Constants.TILE_SIZE + Constants.TILES_OFFSET);
86 | int y = (pos.getY() - Constants.MAP_POS_Y) / (Constants.TILE_SIZE + Constants.TILES_OFFSET);
87 | return new Vector2(x,y);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/AbstractView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import java.util.Observable;
4 | import java.util.Observer;
5 |
6 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
7 |
8 | public abstract class AbstractView implements Observer {
9 | protected GraphicEntityModule entityModule;
10 | private boolean disposable = false;
11 |
12 | public AbstractView(GraphicEntityModule entityManager) {
13 | this.entityModule = entityManager;
14 | }
15 |
16 | public abstract void updateView();
17 |
18 | public boolean isDisposable() {
19 | return disposable;
20 | }
21 |
22 | public void doDispose() {
23 | disposable = true;
24 | }
25 |
26 | public void update(Observable observable, Object arg) {}
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/ArrowView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Utils.Constants;
4 | import com.codingame.game.Utils.Vector2;
5 | import com.codingame.gameengine.module.entities.Entity;
6 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
7 | import com.codingame.gameengine.module.entities.Sprite;
8 |
9 | public class ArrowView extends AbstractView {
10 | private final Vector2 pos;
11 | private final double rotation;
12 |
13 | private Sprite sprite;
14 |
15 | public ArrowView(GraphicEntityModule entityModule, Vector2 pos, double rotation) {
16 | super(entityModule);
17 | this.pos = pos;
18 | this.rotation = rotation;
19 |
20 | createArrowView();
21 | }
22 |
23 | private void createArrowView() {
24 | sprite = entityModule.createSprite()
25 | .setImage(String.format("arrow_%d.png", 0))
26 | .setX(pos.getX())
27 | .setY(pos.getY())
28 | .setBaseWidth(Constants.TILE_SIZE)
29 | .setBaseHeight(Constants.TILE_SIZE / 2)
30 | .setAnchor(0.5)
31 | .setZIndex(0)
32 | .setRotation(rotation)
33 | .setVisible(false);
34 | }
35 |
36 | public void updateView() {}
37 |
38 | public void showArrow(int type) {
39 | sprite.setImage(String.format("arrow_%d.png", type))
40 | .setVisible(true);
41 | entityModule.commitEntityState(0, sprite);
42 | }
43 |
44 | public void hideArrow() {
45 | sprite.setVisible(false);
46 | entityModule.commitEntityState(0, sprite);
47 | }
48 |
49 | public Entity getEntity() {
50 | return sprite;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/BoardView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Model.CardModel;
4 | import com.codingame.game.Model.TileModel;
5 | import com.codingame.game.Player;
6 | import com.codingame.game.Utils.Constants;
7 | import com.codingame.game.Utils.Vector2;
8 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
9 | import com.codingame.view.tooltip.TooltipModule;
10 | import com.codingame.gameengine.module.entities.Group;
11 |
12 | import java.util.*;
13 |
14 | public class BoardView extends AbstractView{
15 | private TooltipModule tooltipModule;
16 |
17 | //distance from arrows to tiles
18 | private final int arrowOffset = 100;
19 | //distance between arrows
20 | private final int arrowSpacing = Constants.TILE_SIZE + Constants.TILES_OFFSET;
21 |
22 | private Group group;
23 |
24 | List tiles;
25 | List players;
26 | List cards;
27 | Map arrows;
28 |
29 | List> arrowsToShow = new ArrayList<>();
30 | List arrowsToHide = new ArrayList<>();
31 |
32 | public BoardView(GraphicEntityModule entityModule, TooltipModule tooltipModule){
33 | super(entityModule);
34 | this.tooltipModule = tooltipModule;
35 |
36 | tiles = new ArrayList<>();
37 | players = new ArrayList<>();
38 | cards = new ArrayList<>();
39 | arrows = new HashMap<>();
40 |
41 | this.group = this.entityModule.createGroup()
42 | .setX(0)
43 | .setY(0)
44 | .setVisible(true)
45 | .setZIndex(1)
46 | .setScale(1);
47 |
48 | createArrows();
49 | }
50 |
51 | public TileView createTileView(TileModel tile) {
52 | TileView tileView = new TileView(entityModule, tooltipModule, tile);
53 | group.add(tileView.getEntity().setZIndex(1));
54 | tiles.add(tileView);
55 | return tileView;
56 | }
57 |
58 | public PlayerView createPlayerView(Player player) {
59 | PlayerView playerView = new PlayerView(entityModule, player, player.getPlayer());
60 | group.add(playerView.getEntity().setZIndex(2));
61 | players.add(playerView);
62 | return playerView;
63 | }
64 |
65 | public CardView createCardView(CardModel card) {
66 | CardView cardView = new CardView(entityModule, tooltipModule, card);
67 | //cards are always below tiles
68 | group.add(cardView.getEntity().setZIndex(0));
69 | cards.add(cardView);
70 | return cardView;
71 | }
72 |
73 | public void updateView() {
74 | for (ArrowView arrow : arrowsToHide)
75 | arrow.hideArrow();
76 | arrowsToHide.clear();
77 |
78 | if (arrowsToShow.size() == 2 && isSamePushAction())
79 | //show two arrows pushing the same line
80 | showArrow(new AbstractMap.SimpleEntry<>(arrowsToShow.get(0).getKey(), 2));
81 | else
82 | arrowsToShow.stream().forEach(arrow -> showArrow(arrow));
83 | arrowsToShow.clear();
84 | }
85 |
86 | private boolean isSamePushAction() {
87 | return arrowsToShow.stream()
88 | .map(arrow -> arrow.getKey())
89 | .distinct()
90 | .count() == 1;
91 | }
92 |
93 | private void showArrow(AbstractMap.SimpleEntry arrow) {
94 | String arrowId = arrow.getKey();
95 | Integer arrowType = arrow.getValue();
96 | ArrowView arrowView = arrows.get(arrowId);
97 | arrowView.showArrow(arrowType);
98 | arrowsToHide.add(arrowView);
99 | }
100 |
101 | public void update(AbstractMap.SimpleEntry action) {
102 | arrowsToShow.add(action);
103 | }
104 |
105 | private void createArrows() {
106 | createUpArrows();
107 | createRightArrows();
108 | createDownArrows();
109 | createLeftArrows();
110 | }
111 |
112 | private void createUpArrows() {
113 | Vector2 pos = new Vector2(Constants.MAP_POS_X,
114 | Constants.MAP_POS_Y + arrowSpacing * (Constants.MAP_HEIGHT - 1) + arrowOffset);
115 | for (int x = 0; x < Constants.MAP_WIDTH; x++) {
116 | String id = x + "" + Constants.Direction.UP.asValue();
117 | ArrowView view = new ArrowView(entityModule, pos, Math.toRadians(0));
118 | group.add(view.getEntity().setZIndex(0));
119 | arrows.put(id, view);
120 | pos.setX(pos.getX() + arrowSpacing);
121 | }
122 | }
123 |
124 | private void createRightArrows(){
125 | Vector2 pos = new Vector2(Constants.MAP_POS_X - arrowOffset, Constants.MAP_POS_Y);
126 | for (int y = 0; y < Constants.MAP_HEIGHT; y++){
127 | String id = y + "" + Constants.Direction.RIGHT.asValue();
128 | ArrowView view = new ArrowView(entityModule, pos, Math.toRadians(90));
129 | group.add(view.getEntity().setZIndex(0));
130 | arrows.put(id, view);
131 | pos.setY(pos.getY() + arrowSpacing);
132 | }
133 | }
134 |
135 | private void createDownArrows() {
136 | Vector2 pos = new Vector2(Constants.MAP_POS_X, Constants.MAP_POS_Y - arrowOffset);
137 | for (int x = 0; x < Constants.MAP_WIDTH; x++) {
138 | String id = x + "" + Constants.Direction.DOWN.asValue();
139 | ArrowView view = new ArrowView(entityModule, pos, Math.toRadians(180));
140 | group.add(view.getEntity().setZIndex(0));
141 | arrows.put(id, view);
142 | pos.setX(pos.getX() + arrowSpacing);
143 | }
144 | }
145 |
146 | private void createLeftArrows(){
147 | Vector2 pos = new Vector2(Constants.MAP_POS_X + arrowSpacing * (Constants.MAP_WIDTH - 1) + arrowOffset,
148 | Constants.MAP_POS_Y);
149 | for (int y = 0; y < Constants.MAP_HEIGHT; y++){
150 | String id = y + "" + Constants.Direction.LEFT.asValue();
151 | ArrowView view = new ArrowView(entityModule, pos, Math.toRadians(270));
152 | group.add(view.getEntity().setZIndex(0));
153 | arrows.put(id, view);
154 | pos.setY(pos.getY() + arrowSpacing);
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/CardDeckView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Model.PlayerModel;
4 | import com.codingame.game.Utils.Constants;
5 | import com.codingame.game.Utils.Vector2;
6 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
7 | import com.codingame.gameengine.module.entities.Group;
8 | import com.codingame.gameengine.module.entities.Sprite;
9 | import com.codingame.gameengine.module.entities.Text;
10 |
11 | public class CardDeckView extends AbstractView {
12 | private Sprite back;
13 | private Group group;
14 | private Text numCards;
15 |
16 | private PlayerModel player;
17 | private final Vector2 pos;
18 |
19 | public CardDeckView(GraphicEntityModule entityModule, PlayerModel player) {
20 | super(entityModule);
21 | this.player = player;
22 | pos = new Vector2(Constants.DECK_POSITIONS.get(player.id));
23 | player.addObserver(this);
24 |
25 | createCardDeckView();
26 | }
27 |
28 | private void createCardDeckView() {
29 | back = entityModule.createSprite()
30 | .setImage(String.format("cardBack_%d.png", player.id))
31 | .setBaseWidth(Constants.CARD_SIZE)
32 | .setBaseHeight(Constants.CARD_SIZE)
33 | .setAnchor(0.5)
34 | .setZIndex(0);
35 | numCards = entityModule.createText("")
36 | .setFillColor(0x000000)
37 | .setFontSize(60)
38 | .setAnchor(0.5)
39 | .setZIndex(1);
40 | group = entityModule.createGroup()
41 | .setScale(1)
42 | .setX(0)
43 | .setY(0)
44 | .setZIndex(0);
45 | group.add(back, numCards);
46 | group.setX(pos.getX()).setY(pos.getY());
47 | }
48 |
49 | public void updateView() {
50 | numCards.setText(String.valueOf(player.getNumDeckCards()));
51 | entityModule.commitEntityState(0, numCards);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/CardView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Referee;
4 | import com.codingame.game.Model.CardModel;
5 | import com.codingame.game.Model.Item;
6 | import com.codingame.game.Model.StateUpdates.CardPositionUpdate;
7 | import com.codingame.game.Model.StateUpdates.FlipCardUpdate;
8 | import com.codingame.game.Model.StateUpdates.RemoveCardUpdate;
9 | import com.codingame.game.Utils.Constants;
10 | import com.codingame.gameengine.module.entities.Entity;
11 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
12 | import com.codingame.gameengine.module.entities.Group;
13 | import com.codingame.gameengine.module.entities.Sprite;
14 | import com.codingame.view.tooltip.TooltipModule;
15 |
16 | import java.util.Observable;
17 |
18 | public class CardView extends MovingView {
19 | private TooltipModule tooltipModule;
20 |
21 | private Group group;
22 | private Sprite front;
23 | private Sprite item;
24 |
25 | private Item cardItem;
26 | private CardModel model;
27 |
28 | public CardView(GraphicEntityModule entityModule, TooltipModule tooltipModule, CardModel card) {
29 | super(entityModule);
30 | this.tooltipModule = tooltipModule;
31 | this.model = card;
32 | this.cardItem = model.getItem();
33 | card.addObserver(this);
34 |
35 | createCardView();
36 | tooltipModule.registerEntity(group);
37 | }
38 |
39 | private void createCardView() {
40 | front = entityModule.createSprite()
41 | .setImage(String.format("cardFront_%d.png", cardItem.getPlayerId()))
42 | .setBaseWidth(Constants.CARD_SIZE)
43 | .setBaseHeight(Constants.CARD_SIZE)
44 | .setAnchor(0.5)
45 | .setZIndex(0);
46 | item = entityModule.createSprite()
47 | .setImage(String.format("item_%s_%d", cardItem.getName(), cardItem.getPlayerId()))
48 | .setAnchor(0.5)
49 | .setZIndex(1);
50 | group = entityModule.createGroup()
51 | .setScale(1)
52 | .setX(0)
53 | .setY(0)
54 | .setVisible(false);
55 | group.add(front, item);
56 | }
57 |
58 | public void updateView() {
59 | group.setZIndex(model.cardLayer);
60 | entityModule.commitEntityState(0, group);
61 | group.setX(model.getPos().getX()).setY(model.getPos().getY());
62 | entityModule.commitEntityState(350. / Referee.myGameManager.getFrameDuration(), group);
63 | tooltipModule.updateExtraTooltipText(group, model.getItem().toTooltip());
64 | }
65 |
66 | private void flip() {
67 | group.setVisible(true);
68 | entityModule.commitEntityState(0, group);
69 | }
70 |
71 | private void updatePosition() {
72 | group.setX(model.getPos().getX()).setY(model.getPos().getY());
73 | entityModule.commitEntityState(1, group);
74 | }
75 |
76 | private void removeCardView() {
77 | group.setAlpha(0);
78 | group.setZIndex(group.getZIndex() - 1);
79 | entityModule.commitEntityState(1, group);
80 | doDispose();
81 | }
82 |
83 | public void update(Observable observable, Object update) {
84 | super.update(model, update);
85 | if (update instanceof FlipCardUpdate) {
86 | flip();
87 | } else if (update instanceof CardPositionUpdate) {
88 | updatePosition();
89 | } else if (update instanceof RemoveCardUpdate){
90 | removeCardView();
91 | }
92 | }
93 |
94 | public Entity getEntity() {
95 | return group;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/MovingView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Utils.Vector2;
4 | import com.codingame.gameengine.module.entities.Entity;
5 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
6 |
7 | public abstract class MovingView extends AbstractView {
8 |
9 | public MovingView(GraphicEntityModule entityModule) {
10 | super(entityModule);
11 | }
12 |
13 | public void setMapPos(Entity entity, Vector2 pos) {
14 | Vector2 newPos = Vector2.fromMapSpaceToViewSpace(pos);
15 | entity.setX(newPos.getX()).setY(newPos.getY());
16 | }
17 |
18 | public abstract Entity getEntity();
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/PlayerTextView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Player;
4 | import com.codingame.game.Referee;
5 | import com.codingame.game.Utils.Constants;
6 | import com.codingame.game.Utils.Vector2;
7 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
8 | import com.codingame.gameengine.module.entities.Group;
9 | import com.codingame.gameengine.module.entities.Sprite;
10 | import com.codingame.gameengine.module.entities.Text;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 |
16 | public class PlayerTextView extends AbstractView {
17 | private final int AVATAR_SIZE = Constants.TILE_SIZE;
18 |
19 | private final int PLAYER_INFO_POS_Y = Constants.SCREEN_HEIGHT - 230;
20 | private final int OPPONENT_INFO_POS_Y = Constants.SCREEN_HEIGHT - PLAYER_INFO_POS_Y;
21 |
22 | private List INFO_POS = Arrays.asList(new Vector2(Constants.PLAYER_DECK_POS_X, PLAYER_INFO_POS_Y),
23 | new Vector2(Constants.OPPONENT_DECK_POS_X, OPPONENT_INFO_POS_Y));
24 |
25 | private final int NAME_VERTICAL_OFFSET = 110;
26 | private int BACKGROUND_VERTICAL_OFFSET = 123;
27 | private List BACKGROUND_HORIZONTAL_OFFSET = Arrays.asList(-15, 0);
28 |
29 | private Group group;
30 | private Text name;
31 | private Sprite avatar;
32 | private Sprite background;
33 |
34 | private Player player;
35 | private Vector2 pos;
36 | private int id;
37 | private int orientation;
38 |
39 |
40 | public PlayerTextView(GraphicEntityModule entityModule, Player player){
41 | super(entityModule);
42 | this.player = player;
43 | id = player.getIndex();
44 | pos = INFO_POS.get(id);
45 | orientation = this.player.getPlayer().orientation;
46 |
47 | createPlayerText();
48 | }
49 |
50 | private void createPlayerText() {
51 | avatar = entityModule.createSprite()
52 | .setX(0)
53 | .setY(0)
54 | .setZIndex(1)
55 | .setImage(player.getAvatarToken())
56 | .setBaseWidth(AVATAR_SIZE)
57 | .setBaseHeight(AVATAR_SIZE)
58 | .setAnchor(0.5);
59 | //reconsider the length param when changing font family or font size
60 | name = entityModule.createText(player.getNicknameToken())
61 | .setX(0)
62 | .setY(NAME_VERTICAL_OFFSET * orientation)
63 | .setZIndex(1)
64 | .setFillColor(player.getColorToken())
65 | .setFontSize(40)
66 | .setFontFamily("Arial Black")
67 | .setAnchor(0.5);
68 | Referee.nicksModule.registerNickname(name);
69 | background = entityModule.createSprite()
70 | .setImage(String.format("background_name_%d.png", id))
71 | .setX(BACKGROUND_HORIZONTAL_OFFSET.get(player.getIndex()))
72 | .setY(BACKGROUND_VERTICAL_OFFSET * orientation)
73 | .setZIndex(0)
74 | .setAnchor(0.5);
75 | group = entityModule.createGroup()
76 | .setX(pos.getX())
77 | .setY(pos.getY())
78 | .setScale(1);
79 | group.add(avatar, name, background);
80 | }
81 |
82 | public void updateView() {}
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/PlayerView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Model.PlayerModel;
4 | import com.codingame.game.Player;
5 | import com.codingame.game.Referee;
6 | import com.codingame.game.InputActions.Action;
7 | import com.codingame.gameengine.module.entities.Entity;
8 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
9 | import com.codingame.gameengine.module.entities.Sprite;
10 |
11 | public class PlayerView extends MovingView{
12 | private Sprite sprite;
13 |
14 | private Player player;
15 | private PlayerModel model;
16 |
17 | public PlayerView(GraphicEntityModule entityModule, Player player, PlayerModel model) {
18 | super(entityModule);
19 | this.player = player;
20 | this.model = model;
21 | model.addObserver(this);
22 |
23 | createPlayerView();
24 | }
25 |
26 | private void createPlayerView() {
27 | sprite = entityModule.createSprite()
28 | .setImage(String.format("elf_%d.png", player.getIndex()))
29 | .setAnchor(0.5);
30 | }
31 |
32 | public void updateView(){
33 | if(Referee.turnType == Action.Type.PUSH) {
34 | entityModule.commitEntityState(0.3, sprite);
35 | setMapPos(sprite, model.getPos());
36 | entityModule.commitEntityState(0.6, sprite);
37 | }
38 | setMapPos(sprite, model.getPos());
39 | }
40 |
41 | public Entity getEntity() {
42 | return sprite;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/TileView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Model.Item;
4 | import com.codingame.game.Model.StateUpdates.PoppedUpdate;
5 | import com.codingame.game.Model.StateUpdates.PushedUpdate;
6 | import com.codingame.game.Model.StateUpdates.RemoveItemUpdate;
7 | import com.codingame.game.Model.StateUpdates.ShowFrameUpdate;
8 | import com.codingame.game.Model.TileModel;
9 | import com.codingame.game.Utils.Constants;
10 | import com.codingame.game.Utils.Constants.Direction;
11 | import com.codingame.game.Utils.Vector2;
12 | import com.codingame.gameengine.module.entities.Entity;
13 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
14 | import com.codingame.gameengine.module.entities.Group;
15 | import com.codingame.gameengine.module.entities.Sprite;
16 | import com.codingame.gameengine.module.entities.Circle;
17 | import com.codingame.view.tooltip.TooltipModule;
18 |
19 | import java.util.Observable;
20 |
21 | public class TileView extends MovingView {
22 | private TooltipModule tooltipModule;
23 |
24 | private Group group;
25 |
26 | private Sprite decors;
27 | private Sprite directions;
28 | private Sprite background;
29 | private Sprite frame;
30 | private Group itemGroup;
31 | private Circle itemBackground;
32 |
33 | private boolean showFrame = false;
34 | private boolean highlight = false;
35 |
36 | private Item tileItem;
37 | private TileModel model;
38 | private TileState state = TileState.STILL;
39 |
40 | private enum TileState{
41 | STILL,
42 | MOVED,
43 | POPPED,
44 | PUSHED;
45 | }
46 |
47 | private Direction tempDirection;
48 |
49 | public TileView(GraphicEntityModule entityModule, TooltipModule tooltipModule, TileModel tile) {
50 | super(entityModule);
51 | this.tooltipModule = tooltipModule;
52 | this.model = tile;
53 | this.tileItem = model.getItem();
54 | tile.addObserver(this);
55 |
56 | createTileView();
57 | tooltipModule.registerEntity(group);
58 | }
59 |
60 | private void createTileView() {
61 | decors = entityModule.createSprite()
62 | .setImage(String.format("decors_%s", model.getPattern()))
63 | .setBaseWidth(Constants.TILE_SIZE)
64 | .setBaseHeight(Constants.TILE_SIZE)
65 | .setAnchor(0.5)
66 | .setZIndex(1);
67 | directions = entityModule.createSprite()
68 | .setImage(String.format("paths_%s", model.getPattern()))
69 | .setBaseWidth(Constants.TILE_SIZE)
70 | .setBaseHeight(Constants.TILE_SIZE)
71 | .setAnchor(0.5)
72 | .setZIndex(2);
73 | frame = entityModule.createSprite()
74 | .setImage("frame.png")
75 | .setBaseWidth(Constants.TILE_SIZE)
76 | .setBaseHeight(Constants.TILE_SIZE)
77 | .setAnchor(0.5)
78 | .setZIndex(2)
79 | .setVisible(false);
80 | background = entityModule.createSprite()
81 | .setImage("tile_background.png")
82 | .setBaseWidth(Constants.TILE_SIZE)
83 | .setBaseHeight(Constants.TILE_SIZE)
84 | .setAlpha(0.3)
85 | .setAnchor(0.5)
86 | .setZIndex(0);
87 | group = entityModule.createGroup()
88 | .setScale(1);
89 | group.add(decors, directions, frame, background);
90 |
91 | addItem();
92 | }
93 |
94 | private void addItem() {
95 | if (tileItem != null) {
96 | itemGroup = entityModule.createGroup().setZIndex(2);
97 | itemBackground = entityModule.createCircle()
98 | .setZIndex(0)
99 | .setScale(0.3)
100 | .setAlpha(0.7);
101 | itemGroup.add(itemBackground);
102 | String spritePath = String.format("item_%s_%d", tileItem.getName(), tileItem.getPlayerId());
103 | itemGroup.add(entityModule.createSprite()
104 | .setImage(spritePath)
105 | .setAnchor(0.5)
106 | .setZIndex(1));
107 | group.add(itemGroup);
108 | }
109 | }
110 |
111 | private void removeItem() {
112 | itemGroup.setScale(0);
113 | entityModule.commitEntityState(1, itemGroup);
114 | group.remove(this.itemGroup);
115 | }
116 |
117 | public void updateView(){
118 | if (model.getPlayerId() != null) {
119 | //always show frame for player's tiles
120 | frame.setVisible(true);
121 | entityModule.commitEntityState(0, frame);
122 |
123 |
124 | if (this.state == TileState.POPPED) {
125 | entityModule.commitEntityState(0.3, group);
126 | Vector2 nextPos = Vector2.fromViewSpaceToMapSpace(new Vector2(group.getX(),group.getY()));
127 | nextPos.add(tempDirection.asVector());
128 | setMapPos(group, nextPos);
129 | //player tile is on top of everything
130 | group.setZIndex(4);
131 | entityModule.commitEntityState(0.6, group);
132 |
133 | }
134 | Vector2 pos = Constants.TILE_POSITIONS.get(model.getPlayerId());
135 | group.setX(pos.getX()).setY(pos.getY());
136 | } else {
137 | //only show frames for moving map tiles
138 | if (showFrame) {
139 | frame.setVisible(true);
140 | entityModule.commitEntityState(0, frame);
141 | frame.setVisible(false);
142 | showFrame = false;
143 | }
144 | if (this.state == TileState.PUSHED) {
145 | //player tile is on top of everything
146 | group.setZIndex(4);
147 | entityModule.commitEntityState(0, group);
148 | Vector2 nextPos = new Vector2(model.getPos());
149 | nextPos.add(tempDirection.getOpposite().asVector());
150 | setMapPos(group, nextPos);
151 | entityModule.commitEntityState(0.3, group);
152 | //get pushed tile zIndex back
153 | group.setZIndex(1);
154 | setMapPos(group, model.getPos());
155 | entityModule.commitEntityState(0.6, group);
156 | } else if (this.state == TileState.MOVED) {
157 | entityModule.commitEntityState(0.3, group);
158 | setMapPos(group, model.getPos());
159 | entityModule.commitEntityState(0.6, group);
160 | }
161 | setMapPos(group, model.getPos());
162 |
163 | }
164 |
165 | this.state = TileState.STILL;
166 |
167 | String tooltipText = model.getPos().toTooltip();
168 | if (model.hasItem()) {
169 | //add highlight once
170 | if (!highlight && model.getItem().getHighlight()){
171 | int highlightColor = tileItem.getHighlightColor();
172 | itemBackground.setFillColor(highlightColor);
173 | entityModule.commitEntityState(0, itemBackground);
174 | highlight = true;
175 | }
176 | tooltipText += '\n' + model.getItem().toTooltip();
177 | }
178 | tooltipModule.updateExtraTooltipText(group, tooltipText);
179 | }
180 |
181 | public void update(Observable observable, Object update) {
182 | super.update(model, update);
183 | if (update instanceof RemoveItemUpdate)
184 | removeItem();
185 | else if (update instanceof ShowFrameUpdate) {
186 | showFrame = true;
187 | if(this.state == TileState.STILL) {
188 | this.state = TileState.MOVED;
189 | }
190 | } else if(update instanceof PushedUpdate) {
191 | this.state = TileState.PUSHED;
192 | this.tempDirection = ((PushedUpdate) update).getDirection();
193 | }else if(update instanceof PoppedUpdate) {
194 |
195 | this.state = TileState.POPPED;
196 | this.tempDirection = ((PoppedUpdate) update).getDirection();
197 | }
198 | }
199 |
200 | public Entity getEntity() {
201 | return group;
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/TurnTextView.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Referee;
4 | import com.codingame.game.Utils.Constants;
5 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
6 | import com.codingame.gameengine.module.entities.Text;
7 |
8 | public class TurnTextView extends AbstractView {
9 | private final int TURN_TEXT_POS_X = Constants.SCREEN_WIDTH - 490;
10 | private final int NUM_TURNS_TEXT_POS_X = Constants.SCREEN_WIDTH - 180;
11 | private final int TYPE_TEXT_POS_X = Constants.SCREEN_WIDTH - 160;
12 | private final int TURN_TEXT_POS_Y = 70;
13 |
14 | //import it once
15 | private final int maxTurns = Constants.MAX_GAME_TURNS;
16 |
17 | private Text turnText;
18 | private Text typeText;
19 | private Text numTurnsText;
20 |
21 |
22 | public TurnTextView(GraphicEntityModule entityModule){
23 | super(entityModule);
24 |
25 | createTexts();
26 | }
27 |
28 | private void createTexts() {
29 | turnText = entityModule.createText("")
30 | .setX(TURN_TEXT_POS_X)
31 | .setY(TURN_TEXT_POS_Y)
32 | .setZIndex(2)
33 | .setFontSize(50)
34 | .setFillColor(0xF0EFEF)
35 | .setFontFamily("Arial")
36 | //aligned to the left
37 | .setAnchorX(0)
38 | .setAnchorY(1);
39 | numTurnsText = entityModule.createText("")
40 | .setX(NUM_TURNS_TEXT_POS_X)
41 | .setY(TURN_TEXT_POS_Y)
42 | .setZIndex(2)
43 | .setFontSize(50)
44 | .setFillColor(0xF0EFEF)
45 | .setFontFamily("Arial")
46 | //aligned to the right
47 | .setAnchorX(1)
48 | .setAnchorY(1);
49 | typeText = entityModule.createText("")
50 | .setX(TYPE_TEXT_POS_X)
51 | .setY(TURN_TEXT_POS_Y)
52 | .setZIndex(2)
53 | .setFontSize(50)
54 | .setFillColor(0xF0EFEF)
55 | .setFontFamily("Arial")
56 | //aligned to the left
57 | .setAnchorX(0)
58 | .setAnchorY(1);
59 | }
60 |
61 | public void updateView() {
62 | if (Referee.turnType != null){
63 | turnText.setText("Turn:");
64 | typeText.setText(Referee.turnType.toString());
65 | numTurnsText.setText(String.format("%d/%d", maxTurns - Referee.gameTurnsLeft, maxTurns));
66 | }
67 | entityModule.commitEntityState(0, turnText, numTurnsText, typeText);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/game/View/ViewController.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.View;
2 |
3 | import com.codingame.game.Model.CardModel;
4 | import com.codingame.game.Model.TileModel;
5 | import com.codingame.game.Player;
6 | import com.codingame.game.Referee;
7 | import com.codingame.game.Utils.Constants;
8 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
9 | import com.codingame.view.tooltip.TooltipModule;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public class ViewController {
15 | private List views = new ArrayList<>();
16 | private GraphicEntityModule entityModule;
17 | private TooltipModule tooltipModule;
18 |
19 | private BoardView board;
20 |
21 | public ViewController(GraphicEntityModule entityModule, TooltipModule tooltipModule) {
22 | this.entityModule = entityModule;
23 | this.tooltipModule = tooltipModule;
24 |
25 | this.board = new BoardView(entityModule, tooltipModule);
26 | Referee.setObserver(board);
27 |
28 | initView();
29 | }
30 |
31 | private void initView() {
32 | createBackground();
33 | }
34 |
35 | public void update() {
36 | board.updateView();
37 |
38 | for(AbstractView view : views) {
39 | view.updateView();
40 | }
41 | disposeViews();
42 | }
43 |
44 | private void disposeViews() {
45 | views.removeIf(view -> view.isDisposable());
46 | }
47 |
48 | private void createBackground() {
49 | entityModule.createSprite()
50 | .setImage("background.jpg")
51 | .setBaseWidth(Constants.SCREEN_WIDTH)
52 | .setBaseHeight(Constants.SCREEN_HEIGHT)
53 | .setX(0)
54 | .setY(0)
55 | .setScale(1)
56 | .setAnchor(0)
57 | .setZIndex(-1);
58 | }
59 |
60 | public void createCardView(CardModel card) {
61 | views.add(board.createCardView(card));
62 | }
63 |
64 | public void createCardDeckView(Player player) {
65 | CardDeckView deckView = new CardDeckView(entityModule, player.getPlayer());
66 | views.add(deckView);
67 | }
68 |
69 | public void createTileView(TileModel tile) {
70 | views.add(board.createTileView(tile));
71 | }
72 |
73 | public void createPlayerView(Player player) {
74 | //create view with player name and avatar
75 | views.add(new PlayerTextView(entityModule, player) );
76 | views.add(board.createPlayerView(player));
77 | }
78 |
79 | public void createTextView() {
80 | TurnTextView textView = new TurnTextView(entityModule);
81 | views.add(textView);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/view/endscreen/EndScreenModule.java:
--------------------------------------------------------------------------------
1 | package com.codingame.view.endscreen;
2 |
3 | import com.codingame.gameengine.core.AbstractPlayer;
4 | import com.codingame.gameengine.core.GameManager;
5 | import com.codingame.gameengine.core.Module;
6 | import com.google.inject.Inject;
7 |
8 | public class EndScreenModule implements Module {
9 |
10 | private GameManager gameManager;
11 | private int[] scores;
12 |
13 | @Inject
14 | EndScreenModule(GameManager gameManager) {
15 | this.gameManager = gameManager;
16 | gameManager.registerModule(this);
17 | }
18 |
19 | public void setScores(int[] scores) {
20 | this.scores = scores;
21 | }
22 |
23 | @Override
24 | public final void onGameInit() {
25 | }
26 | @Override
27 | public final void onAfterGameTurn() {
28 | }
29 |
30 | @Override
31 | public final void onAfterOnEnd() {
32 | gameManager.setViewData("endScreen", scores);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/view/nicknameshandler/NicknamesHandlerModule.java:
--------------------------------------------------------------------------------
1 | package com.codingame.view.nicknameshandler;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import com.codingame.game.Player;
7 | import com.codingame.gameengine.core.Module;
8 | import com.codingame.gameengine.core.MultiplayerGameManager;
9 | import com.codingame.gameengine.module.entities.Text;
10 | import com.google.inject.Inject;
11 |
12 | public class NicknamesHandlerModule implements Module {
13 | List nicknames = new ArrayList<>(2);
14 | private MultiplayerGameManager gameManager;
15 |
16 | @Inject
17 | public NicknamesHandlerModule(MultiplayerGameManager gameManager) {
18 | this.gameManager = gameManager;
19 | gameManager.registerModule(this);
20 | }
21 |
22 | @Override
23 | public void onGameInit() {
24 | gameManager.setViewGlobalData("nicks", nicknames.stream().mapToInt(n -> n.getId()).toArray());
25 | }
26 |
27 | public void registerNickname(Text nick) {
28 | nicknames.add(nick);
29 | }
30 |
31 | @Override
32 | public void onAfterGameTurn() {
33 |
34 | }
35 |
36 | @Override
37 | public void onAfterOnEnd() {
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/codingame/view/tooltip/TooltipModule.java:
--------------------------------------------------------------------------------
1 | package com.codingame.view.tooltip;
2 |
3 | import com.codingame.gameengine.core.AbstractPlayer;
4 | import com.codingame.gameengine.core.GameManager;
5 | import com.codingame.gameengine.core.Module;
6 | import com.codingame.gameengine.module.entities.Entity;
7 | import com.codingame.gameengine.module.entities.GraphicEntityModule;
8 | import com.google.inject.Inject;
9 |
10 | import java.util.Arrays;
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | public class TooltipModule implements Module {
15 |
16 | GameManager gameManager;
17 | @Inject
18 | GraphicEntityModule entityModule;
19 | Map> registrations;
20 | Map> newRegistrations;
21 | Map extra, newExtra;
22 |
23 | @Inject
24 | TooltipModule(GameManager gameManager) {
25 | this.gameManager = gameManager;
26 | gameManager.registerModule(this);
27 | registrations = new HashMap<>();
28 | newRegistrations = new HashMap<>();
29 | extra = new HashMap<>();
30 | newExtra = new HashMap<>();
31 | }
32 |
33 | @Override
34 | public void onGameInit() {
35 | sendFrameData();
36 | }
37 |
38 | @Override
39 | public void onAfterGameTurn() {
40 | sendFrameData();
41 | }
42 |
43 | @Override
44 | public void onAfterOnEnd() {
45 | // Do nothing
46 | }
47 |
48 | private void sendFrameData() {
49 | Object[] data = { newRegistrations, newExtra };
50 | gameManager.setViewData("tooltips", data);
51 |
52 | newRegistrations.clear();
53 | newExtra.clear();
54 | }
55 |
56 | public void registerEntity(Entity> entity) {
57 | registerEntity(entity, new HashMap<>());
58 | }
59 |
60 | public void registerEntity(Entity> entity, Map params) {
61 | registerEntity(entity.getId(), params);
62 | }
63 |
64 | public void registerEntity(int id, Map params) {
65 | if (!params.equals(registrations.get(id))) {
66 | newRegistrations.put(id, params);
67 | registrations.put(id, params);
68 | }
69 | }
70 |
71 | boolean deepEquals(String[] a, String[] b) {
72 | return Arrays.deepEquals(a,b);
73 | }
74 |
75 | public Map getParams(int id) {
76 | Map params = registrations.get(id);
77 | if (params == null) {
78 | params = new HashMap<>();
79 | registrations.put(id, params);
80 | }
81 | return params;
82 | }
83 |
84 | public void updateExtraTooltipText(Entity> entity, String... lines) {
85 | int id = entity.getId();
86 | if (!deepEquals(lines, extra.get(id))) {
87 | newExtra.put(id, lines);
88 | extra.put(id, lines);
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/resources/view/assets/arrow_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/arrow_0.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/arrow_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/arrow_1.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/arrow_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/arrow_2.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/background.jpg
--------------------------------------------------------------------------------
/src/main/resources/view/assets/background_name_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/background_name_0.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/background_name_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/background_name_1.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/cardBack_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/cardBack_0.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/cardBack_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/cardBack_1.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/cardFront_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/cardFront_0.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/cardFront_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/cardFront_1.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/elf_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/elf_0.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/elf_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/elf_1.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/frame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/frame.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/items_sheet.json:
--------------------------------------------------------------------------------
1 | {"frames":{"item_ARROW_0":{"frame":{"x":0,"y":0,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_ARROW_1":{"frame":{"x":0,"y":49,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_BOOK_0":{"frame":{"x":49,"y":0,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_BOOK_1":{"frame":{"x":49,"y":49,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_CANDY_0":{"frame":{"x":0,"y":98,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_CANDY_1":{"frame":{"x":49,"y":98,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_CANE_0":{"frame":{"x":98,"y":0,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_CANE_1":{"frame":{"x":98,"y":49,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_DIAMOND_0":{"frame":{"x":98,"y":98,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_DIAMOND_1":{"frame":{"x":0,"y":147,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_FISH_0":{"frame":{"x":49,"y":147,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_FISH_1":{"frame":{"x":98,"y":147,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_KEY_0":{"frame":{"x":147,"y":0,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_KEY_1":{"frame":{"x":147,"y":49,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_MASK_0":{"frame":{"x":147,"y":98,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_MASK_1":{"frame":{"x":147,"y":147,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_POTION_0":{"frame":{"x":0,"y":196,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_POTION_1":{"frame":{"x":49,"y":196,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_SCROLL_0":{"frame":{"x":98,"y":196,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_SCROLL_1":{"frame":{"x":147,"y":196,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_SHIELD_0":{"frame":{"x":196,"y":0,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_SHIELD_1":{"frame":{"x":196,"y":49,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_SWORD_0":{"frame":{"x":196,"y":98,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}},"item_SWORD_1":{"frame":{"x":196,"y":147,"w":48,"h":48},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":48,"h":48},"sourceSize":{"w":48,"h":48}}},"meta":{"app":"https://www.leshylabs.com/apps/sstool/","version":"Leshy SpriteSheet Tool v0.8.4","image":"items_sheet.png","size":{"w":244,"h":244},"scale":1}}
--------------------------------------------------------------------------------
/src/main/resources/view/assets/items_sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/items_sheet.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/logo.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/tile_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/tile_background.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/tile_decorators.json:
--------------------------------------------------------------------------------
1 | {"frames":{"decors_0011":{"frame":{"x":0,"y":0,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_0101":{"frame":{"x":0,"y":313,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_0111":{"frame":{"x":313,"y":0,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_1001":{"frame":{"x":313,"y":313,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_1010":{"frame":{"x":0,"y":626,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_1100":{"frame":{"x":313,"y":626,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_1101":{"frame":{"x":626,"y":0,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_1110":{"frame":{"x":626,"y":313,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_1111":{"frame":{"x":626,"y":626,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_0110":{"frame":{"x":0,"y":939,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"decors_1011":{"frame":{"x":313,"y":939,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}}},"meta":{"app":"https://www.leshylabs.com/apps/sstool/","version":"Leshy SpriteSheet Tool v0.8.4","image":"tile_decorators.png","size":{"w":938,"h":1251},"scale":1}}
--------------------------------------------------------------------------------
/src/main/resources/view/assets/tile_decorators.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/tile_decorators.png
--------------------------------------------------------------------------------
/src/main/resources/view/assets/tile_paths.json:
--------------------------------------------------------------------------------
1 | {"frames":{"paths_0011":{"frame":{"x":0,"y":0,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_0101":{"frame":{"x":0,"y":313,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_0110":{"frame":{"x":313,"y":0,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_0111":{"frame":{"x":313,"y":313,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_1001":{"frame":{"x":0,"y":626,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_1010":{"frame":{"x":313,"y":626,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_1011":{"frame":{"x":626,"y":0,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_1100":{"frame":{"x":626,"y":313,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_1101":{"frame":{"x":626,"y":626,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_1110":{"frame":{"x":0,"y":939,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}},"paths_1111":{"frame":{"x":313,"y":939,"w":312,"h":312},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":312,"h":312},"sourceSize":{"w":312,"h":312}}},"meta":{"app":"https://www.leshylabs.com/apps/sstool/","version":"Leshy SpriteSheet Tool v0.8.4","image":"tile_paths.png","size":{"w":938,"h":1251},"scale":1}}
--------------------------------------------------------------------------------
/src/main/resources/view/assets/tile_paths.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodinGameCommunity/XmasRush/df8eb80f709afaab446a4e3d5c30a73337b85e73/src/main/resources/view/assets/tile_paths.png
--------------------------------------------------------------------------------
/src/main/resources/view/config.js:
--------------------------------------------------------------------------------
1 | import { GraphicEntityModule } from './entity-module/GraphicEntityModule.js';
2 | import { EndScreenModule } from './modules/endScreen/EndScreenModule.js';
3 | import { TooltipModule } from './modules/tooltip/TooltipModule.js';
4 | import { NicknamesHandlerModule } from './modules/nicknamesHandlerModule/NicknamesHandlerModule.js';
5 | import { options as viewOptions, ToggleModule } from './modules/toggleModule/ToggleModule.js';
6 |
7 | // List of viewer modules that you want to use in your game
8 | export const modules = [
9 | GraphicEntityModule,
10 | EndScreenModule,
11 | TooltipModule,
12 | ToggleModule,
13 | NicknamesHandlerModule
14 | ];
15 |
16 | // Setting players' colors
17 | export const playerColors = [
18 | '#ff1d5c', // player 1
19 | '#41a200' // player 2
20 | ];
21 |
22 | export const options = [{
23 | title: 'TILE SCENERY',
24 | get: function () {
25 | return viewOptions.decor
26 | },
27 | set: function (value) {
28 | viewOptions.decor = value
29 | viewOptions.refreshDecor()
30 | },
31 | values: {
32 | 'ON': true,
33 | 'OFF': false
34 | }
35 | }];
--------------------------------------------------------------------------------
/src/main/resources/view/modules/endScreen/EndScreenModule.js:
--------------------------------------------------------------------------------
1 | import {WIDTH, HEIGHT} from '../../core/constants.js'
2 | import {lerp, unlerp} from '../../core/utils.js'
3 |
4 | export class EndScreenModule {
5 | constructor (assets) {
6 | this.states = []
7 | this.scores = []
8 | this.globalData = {}
9 | window.module = this
10 | this.atEnd = false
11 | }
12 |
13 | static get name () {
14 | return 'endScreen'
15 | }
16 |
17 | updateScene (previousData, currentData, progress) {
18 | if (currentData.scores && progress === 1) {
19 | this.atEnd = true
20 | } else {
21 | this.atEnd = false
22 | }
23 | }
24 |
25 | handleFrameData (frameInfo, scores) {
26 | const state = {
27 | number: frameInfo.number,
28 | scores
29 | }
30 | if (scores) {
31 | this.scores = scores
32 | }
33 | this.states.push(state)
34 | return state
35 | }
36 |
37 | reinitScene (container, canvasData) {
38 | this.toDestroy = []
39 | this.container = container
40 | this.endLayer = this.createEndScene(this)
41 | if (this.atEnd) {
42 | this.initEndScene()
43 | }
44 | this.container.addChild(this.endLayer)
45 | }
46 |
47 | animateScene (delta) {
48 | let step = Math.min(32, delta)
49 |
50 | if (this.atEnd) {
51 | if (!this.animationEnded) {
52 | this.renderEndScene(step)
53 | }
54 | } else {
55 | if (this.endTime > 0) {
56 | this.destroyEndScene()
57 | }
58 | this.endTime = 0
59 | }
60 | }
61 |
62 | destroyEndScene () {
63 | this.animationEnded = false
64 | this.endLayer.visible = false
65 | }
66 |
67 | initEndScene () {
68 | this.animationEnded = false
69 | this.endLayer.visible = true
70 | }
71 |
72 | renderEndScene (step) {
73 | var endOfEnd = 10000
74 | if (this.endTime === 0) {
75 | this.initEndScene()
76 | }
77 |
78 | var backS = 0
79 | var backD = 400
80 | var backP = unlerp(backS, backS + backD, this.endTime)
81 | this.endLayer.backgroundRanking.alpha = backP * 0.9
82 |
83 | var logoS = 400
84 | var logoD = 600
85 | var logoP = unlerp(logoS, logoS + logoD, this.endTime)
86 | this.endLayer.titleRanking.scale.x = this.endLayer.titleRanking.scale.y = 0.001 + lerp(10, 0.8, logoP)
87 | this.endLayer.titleRanking.visible = !!logoP
88 |
89 | var rankS = 1000
90 | var rankD = 300
91 | for (let i = 0; i < this.finishers.length; ++i) {
92 | var p = unlerp(rankS + rankD * i, rankS + rankD * i + rankD, this.endTime)
93 | this.finishers[i].alpha = p
94 | }
95 |
96 | this.endTime += step
97 |
98 | if (this.endTime >= endOfEnd) {
99 | this.animationEnded = true
100 | }
101 | }
102 |
103 | handleGlobalData (players, globalData) {
104 | this.globalData = {
105 | players: players,
106 | playerCount: players.length
107 | }
108 | }
109 |
110 | generateText (text, size, align, color, forceLato) {
111 | var textEl
112 | if (!forceLato) {
113 | textEl = new PIXI.extras.BitmapText(text, {
114 | font: size + 'px 04b',
115 | tint: color
116 | })
117 | textEl.lineHeight = size
118 | } else {
119 | textEl = new PIXI.Text(text, {
120 | fontSize: Math.round(size / 1.2) + 'px',
121 | fontFamily: 'Lato',
122 | fontWeight: 'bold',
123 | fill: color
124 | })
125 | textEl.lineHeight = Math.round(size / 1.2)
126 | this.toDestroy.push(textEl)
127 | }
128 | if (align === 'right') {
129 | textEl.anchor.x = 1
130 | } else if (align === 'center') {
131 | textEl.anchor.x = 0.5
132 | }
133 | return textEl
134 | }
135 |
136 | createFinisher (finisher) {
137 | var layer = new PIXI.Container()
138 |
139 | /** ************************************* */
140 | var avatarContainer = new PIXI.Container()
141 | avatarContainer.y = 0
142 | avatarContainer.x = 0
143 |
144 | var backgroundAvatar = new PIXI.Graphics()
145 | backgroundAvatar.beginFill(0xffffff)
146 | backgroundAvatar.alpha = 0.1
147 | backgroundAvatar.drawRect(0, 0, 240, 120)
148 | avatarContainer.addChild(backgroundAvatar)
149 |
150 | var avatarBorder = new PIXI.Graphics()
151 | avatarBorder.lineStyle(1, 0xffffff)
152 | avatarBorder.alpha = 0.5
153 | avatarBorder.drawRect(0, 0, 120, 120)
154 | avatarContainer.addChild(avatarBorder)
155 |
156 | var avatar = new PIXI.Sprite(finisher.player.avatar)
157 | avatar.width = avatar.height = 120
158 |
159 | var rank = this.generateText(finisher.rank.toString(), 76, 'center', finisher.player.color, true)
160 | rank.anchor.y = 0.5
161 | rank.position.x = 160
162 | rank.position.y = 56
163 | avatarContainer.addChild(rank)
164 |
165 | var rankLetter = this.generateText(finisher.rank === 1 ? 'ST' : 'ND'.toString(), 34, 'left', finisher.player.color, true)
166 | rankLetter.position.x = 184
167 | rankLetter.position.y = 32
168 | avatarContainer.addChild(rankLetter)
169 |
170 | var hudAvatar = new PIXI.Container()
171 | hudAvatar.addChild(avatar)
172 |
173 | avatarContainer.addChild(hudAvatar)
174 |
175 | /** ************************************* */
176 |
177 | var name = this.generateText(finisher.player.name.toUpperCase(), 50, 'left', finisher.player.color, true)
178 | var scoreLabel = this.generateText(((finisher.score >= 0) ? finisher.score.toString() + ' points' : '-'), 64, 'left', finisher.player.color, true)
179 |
180 | name.x = 330
181 | name.y = -4
182 | scoreLabel.x = 330
183 | scoreLabel.y = 50
184 |
185 | layer.addChild(avatarContainer)
186 | layer.addChild(name)
187 | layer.addChild(scoreLabel)
188 |
189 | return layer
190 | }
191 |
192 | createEndScene () {
193 | var layer = new PIXI.Container()
194 |
195 | var background = new PIXI.Graphics()
196 | background.beginFill(0, 0.85)
197 | background.drawRect(0, 0, WIDTH, HEIGHT)
198 | background.endFill()
199 |
200 | layer.backgroundRanking = background
201 |
202 | var titleRanking = new PIXI.Sprite.fromFrame('logo.png')
203 | titleRanking.anchor.x = titleRanking.anchor.y = 0.5
204 | layer.titleRanking = titleRanking
205 |
206 | titleRanking.position.x = WIDTH / 2
207 | titleRanking.position.y = 230
208 |
209 | var podium = []
210 | for (var i = 0; i < this.globalData.playerCount; ++i) {
211 | podium.push({
212 | score: this.scores[i],
213 | player: this.globalData.players[i],
214 | rank: 0
215 | })
216 | }
217 | podium.sort(function (a, b) {
218 | return b.score - a.score
219 | })
220 |
221 | this.finishers = []
222 | var finishers = new PIXI.Container()
223 | var curRank = 1
224 | var elem
225 | for (i = 0; i < podium.length; ++i) {
226 | if (i > 0 && podium[i - 1].score !== podium[i].score) {
227 | curRank++
228 | }
229 |
230 | podium[i].rank = curRank
231 | elem = this.createFinisher(podium[i])
232 | finishers.addChild(elem)
233 | this.finishers.push(elem)
234 | }
235 |
236 | for (i = 0; i < this.finishers.length; ++i) {
237 | this.finishers[i].position.x = (WIDTH - this.finishers[0].width) / 2
238 | this.finishers[i].position.y = i * 150
239 | }
240 | finishers.y = 400
241 |
242 | layer.addChild(background)
243 | layer.addChild(titleRanking)
244 | layer.addChild(finishers)
245 |
246 | layer.visible = false
247 | return layer
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/src/main/resources/view/modules/nicknamesHandlerModule/NicknamesHandlerModule.js:
--------------------------------------------------------------------------------
1 | import { api as entityModule } from '../../entity-module/GraphicEntityModule.js'
2 | import { fitAspectRatio } from '../../core/utils.js'
3 | export const api = {
4 | showDamage: true,
5 | showCurve: false
6 | }
7 |
8 | export class NicknamesHandlerModule {
9 | constructor (assets) {
10 | this.mustShrinkNickname = true
11 | this.nicknameIds = []
12 | }
13 |
14 | static get name () {
15 | return 'nicks'
16 | }
17 |
18 | updateScene (previousData, currentData, progress) {
19 | if (this.mustShrinkNickname) {
20 | this.mustShrinkNickname = false
21 | this.nicknameIds.forEach(entityId => {
22 | let entity = entityModule.entities.get(entityId)
23 | if (!entity.currentState.text || entity.currentState.text === '') {
24 | this.mustShrinkNickname = true
25 | } else {
26 | if (entity.graphics.width > 270) {
27 | let aspectRatio = fitAspectRatio(entity.graphics.width, entity.graphics.height, 270, 50)
28 | entity.graphics.scale.set(aspectRatio)
29 | }
30 | }
31 | })
32 | }
33 | }
34 |
35 | handleFrameData (frameInfo, nothing) {
36 | return {...frameInfo}
37 | }
38 |
39 | reinitScene (container, canvasData) {
40 | this.mustShrinkNickname = true
41 | }
42 |
43 | animateScene (delta) {
44 | }
45 |
46 | handleGlobalData (players, nicknameIds) {
47 | this.nicknameIds = nicknameIds || []
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/resources/view/modules/toggleModule/ToggleModule.js:
--------------------------------------------------------------------------------
1 | import { api as entityModule } from '../../entity-module/GraphicEntityModule.js'
2 |
3 | export const options = {
4 | decor: false,
5 | refreshDecor: () => {}
6 | }
7 |
8 | export class ToggleModule {
9 | constructor (assets) {
10 | this.interactive = {}
11 | this.previousFrame = {
12 | tooltips: {},
13 | paths: {},
14 | ownerships: {}
15 | }
16 |
17 | options.refreshDecor = () => {
18 | entityModule.entities.forEach(
19 | e => {
20 | if (e.currentState.image && e.currentState.image.indexOf('decor') >= 0) {
21 | e.graphics.visible = options.decor
22 | }
23 | })
24 | }
25 | }
26 |
27 | static get name () {
28 | return 'togglemodule'
29 | }
30 |
31 | updateScene (previousData, currentData, progress) {
32 | this.currentFrame = currentData
33 | this.currentProgress = progress
34 | options.refreshDecor()
35 | }
36 |
37 | handleFrameData (frameInfo, data) {
38 | }
39 |
40 | reinitScene (container, canvasData) {
41 | }
42 |
43 | animateScene (delta) {
44 | }
45 |
46 | handleGlobalData (players, globalData) {
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/resources/view/modules/tooltip/TooltipModule.js:
--------------------------------------------------------------------------------
1 | import { ErrorLog } from '../../core/ErrorLog.js';
2 | import { WIDTH, HEIGHT } from '../../core/constants.js';
3 | import * as utils from '../../core/utils.js';
4 | import { api as entityModule } from '../../entity-module/GraphicEntityModule.js';
5 |
6 |
7 | function getMouseOverFunc(id, tooltip) {
8 | return function () {
9 | tooltip.inside[id] = true;
10 | };
11 | }
12 |
13 | function getMouseOutFunc(id, tooltip) {
14 | return function () {
15 | delete tooltip.inside[id];
16 | };
17 | }
18 |
19 | function getEntityState(entity, frame, progress) {
20 | const subStates = entity.states[frame];
21 | if (subStates && subStates.length) {
22 | return subStates[subStates.length - 1];
23 | }
24 | return null;
25 | }
26 |
27 | function getMouseMoveFunc(tooltip, container, module) {
28 | return function (ev) {
29 | if (tooltip) {
30 | var pos = ev.data.getLocalPosition(container);
31 | tooltip.x = pos.x;
32 | tooltip.y = pos.y;
33 | var point = {
34 | x: pos.x * entityModule.coeff,
35 | y: pos.y * entityModule.coeff
36 | };
37 |
38 | const showing = [];
39 | const ids = Object.keys(tooltip.inside).map(n => +n);
40 |
41 | for (let id of ids) {
42 | if (tooltip.inside[id]) {
43 | const entity = entityModule.entities.get(id);
44 | const state = entity && getEntityState(entity, module.currentFrame.number);
45 | if (!state || state.alpha === 0 || !state.visible) {
46 | delete tooltip.inside[id];
47 | } else {
48 | showing.push(id);
49 | }
50 | }
51 | }
52 |
53 | if (showing.length) {
54 | const tooltipBlocks = [];
55 | for (let show of showing) {
56 | const entity = entityModule.entities.get(show);
57 | const state = getEntityState(entity, module.currentFrame.number);
58 | if (state !== null) {
59 | let tooltipBlock;
60 | const params = module.currentFrame.registered[show];
61 |
62 | tooltip.visible = true;
63 | const extra = module.currentFrame.extraText[show];
64 | if (extra && extra.length) {
65 | tooltipBlock = extra;
66 | }
67 | tooltipBlocks.push(tooltipBlock);
68 | }
69 | }
70 | tooltip.label.text = tooltipBlocks.join('\n──────────\n')
71 | } else {
72 | tooltip.visible = false;
73 | }
74 |
75 | tooltip.background.width = tooltip.label.width + 20;
76 | tooltip.background.height = tooltip.label.height + 20;
77 |
78 | tooltip.pivot.x = -30;
79 | tooltip.pivot.y = -50;
80 |
81 | if (tooltip.y - tooltip.pivot.y + tooltip.height > HEIGHT) {
82 | tooltip.pivot.y = 10 + tooltip.height;
83 | tooltip.y -= tooltip.y - tooltip.pivot.y + tooltip.height - HEIGHT
84 | }
85 |
86 | if (tooltip.x - tooltip.pivot.x + tooltip.width > WIDTH) {
87 | tooltip.pivot.x = tooltip.width;
88 | }
89 | }
90 |
91 | }
92 | };
93 |
94 | export class TooltipModule {
95 | constructor(assets) {
96 | this.interactive = {};
97 | this.previousFrame = {
98 | registrations: {},
99 | extra: {}
100 | };
101 | this.lastProgress = 1;
102 | this.lastFrame = 0;
103 |
104 | }
105 |
106 | static get name() {
107 | return 'tooltips';
108 | }
109 |
110 | updateScene(previousData, currentData, progress) {
111 | this.currentFrame = currentData;
112 | this.currentProgress = progress;
113 | }
114 |
115 | handleFrameData(frameInfo, [registrations, extra]) {
116 | const registered = { ...registrations };
117 | const extraText = { ...this.previousFrame.extraText, ...extra };
118 |
119 | Object.keys(registrations).forEach(
120 | k => {
121 | this.interactive[k] = true;
122 | }
123 | );
124 |
125 | const frame = { registered, extraText, number: frameInfo.number };
126 | this.previousFrame = frame;
127 | return frame;
128 | }
129 |
130 | reinitScene(container, canvasData) {
131 | this.tooltip = this.initTooltip();
132 | entityModule.entities.forEach(entity => {
133 | if (this.interactive[entity.id]) {
134 | entity.container.interactive = true;
135 | entity.container.mouseover = getMouseOverFunc(entity.id, this.tooltip);
136 | entity.container.mouseout = getMouseOutFunc(entity.id, this.tooltip);
137 | }
138 | });
139 | this.container = container;
140 | container.interactive = true;
141 | container.mousemove = getMouseMoveFunc(this.tooltip, container, this);
142 | container.addChild(this.tooltip);
143 | }
144 |
145 | generateText(text, size, color, align) {
146 | var textEl = new PIXI.Text(text, {
147 | fontSize: Math.round(size / 1.2) + 'px',
148 | fontFamily: 'monospace',
149 | fontWeight: 'bold',
150 | fill: color
151 | });
152 |
153 | textEl.lineHeight = Math.round(size / 1.2);
154 | if (align === 'right') {
155 | textEl.anchor.x = 1;
156 | } else if (align === 'center') {
157 | textEl.anchor.x = 0.5;
158 | }
159 |
160 | return textEl;
161 | };
162 |
163 | initTooltip() {
164 | var tooltip = new PIXI.Container();
165 | var background = tooltip.background = new PIXI.Graphics();
166 | var label = tooltip.label = this.generateText('', 36, 0xFFFFFF, 'left');
167 |
168 | background.beginFill(0x0, 0.7);
169 | background.drawRect(0, 0, 200, 185);
170 | background.endFill();
171 | background.x = -10;
172 | background.y = -10;
173 |
174 | tooltip.visible = false;
175 | tooltip.inside = {};
176 |
177 | tooltip.addChild(background);
178 | tooltip.addChild(label);
179 |
180 | tooltip.interactiveChildren = false;
181 | return tooltip;
182 | };
183 |
184 | animateScene(delta) {
185 |
186 | }
187 |
188 | handleGlobalData(players, globalData) {
189 |
190 | }
191 | }
192 |
193 | class NotYetImplemented extends Error {
194 | constructor(feature) {
195 | super('Not yet implemented: "' + feature);
196 | this.feature = feature;
197 | this.name = 'NotYetImplemented';
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/test/java/Main.java:
--------------------------------------------------------------------------------
1 | import com.codingame.gameengine.runner.MultiplayerGameRunner;
2 |
3 | public class Main {
4 | public static void main(String[] args) {
5 |
6 | final String AVATAR_TWINKLE = "https://static.codingame.com/servlet/fileservlet?id=23672527342224&format=profile_avatar";
7 | final String AVATAR_PIXIE = "https://static.codingame.com/servlet/fileservlet?id=23672566492606&format=profile_avatar";
8 |
9 | MultiplayerGameRunner gameRunner = new MultiplayerGameRunner();
10 |
11 | gameRunner.addAgent(Player1.class, "Twinkle", AVATAR_TWINKLE);
12 | gameRunner.addAgent(Player2.class, "Pixie", AVATAR_PIXIE);
13 |
14 | System.setProperty("league.level", "3");
15 | gameRunner.setSeed(20L);
16 |
17 | gameRunner.start();
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/Player1.java:
--------------------------------------------------------------------------------
1 | import java.util.Scanner;
2 |
3 | public class Player1 {
4 | public static void main(String args[]) {
5 | Scanner in = new Scanner(System.in);
6 | int boardWidth = 7;
7 | int boardHeight = 7;
8 |
9 | int turn = 0;
10 | // game loop
11 | while (true) {
12 |
13 | int turnType = in.nextInt();
14 | for (int i = 0; i < boardHeight; i++) {
15 | for (int j = 0; j < boardWidth; j++) {
16 | String tile = in.next();
17 | System.err.print(tile + " ");
18 | }
19 | System.err.println();
20 | }
21 | for (int i = 0; i < 2; i++) {
22 | int numPlayerCards = in.nextInt(); // the number of cards in the stack for each player
23 | int playerX = in.nextInt();
24 | int playerY = in.nextInt();
25 | String playerTile = in.next();
26 | System.err.println(numPlayerCards + " " + playerX + "," + playerY + " " + playerTile);
27 | }
28 | int numItems = in.nextInt(); // the total number of items available on board and on player tiles (does not include quest cards)
29 | for (int i = 0; i < numItems; i++) {
30 | String itemName = in.next();
31 | int itemX = in.nextInt();
32 | int itemY = in.nextInt();
33 | int itemPlayerId = in.nextInt();
34 | System.err.println(itemName + itemPlayerId + " " + itemX + "," + itemY);
35 | }
36 | int numQuests = in.nextInt(); // the total number of available quest cards for both players
37 | for (int i = 0; i < numQuests; i++) {
38 | String questItemName = in.next();
39 | int questPlayerId = in.nextInt();
40 | System.err.println(questItemName + questPlayerId);
41 | }
42 |
43 | //league 3
44 | if (turn == 0) System.out.println("PUSH 0 DOWN");
45 | if (turn == 1) System.out.println("MOVE RIGHT UP RIGHT RIGHT DOWN");
46 | if (turn == 2) System.out.println("PUSH 1 RIGHT");
47 | if (turn == 3) System.out.println("MOVE UP RIGHT RIGHT LEFT LEFT DOWN");
48 | if (turn == 4) System.out.println("PUSH 6 UP");
49 | if (turn == 5) System.out.println("MOVE DOWN DOWN DOWN DOWN LEFT DOWN RIGHT RIGHT LEFT LEFT UP RIGHT UP UP UP UP UP RIGHT RIGHT");
50 | if (turn == 6) System.out.println("PUSH 4 RIGHT");
51 | if (turn == 7) System.out.println("PASS");
52 | if (turn == 8) System.out.println("PUSH 6 DOWN");
53 | if (turn == 9) System.out.println("MOVE UP");
54 | if (turn == 10) System.out.println("PUSH 5 UP");
55 | if (turn == 11) System.out.println("PASS");
56 | if (turn == 12) System.out.println("PUSH 4 LEFT");
57 | if (turn == 13) System.out.println("PASS");
58 | if (turn == 14) System.out.println("PUSH 0 LEFT");
59 | if (turn == 15) System.out.println("MOVE RIGHT");
60 | if (turn == 16) System.out.println("PUSH 0 RIGHT");
61 | if (turn == 17) System.out.println("MOVE RIGHT");
62 | if (turn == 18) System.out.println("PUSH 0 RIGHT");
63 | if (turn == 19) System.out.println("MOVE DOWN RIGHT UP RIGHT DOWN DOWN");
64 | if (turn == 20) System.out.println("PUSH 2 RIGHT");
65 | if (turn == 21) System.out.println("MOVE DOWN DOWN UP UP");
66 | if (turn == 22) System.out.println("PUSH 2 LEFT");
67 | if (turn == 23) System.out.println("MOVE UP UP LEFT DOWN");
68 | turn++;
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/test/java/Player2.java:
--------------------------------------------------------------------------------
1 | import java.util.Scanner;
2 |
3 | public class Player2 {
4 | public static void main(String args[]) {
5 | Scanner in = new Scanner(System.in);
6 | int boardWidth = 7;
7 | int boardHeight = 7;
8 |
9 | int turn = 0;
10 | // game loop
11 | while (true) {
12 | int turnType = in.nextInt();
13 | for (int i = 0; i < boardHeight; i++) {
14 | for (int j = 0; j < boardWidth; j++) {
15 | String tile = in.next();
16 | System.err.print(tile + " ");
17 | }
18 | System.err.println();
19 | }
20 | for (int i = 0; i < 2; i++) {
21 | int numPlayerCards = in.nextInt(); // the number of cards in the stack for each player
22 | int playerX = in.nextInt();
23 | int playerY = in.nextInt();
24 | String playerTile = in.next();
25 | System.err.println(numPlayerCards + " " + playerX + "," + playerY + " " + playerTile);
26 | }
27 | int numItems = in.nextInt(); // the total number of items available on board and on player tiles (does not include quest cards)
28 | for (int i = 0; i < numItems; i++) {
29 | String itemName = in.next();
30 | int itemX = in.nextInt();
31 | int itemY = in.nextInt();
32 | int itemPlayerId = in.nextInt();
33 | System.err.println(itemName + itemPlayerId + " " + itemX + "," + itemY);
34 | }
35 | int numQuests = in.nextInt(); // the total number of available quest cards for both players
36 | for (int i = 0; i < numQuests; i++) {
37 | String questItemName = in.next();
38 | int questPlayerId = in.nextInt();
39 | System.err.println(questItemName + questPlayerId);
40 | }
41 |
42 | //league 3
43 | if (turn == 0) System.out.println("PUSH 1 UP");
44 | if (turn == 1) System.out.println("MOVE UP");
45 | if (turn == 2) System.out.println("PUSH 5 UP");
46 | if (turn == 3) System.out.println("MOVE DOWN LEFT");
47 | if (turn == 4) System.out.println("PUSH 5 DOWN");
48 | if (turn == 5) System.out.println("MOVE LEFT DOWN DOWN DOWN DOWN DOWN LEFT");
49 | if (turn == 6) System.out.println("PUSH 5 LEFT");
50 | if (turn == 7) System.out.println("MOVE UP DOWN DOWN");
51 | if (turn == 8) System.out.println("PUSH 2 DOWN");
52 | if (turn == 9) System.out.println("MOVE RIGHT DOWN RIGHT DOWN UP UP RIGHT");
53 | if (turn == 10) System.out.println("PUSH 0 UP");
54 | if (turn == 11) System.out.println("MOVE LEFT");
55 | if (turn == 12) System.out.println("PUSH 1 LEFT");
56 | if (turn == 13) System.out.println("PASS");
57 | if (turn == 14) System.out.println("PUSH 4 UP");
58 | if (turn == 15) System.out.println("MOVE DOWN UP RIGHT UP UP UP RIGHT");
59 | if (turn == 16) System.out.println("PUSH 2 RIGHT");
60 | if (turn == 17) System.out.println("MOVE UP RIGHT UP LEFT");
61 | if (turn == 18) System.out.println("PUSH 2 LEFT");
62 | if (turn == 19) System.out.println("MOVE DOWN LEFT DOWN UP RIGHT UP RIGHT");
63 | if (turn == 20) System.out.println("PUSH 2 UP");
64 | if (turn == 21) System.out.println("MOVE UP RIGHT DOWN RIGHT UP RIGHT UP UP DOWN DOWN LEFT DOWN LEFT UP LEFT");
65 | if (turn == 22) System.out.println("PUSH 5 LEFT");
66 | if (turn == 23) System.out.println("MOVE UP");
67 | turn++;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/InputActions/MoveActionTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | import com.codingame.game.Utils.Constants;
4 | import org.junit.Test;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import static org.junit.Assert.*;
10 |
11 | public class MoveActionTest {
12 |
13 | @Test(expected=AssertionError.class)
14 | public void testAssertionsEnabled() {
15 | assert false;
16 | }
17 |
18 | @Test
19 | public void testConstructorMutatorsObservers() {
20 | Action.Type type = Action.Type.MOVE;
21 | Constants.Direction step1 = Constants.Direction.UP;
22 | Constants.Direction step2 = Constants.Direction.LEFT;
23 | MoveAction action = new MoveAction(type);
24 | assertEquals(type, action.getType());
25 | assertEquals(null, action.getStep());
26 | action.addStep(step1);
27 | action.addStep(step2);
28 | assertEquals(step1, action.getStep());
29 | assertEquals(step2, action.getStep());
30 | assertEquals(null, action.getStep());
31 | }
32 |
33 | @Test
34 | public void testIsEmptySetEmpty() {
35 | Action.Type type = Action.Type.MOVE;
36 | Constants.Direction step1 = Constants.Direction.UP;
37 | MoveAction action = new MoveAction(type);
38 | assertTrue(action.isEmpty());
39 | action.addStep(step1);
40 | assertFalse(action.isEmpty());
41 | action.setEmpty();
42 | assertTrue(action.isEmpty());
43 | }
44 |
45 | @Test
46 | public void testActionMethods() {
47 | Action.Type type = Action.Type.MOVE;
48 | MoveAction action = new MoveAction(type);
49 | Action.Type turn = Action.Type.MOVE;
50 | assertFalse(action.isPassAction());
51 | assertTrue(action.isLegalAction(turn));
52 | turn = Action.Type.PUSH;
53 | assertFalse(action.isLegalAction(turn));
54 | assertEquals(1, action.getType().getValue());
55 | }
56 | }
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/InputActions/PassActionTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | import com.codingame.game.Utils.Constants;
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.*;
7 |
8 | public class PassActionTest {
9 |
10 | @Test(expected=AssertionError.class)
11 | public void testAssertionsEnabled() {
12 | assert false;
13 | }
14 |
15 | @Test
16 | public void testConstructorObservers() {
17 | Action.Type type = Action.Type.PASS;
18 | PassAction action = new PassAction(type);
19 | assertEquals(type, action.getType());
20 | assertTrue(action.isPassAction());
21 | }
22 |
23 | @Test
24 | public void testLegalAction() {
25 | Action.Type type = Action.Type.PASS;
26 | PassAction action = new PassAction(type);
27 | Action.Type turn = Action.Type.PUSH;
28 | assertFalse(action.isLegalAction(turn));
29 | turn = Action.Type.MOVE;
30 | assertTrue(action.isLegalAction(turn));
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/InputActions/PushActionTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.InputActions;
2 |
3 | import com.codingame.game.Utils.Constants;
4 | import org.junit.Test;
5 |
6 | import java.util.Arrays;
7 |
8 | import static org.junit.Assert.*;
9 |
10 | public class PushActionTest {
11 |
12 | @Test(expected=AssertionError.class)
13 | public void testAssertionsEnabled() {
14 | assert false;
15 | }
16 |
17 | @Test(expected=AssertionError.class)
18 | public void testIncorrectLine() throws AssertionError {
19 | int lineId = Constants.MAP_SIZE + 1;
20 | Constants.Direction direction = Constants.Direction.UP;
21 | Action.Type type = Action.Type.PUSH;
22 | PushAction action = new PushAction(lineId, direction, type);
23 | }
24 |
25 | @Test(expected=AssertionError.class)
26 | public void testPushSameLineLargerActionsSize() throws AssertionError {
27 | int lineId = 1;
28 | Constants.Direction direction1 = Constants.Direction.UP;
29 | Constants.Direction direction2 = Constants.Direction.DOWN;
30 | Action.Type type = Action.Type.PUSH;
31 |
32 | PushAction action1 = new PushAction(lineId, direction1, type);
33 | PushAction action2 = new PushAction(lineId, direction2, type);
34 | PushAction action3 = new PushAction(lineId, direction1, type);
35 |
36 | PushAction.pushSameLine(Arrays.asList(action1, action2, action3));
37 | }
38 |
39 | @Test(expected=AssertionError.class)
40 | public void testPushSameLineSmallerActionsSize() throws AssertionError {
41 | int lineId = 1;
42 | Constants.Direction direction1 = Constants.Direction.UP;
43 | Action.Type type = Action.Type.PUSH;
44 |
45 | PushAction action1 = new PushAction(lineId, direction1, type);
46 |
47 | PushAction.pushSameLine(Arrays.asList(action1));
48 | }
49 |
50 | @Test(expected=AssertionError.class)
51 | public void testPushSameLineMixedPlanes() throws AssertionError {
52 | int lineId = 1;
53 | Constants.Direction direction1 = Constants.Direction.UP;
54 | Constants.Direction direction2 = Constants.Direction.LEFT;
55 | Action.Type type = Action.Type.PUSH;
56 |
57 | PushAction action1 = new PushAction(lineId, direction1, type);
58 | PushAction action2 = new PushAction(lineId, direction2, type);
59 |
60 | PushAction.pushSameLine(Arrays.asList(action1, action2));
61 | }
62 |
63 | @Test
64 | public void testConstructorObservers() {
65 | int lineId = 5;
66 | Constants.Direction direction = Constants.Direction.UP;
67 | Action.Type type = Action.Type.PUSH;
68 | PushAction action = new PushAction(lineId, direction, type);
69 | assertEquals(type, action.getType());
70 | assertEquals(lineId, action.getLine());
71 | assertEquals(direction, action.getDirection());
72 | assertFalse(action.isHorizontal());
73 | }
74 |
75 | @Test
76 | public void testActionMethods() {
77 | int lineId = 5;
78 | Constants.Direction direction = Constants.Direction.UP;
79 | Action.Type type = Action.Type.PUSH;
80 | Action.Type turn = Action.Type.PUSH;
81 | PushAction action = new PushAction(lineId, direction, type);
82 | assertFalse(action.isPassAction());
83 | assertTrue(action.isLegalAction(turn));
84 | turn = Action.Type.MOVE;
85 | assertFalse(action.isLegalAction(turn));
86 | assertEquals(0, action.getType().getValue());
87 | }
88 |
89 | @Test
90 | public void testPushSameLine() {
91 | int lineId1 = 5;
92 | int lineId2 = 1;
93 | Constants.Direction direction1 = Constants.Direction.UP;
94 | Constants.Direction direction2 = Constants.Direction.DOWN;
95 | Action.Type type = Action.Type.PUSH;
96 |
97 | PushAction action1 = new PushAction(lineId1, direction1, type);
98 | PushAction action2 = new PushAction(lineId1, direction1, type);
99 | assertTrue(PushAction.pushSameLine(Arrays.asList(action1, action2)));
100 |
101 | PushAction action3 = new PushAction(lineId1, direction2, type);
102 | assertTrue(PushAction.pushSameLine(Arrays.asList(action1, action3)));
103 |
104 | PushAction action4 = new PushAction(lineId2, direction1, type);
105 | assertFalse(PushAction.pushSameLine(Arrays.asList(action1, action4)));
106 | }
107 |
108 | @Test
109 | public void testToString() {
110 | int lineId1 = 0;
111 | int lineId2 = 2;
112 | int lineId3 = 5;
113 | int lineId4 = 6;
114 | Constants.Direction direction1 = Constants.Direction.UP;
115 | Constants.Direction direction2 = Constants.Direction.RIGHT;
116 | Constants.Direction direction3 = Constants.Direction.DOWN;
117 | Constants.Direction direction4 = Constants.Direction.LEFT;
118 | Action.Type type = Action.Type.PUSH;
119 |
120 | PushAction action1 = new PushAction(lineId1, direction1, type);
121 | PushAction action2 = new PushAction(lineId2, direction2, type);
122 | PushAction action3 = new PushAction(lineId3, direction3, type);
123 | PushAction action4 = new PushAction(lineId4, direction4, type);
124 |
125 | assertEquals("00", action1.toString());
126 | assertEquals("21", action2.toString());
127 | assertEquals("52", action3.toString());
128 | assertEquals("63", action4.toString());
129 |
130 | }
131 |
132 | }
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/Model/CardModelTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import com.codingame.game.Utils.Vector2;
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.*;
7 |
8 |
9 | public class CardModelTest {
10 |
11 | @Test(expected=AssertionError.class)
12 | public void testAssertionsEnabled() {
13 | assert false;
14 | }
15 |
16 | @Test(expected=AssertionError.class)
17 | public void testIncorrectItem() throws AssertionError {
18 | CardModel card = new CardModel(new Item("APPLE", 3),
19 | new Vector2(2, 1));
20 | }
21 |
22 | @Test
23 | public void testConstructorObservers() {
24 | Item item = new Item("BOOK", 1);
25 | Vector2 pos1 = new Vector2(2, 1);
26 | Vector2 pos2 = new Vector2(1, 3);
27 | CardModel card = new CardModel(item, pos1);
28 | assertTrue(card.getItem().equals(item));
29 | assertTrue(card.getPos().equals(pos1));
30 | card.setPos(pos2);
31 | assertTrue(card.getPos().equals(pos2));
32 | }
33 |
34 | @Test
35 | public void testConstructorExposure() {
36 | Item item = new Item("BOOK", 1);
37 | Vector2 pos = new Vector2(2, 1);
38 | CardModel card = new CardModel(item, pos);
39 | item = new Item("ARROW", 0);
40 | pos = new Vector2(1, 3);
41 | assertFalse(card.getItem().equals(item));
42 | assertFalse(card.getPos().equals(pos));
43 | }
44 |
45 | @Test
46 | public void testGetterExposure() {
47 | Item item1 = new Item("BOOK", 1);
48 | Vector2 pos1 = new Vector2(2, 1);
49 | CardModel card = new CardModel(item1, pos1);
50 | Item item2 = card.getItem();
51 | Vector2 pos2 = card.getPos();
52 | item2 = new Item("ARROW", 0);
53 | pos2 = new Vector2(1, 3);
54 | assertFalse(card.getItem().equals(item2));
55 | assertFalse(card.getPos().equals(pos2));
56 | assertTrue(card.getItem().equals(item1));
57 | assertTrue(card.getPos().equals(pos1));
58 | }
59 |
60 | @Test
61 | public void testCardToString() {
62 | Item item = new Item("BOOK", 1);
63 | Vector2 pos = new Vector2(2, 1);
64 | CardModel card = new CardModel(item, pos);
65 | assertEquals("BOOK 1", card.cardToString());
66 | }
67 |
68 | @Test
69 | public void testOpponentCardToString() {
70 | Item item = new Item("BOOK", 1);
71 | Vector2 pos = new Vector2(2, 1);
72 | CardModel card = new CardModel(item, pos);
73 | assertEquals("BOOK 0", card.opponentCardToString());
74 | }
75 |
76 | @Test
77 | public void testFlip() {
78 | Item item = new Item("BOOK", 1);
79 | Vector2 pos = new Vector2(2, 1);
80 | CardModel card = new CardModel(item, pos);
81 | assertFalse(item.getHighlight());
82 | card.flip();
83 | assertTrue(item.getHighlight());
84 | card.flip();
85 | assertTrue(item.getHighlight());
86 | }
87 | }
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/Model/ItemTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import org.junit.Test;
4 | import static org.junit.Assert.*;
5 |
6 | import java.util.*;
7 |
8 | public class ItemTest {
9 |
10 | @Test(expected=AssertionError.class)
11 | public void testAssertionsEnabled() {
12 | assert false;
13 | }
14 |
15 | @Test(expected=AssertionError.class)
16 | public void testItemIncorrectName() throws AssertionError {
17 | Item item = new Item("APPLE", 0);
18 | }
19 |
20 | @Test(expected=AssertionError.class)
21 | public void testItemIncorrectId() throws AssertionError {
22 | Item item = new Item("BOOK", 3);
23 | }
24 |
25 | @Test
26 | public void testItemObservers() {
27 | Item item = new Item("BOOK", 0);
28 | assertEquals("BOOK", item.getName());
29 | assertEquals(0, item.getPlayerId());
30 | }
31 |
32 | @Test
33 | public void testTwoItemsDifferentName() {
34 | Set- items = new HashSet<>();
35 | Item item1 = new Item("BOOK", 1);
36 | Item item2 = new Item("POTION", 1);
37 | items.add(item1);
38 | items.add(item2);
39 | assertTrue(items.size() == 2);
40 | }
41 |
42 | @Test
43 | public void testTwoItemsDifferentIds() {
44 | Set
- items = new HashSet<>();
45 | Item item1 = new Item("BOOK", 0);
46 | Item item2 = new Item("BOOK", 1);
47 | items.add(item1);
48 | items.add(item2);
49 | assertTrue(items.size() == 2);
50 | }
51 |
52 | @Test
53 | public void testTwoSameItems() {
54 | Set
- items = new HashSet<>();
55 | Item item1 = new Item("BOOK", 0);
56 | Item item2 = new Item("BOOK", 0);
57 | items.add(item1);
58 | items.add(item2);
59 | assertTrue(items.size() == 1);
60 | }
61 |
62 | @Test
63 | public void testRefExposure() {
64 | Item item1 = new Item("BOOK", 0);
65 | Item item2 = item1;
66 | item1 = new Item("DIAMOND", 1);
67 | assertTrue(item2.getName().equals("BOOK"));
68 | assertTrue(item2.getPlayerId() == 0);
69 | }
70 |
71 | @Test
72 | public void testItemToString() {
73 | Item item = new Item("BOOK", 1);
74 | assertEquals("BOOK 1", item.itemToString());
75 | }
76 |
77 | @Test
78 | public void testGetOpponentsId() {
79 | Item item = new Item("BOOK", 1);
80 | assertEquals(0, item.getOpponentId());
81 | }
82 |
83 | @Test
84 | public void testOpponentVectorToString() {
85 | Item item = new Item("BOOK", 1);
86 | assertEquals("BOOK 0", item.opponentItemToString());
87 | }
88 |
89 | @Test
90 | public void testSetGetHighlight() {
91 | Item item = new Item("BOOK", 1);
92 | assertFalse(item.getHighlight());
93 | item.setHighlight();
94 | assertTrue(item.getHighlight());
95 | item.setHighlight();
96 | assertTrue(item.getHighlight());
97 | }
98 | }
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/Model/PlayerModelTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertFalse;
5 | import static org.junit.Assert.assertNull;
6 | import static org.junit.Assert.assertTrue;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.List;
11 |
12 | import org.junit.Test;
13 |
14 | import com.codingame.game.Utils.Constants;
15 | import com.codingame.game.Utils.Vector2;
16 |
17 | public class PlayerModelTest {
18 |
19 | @Test(expected=AssertionError.class)
20 | public void testAssertionsEnabled() {
21 | assert false;
22 | }
23 |
24 | @Test(expected=AssertionError.class)
25 | public void testSetCardsIncorrectId() throws AssertionError {
26 | int id = 1;
27 | PlayerModel player = new PlayerModel(id);
28 | Item item1 = new Item("BOOK", id);
29 | Item item2 = new Item("POTION", 0);
30 | List
- itemList = new ArrayList<>();
31 | itemList.addAll(Arrays.asList(item1, item2));
32 | player.setCards(itemList);
33 | }
34 |
35 | @Test(expected=AssertionError.class)
36 | public void testSetCardsRepeatedItems() throws AssertionError {
37 | int id = 1;
38 | PlayerModel player = new PlayerModel(id);
39 | Item item1 = new Item("BOOK", id);
40 | Item item2 = new Item("BOOK", id);
41 | List
- itemList = new ArrayList<>();
42 | itemList.addAll(Arrays.asList(item1, item2));
43 | player.setCards(itemList);
44 | }
45 |
46 | @Test
47 | public void testConstructor() {
48 | int id = 1;
49 | PlayerModel player = new PlayerModel(id);
50 | assertEquals(id, player.id);
51 | assertEquals(Constants.PLAYER_POSITIONS.get(id), player.getPos());
52 | }
53 |
54 | @Test
55 | public void testTileMethods() {
56 | int id = 0;
57 | PlayerModel player = new PlayerModel(id);
58 | Vector2 pos = new Vector2(1, 2);
59 | TileModel tile1 = new TileModel("1111", pos);
60 | TileModel tile2 = new TileModel("1001", pos);
61 | assertNull(tile1.getPlayerId());
62 | player.setTile(tile1);
63 | assertTrue(tile1.getPlayerId() == id);
64 | assertEquals(tile1, player.getTile());
65 | assertEquals(Constants.TILE_MODEL_POSITIONS.get(id), player.getTile().getPos());
66 | player.setTile(tile2);
67 | assertNull(tile1.getPlayerId());
68 | }
69 |
70 | @Test
71 | public void testSetGetCards() {
72 | int id = 1;
73 | PlayerModel player = new PlayerModel(id);
74 | Item item1 = new Item("BOOK", id);
75 | Item item2 = new Item("POTION", id);
76 | List
- itemList = new ArrayList<>();
77 | itemList.addAll(Arrays.asList(item1, item2));
78 | player.setCards(itemList);
79 | assertEquals(2, player.getCards().size());
80 | assertEquals(item1, player.getCards().get(0).getItem());
81 | assertEquals(item2, player.getCards().get(1).getItem());
82 | List cards = player.getCards();
83 | cards = new ArrayList<>();
84 | assertFalse(player.getCards().isEmpty());
85 | }
86 |
87 | @Test
88 | public void testRemoveItemCard() {
89 | int id = 1;
90 | PlayerModel player = new PlayerModel(id);
91 | Item item1 = new Item("BOOK", id);
92 | Item item2 = new Item("POTION", id);
93 | int numVisibleCards = 1;
94 | List
- itemList = Arrays.asList(item1, item2);
95 | player.setCards(itemList);
96 | assertFalse(player.removeCard(item1));
97 | assertFalse(player.removeCard(item2));
98 | player.setNumVisibleCards(numVisibleCards);
99 | player.flipCards();
100 | assertTrue(player.removeCard(item2));
101 | assertFalse(player.removeCard(item2));
102 | player.flipCards();
103 | assertTrue(player.removeCard(item1));
104 | assertFalse(player.removeCard(item1));
105 | }
106 |
107 | @Test
108 | public void testSetNumVisibleCards() {
109 | int id = 1;
110 | PlayerModel player = new PlayerModel(id);
111 | Item item1 = new Item("BOOK", id);
112 | Item item2 = new Item("POTION", id);
113 | Item item3 = new Item("ARROW", id);
114 | Item item4 = new Item("FISH", id);
115 | int numVisibleCards1 = 1;
116 | int numVisibleCards2 = 3;
117 | int numVisibleCards3 = 4;
118 | List
- itemList = Arrays.asList(item1, item2, item3, item4);
119 | player.setCards(itemList);
120 | player.setNumVisibleCards(numVisibleCards1);
121 | player.flipCards();
122 | assertEquals(1, player.getNumQuestCards());
123 | assertEquals(3, player.getNumDeckCards());
124 | player.setNumVisibleCards(numVisibleCards2);
125 | player.flipCards();
126 | assertEquals(3, player.getNumQuestCards());
127 | assertEquals(1, player.getNumDeckCards());
128 | player.setNumVisibleCards(numVisibleCards3);
129 | player.flipCards();
130 | assertEquals(3, player.getNumQuestCards());
131 | assertEquals(1, player.getNumDeckCards());
132 | }
133 |
134 | @Test
135 | public void testFlipCards() {
136 | int id = 1;
137 | PlayerModel player = new PlayerModel(id);
138 | Item item1 = new Item("BOOK", id);
139 | Item item2 = new Item("POTION", id);
140 | Item item3 = new Item("ARROW", id);
141 | Item item4 = new Item("FISH", id);
142 | int numVisibleCards = 3;
143 | List
- itemList = Arrays.asList(item1, item2, item3, item4);
144 | player.flipCards(); // shall not produce errors
145 | assertEquals(0, player.getNumQuestCards());
146 | assertEquals(0, player.getNumDeckCards());
147 | player.setCards(itemList);
148 | player.flipCards();
149 | assertEquals(0, player.getNumQuestCards());
150 | assertEquals(4, player.getNumDeckCards());
151 | player.setNumVisibleCards(numVisibleCards);
152 | player.flipCards();
153 | assertEquals(3, player.getNumQuestCards());
154 | assertEquals(1, player.getNumDeckCards());
155 | player.flipCards();
156 | assertEquals(3, player.getNumQuestCards());
157 | assertEquals(1, player.getNumDeckCards());
158 | }
159 |
160 | @Test
161 | public void testPlayerToString() {
162 | int id = 1;
163 | PlayerModel player = new PlayerModel(id);
164 | Vector2 pos = new Vector2(1, 2);
165 | TileModel tile = new TileModel("1111", pos);
166 | player.setTile(tile);
167 | Item item1 = new Item("BOOK", 1);
168 | Item item2 = new Item("POTION", 1);
169 | List
- itemList = new ArrayList<>();
170 | itemList.addAll(Arrays.asList(item1, item2));
171 | player.setCards(itemList);
172 | assertEquals("2 6 6 1111", player.playerToString());
173 | }
174 |
175 | @Test
176 | public void testMoveToPos() {
177 | int id = 1;
178 | PlayerModel player = new PlayerModel(id);
179 | assertEquals(new Vector2(6, 6), player.getPos());
180 | Vector2 pos = new Vector2(6, 5);
181 | player.move(pos);
182 | assertEquals(pos, player.getPos());
183 | }
184 |
185 | @Test
186 | public void testMoveInDirection() {
187 | int id = 1;
188 | PlayerModel player = new PlayerModel(id);
189 | player.move(Constants.Direction.UP);
190 | assertEquals(new Vector2(6, 5), player.getPos());
191 | player.move(Constants.Direction.LEFT);
192 | assertEquals(new Vector2(5, 5), player.getPos());
193 | player.move(Constants.Direction.DOWN);
194 | assertEquals(new Vector2(5, 6), player.getPos());
195 | player.move(Constants.Direction.RIGHT);
196 | assertEquals(new Vector2(6, 6), player.getPos());
197 | }
198 | }
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/Model/TileModelTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Model;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertFalse;
5 | import static org.junit.Assert.assertNull;
6 | import static org.junit.Assert.assertTrue;
7 |
8 | import org.junit.Test;
9 |
10 | import com.codingame.game.Utils.Constants;
11 | import com.codingame.game.Utils.Vector2;
12 |
13 | public class TileModelTest {
14 |
15 | @Test(expected=AssertionError.class)
16 | public void testAssertionsEnabled() {
17 | assert false;
18 | }
19 |
20 | @Test(expected=AssertionError.class)
21 | public void testTileIncorrectPatternDigit() throws AssertionError {
22 | TileModel tile = new TileModel("1112", new Vector2(1, 2));
23 | }
24 |
25 | @Test(expected=AssertionError.class)
26 | public void testTileIncorrectPatternLength() throws AssertionError {
27 | TileModel tile = new TileModel("11100", new Vector2(1, 2));
28 | }
29 |
30 | @Test(expected=AssertionError.class)
31 | public void testTileSetIncorrectItem() throws AssertionError {
32 | TileModel tile = new TileModel("1111", new Vector2(1, 2));
33 | tile.setItem(new Item("APPLE", 0));
34 | }
35 |
36 | @Test(expected=AssertionError.class)
37 | public void testTileSetItem() throws AssertionError {
38 | TileModel tile = new TileModel("1111", new Vector2(1, 2));
39 | tile.setItem(new Item("BOOK", 0));
40 | tile.setItem(new Item("ARROW", 0));
41 | }
42 |
43 | @Test(expected=AssertionError.class)
44 | public void testTileRemoveItem() throws AssertionError {
45 | TileModel tile = new TileModel("1111", new Vector2(1, 2));
46 | tile.removeItem();
47 | }
48 |
49 | @Test(expected=AssertionError.class)
50 | public void testOpponentTileNoItem() throws AssertionError {
51 | TileModel tile = new TileModel("1111", new Vector2(1, 2));
52 | tile.opponentTileToString();
53 | }
54 |
55 | @Test
56 | public void testSetPosExposure() {
57 | Vector2 pos = new Vector2(1, 2);
58 | TileModel tile = new TileModel("1111", pos);
59 | assertTrue(tile.getPos().equals(pos));
60 | pos.setX(4);
61 | pos.setY(3);
62 | assertFalse(tile.getPos().equals(pos));
63 | }
64 |
65 | @Test
66 | public void testGetPosExposure() {
67 | Vector2 pos = new Vector2(1, 2);
68 | TileModel tile = new TileModel("1111", pos);
69 | assertTrue(tile.getPos().equals(pos));
70 | Vector2 newPos = tile.getPos();
71 | newPos.setX(4);
72 | newPos.setY(3);
73 | assertTrue(tile.getPos().equals(pos));
74 | }
75 |
76 | @Test
77 | public void testConstructorPosExposure() {
78 | Vector2 pos = new Vector2(1, 2);
79 | TileModel tile = new TileModel("1111", pos);
80 | assertTrue(tile.getPos().equals(pos));
81 | pos.setX(4);
82 | pos.setY(3);
83 | assertTrue(tile.getPos().equals(new Vector2(1, 2)));
84 | }
85 |
86 | @Test
87 | public void testDirectionCheck() {
88 | Vector2 pos = new Vector2(1, 2);
89 | TileModel tile = new TileModel("1111", pos);
90 | assertTrue(tile.hasDirection(Constants.Direction.UP));
91 | assertTrue(tile.hasDirection(Constants.Direction.RIGHT));
92 | assertTrue(tile.hasDirection(Constants.Direction.DOWN));
93 | assertTrue(tile.hasDirection(Constants.Direction.LEFT));
94 | tile = new TileModel("0100", pos);
95 | assertFalse(tile.hasDirection(Constants.Direction.UP));
96 | assertTrue(tile.hasDirection(Constants.Direction.RIGHT));
97 | assertFalse(tile.hasDirection(Constants.Direction.DOWN));
98 | assertFalse(tile.hasDirection(Constants.Direction.LEFT));
99 | tile = new TileModel("0010", pos);
100 | assertFalse(tile.hasDirection(Constants.Direction.UP));
101 | assertFalse(tile.hasDirection(Constants.Direction.RIGHT));
102 | assertTrue(tile.hasDirection(Constants.Direction.DOWN));
103 | assertFalse(tile.hasDirection(Constants.Direction.LEFT));
104 | tile = new TileModel("0001", pos);
105 | assertFalse(tile.hasDirection(Constants.Direction.UP));
106 | assertFalse(tile.hasDirection(Constants.Direction.RIGHT));
107 | assertFalse(tile.hasDirection(Constants.Direction.DOWN));
108 | assertTrue(tile.hasDirection(Constants.Direction.LEFT));
109 | }
110 |
111 | @Test
112 | public void testRotatePattern() {
113 | Vector2 pos = new Vector2(1, 2);
114 | TileModel tile = new TileModel("1000", pos);
115 | assertTrue(tile.hasDirection(Constants.Direction.UP));
116 | tile.rotate(0);
117 | assertTrue(tile.hasDirection(Constants.Direction.UP));
118 | tile.rotate(1);
119 | assertTrue(tile.hasDirection(Constants.Direction.RIGHT));
120 | tile.rotate(2);
121 | assertTrue(tile.hasDirection(Constants.Direction.LEFT));
122 | tile.rotate(3);
123 | assertTrue(tile.hasDirection(Constants.Direction.DOWN));
124 | }
125 |
126 | @Test
127 | public void testGetSetItem() {
128 | Vector2 pos = new Vector2(1, 2);
129 | TileModel tile = new TileModel("1000", pos);
130 | assertFalse(tile.hasItem());
131 | assertNull(tile.getItem());
132 | Item item = new Item("BOOK", 0);
133 | tile.setItem(item);
134 | assertTrue(tile.hasItem());
135 | assertTrue(tile.getItem().equals(item));
136 | item = new Item("ARROW", 1);
137 | assertFalse(tile.getItem().equals(item));
138 | Item item2 = tile.getItem();
139 | item2 = new Item("ARROW", 1);
140 | assertFalse(tile.getItem().equals(item2));
141 | }
142 |
143 | @Test
144 | public void testRemoveItem() {
145 | Vector2 pos = new Vector2(1, 2);
146 | TileModel tile = new TileModel("1111", pos);
147 | Item item = new Item("BOOK", 0);
148 | tile.setItem(item);
149 | tile.removeItem();
150 | assertNull(tile.getItem());
151 | }
152 |
153 | @Test
154 | public void testPatternToString() {
155 | Vector2 pos = new Vector2(1, 2);
156 | TileModel tile = new TileModel("1010", pos);
157 | assertEquals("1010", tile.patternToString());
158 | }
159 |
160 | @Test
161 | public void testTileToString() {
162 | Vector2 pos = new Vector2(1, 2);
163 | TileModel tile = new TileModel("1010", pos);
164 | Item item = new Item("BOOK", 0);
165 | tile.setItem(item);
166 | assertEquals("BOOK 1 2 0", tile.tileToString());
167 | tile.removeItem();
168 | assertEquals("", tile.tileToString());
169 | }
170 |
171 | @Test
172 | public void testMoveTileToPos() {
173 | Vector2 pos = new Vector2(1, 2);
174 | TileModel tile = new TileModel("1010", pos);
175 | Vector2 newPos = new Vector2(3, 4);
176 | tile.move(newPos);
177 | assertEquals(newPos, tile.getPos());
178 | newPos = new Vector2(0, 0);
179 | tile.move(newPos);
180 | assertEquals(newPos, tile.getPos());
181 | newPos = Vector2.MINUS_ONE;
182 | tile.move(newPos);
183 | assertEquals(newPos, tile.getPos());
184 | }
185 |
186 | @Test
187 | public void testMoveTileInDirection() {
188 | Vector2 pos = new Vector2(1, 2);
189 | TileModel tile = new TileModel("1010", pos);
190 | tile.move(Constants.Direction.UP);
191 | assertEquals(new Vector2(1, 1), tile.getPos());
192 | tile.move(Constants.Direction.RIGHT);
193 | assertEquals(new Vector2(2, 1), tile.getPos());
194 | tile.move(Constants.Direction.DOWN);
195 | assertEquals(new Vector2(2, 2), tile.getPos());
196 | tile.move(Constants.Direction.LEFT);
197 | assertEquals(new Vector2(1, 2), tile.getPos());
198 | }
199 |
200 | @Test
201 | public void testIsThreeWayPlus() {
202 | TileModel tile1 = new TileModel("0000",new Vector2(1, 2));
203 | TileModel tile2 = new TileModel("1010",new Vector2(1, 2));
204 | TileModel tile3 = new TileModel("1110",new Vector2(1, 2));
205 | TileModel tile4 = new TileModel("1111",new Vector2(1, 2));
206 | assertFalse(tile1.isThreeWayPlus());
207 | assertFalse(tile2.isThreeWayPlus());
208 | assertTrue(tile3.isThreeWayPlus());
209 | assertTrue(tile4.isThreeWayPlus());
210 | }
211 |
212 | @Test
213 | public void testOpponentTile() {
214 | Vector2 pos1 = new Vector2(1, 2);
215 | TileModel tile = new TileModel("1010", pos1);
216 | Item item = new Item("BOOK", 0);
217 | tile.setItem(item);
218 | assertEquals("BOOK 1 2 1", tile.opponentTileToString());
219 | tile.setPos(Constants.TILE_MODEL_POSITIONS.get(0));
220 | tile.setPlayerId(0);
221 | assertEquals("BOOK -2 -2 1", tile.opponentTileToString());
222 | tile.setPos(Constants.TILE_MODEL_POSITIONS.get(1));
223 | tile.setPlayerId(1);
224 | assertEquals("BOOK -1 -1 1", tile.opponentTileToString());
225 | }
226 |
227 | @Test
228 | public void testPlayerId() {
229 | Vector2 pos = new Vector2(1, 2);
230 | Integer id = 1;
231 | TileModel tile = new TileModel("1010", pos);
232 | assertNull(tile.getPlayerId());
233 | tile.setPlayerId(id);
234 | assertEquals(id, tile.getPlayerId());
235 | }
236 |
237 | }
238 |
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/PlayerTest.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game;
2 |
3 | import com.codingame.game.Model.PlayerModel;
4 | import com.codingame.game.Utils.Constants;
5 | import org.junit.Rule;
6 | import org.junit.Test;
7 | import org.junit.rules.ExpectedException;
8 |
9 | import java.util.List;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | public class PlayerTest {
14 |
15 | @Test(expected=AssertionError.class)
16 | public void testAssertionsEnabled() {
17 | assert false;
18 | }
19 |
20 | @Test
21 | public void testCreateGetModel() {
22 | Player player = new Player();
23 | int id = player.getIndex();
24 | PlayerModel model = player.createPlayer();
25 | assertEquals(id, model.id);
26 | assertEquals(model, player.getPlayer());
27 | }
28 |
29 | @Test
30 | public void testGetModel() {
31 | Player player = new Player();
32 | int id = player.getIndex();
33 | assertEquals(id, player.createPlayer().id);
34 | }
35 | }
--------------------------------------------------------------------------------
/src/test/java/com/codingame/game/Utils/Vector2Test.java:
--------------------------------------------------------------------------------
1 | package com.codingame.game.Utils;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.*;
6 |
7 | import static org.junit.Assert.*;
8 |
9 |
10 | /**
11 | * Test suite for Vector2 specs.
12 | */
13 | public class Vector2Test {
14 |
15 | @Test(expected=AssertionError.class)
16 | public void testAssertionsEnabled() {
17 | assert false;
18 | }
19 |
20 | @Test
21 | public void testNegativeConstants() {
22 | Vector2 vector1 = Vector2.MINUS_ONE;
23 | assertEquals(-1, vector1.getX());
24 | assertEquals(-1, vector1.getY());
25 | Vector2 vector2 = Vector2.MINUS_TWO;
26 | assertEquals(-2, vector2.getX());
27 | assertEquals(-2, vector2.getY());
28 | }
29 |
30 | @Test
31 | public void testVectorConstructorMutator() {
32 | Vector2 vector = new Vector2(3, 5);
33 | assertEquals(3, vector.getX());
34 | assertEquals(5, vector.getY());
35 | vector.setX(4);
36 | vector.setY(2);
37 | assertEquals(4, vector.getX());
38 | assertEquals(2, vector.getY());
39 | }
40 |
41 | @Test
42 | public void testVectorFromAnotherVector() {
43 | Vector2 vector1 = new Vector2(3, 5);
44 | Vector2 vector2 = new Vector2(vector1);
45 | vector1.setX(4);
46 | vector1.setY(2);
47 | assertEquals(3, vector2.getX());
48 | assertEquals(5, vector2.getY());
49 | }
50 |
51 | @Test
52 | public void testVectorWrapping() {
53 | Vector2 vector1 = new Vector2(3, 5);
54 | Vector2 vector2 = new Vector2(2, -3);
55 | Vector2 vector3 = new Vector2(-4, 2);
56 | Vector2 vector4 = new Vector2(1, 4);
57 | vector1.wrap(vector2);
58 | assertEquals(5, vector1.getX());
59 | assertEquals(2, vector1.getY());
60 | vector1.wrap(vector3);
61 | assertEquals(1, vector1.getX());
62 | assertEquals(4, vector1.getY());
63 | vector1.wrap(vector4);
64 | assertEquals(2, vector1.getX());
65 | assertEquals(1, vector1.getY());
66 | vector1.wrap(vector3);
67 | assertEquals(5, vector1.getX());
68 | assertEquals(3, vector1.getY());
69 | }
70 |
71 | @Test
72 | public void testVectorAddition() {
73 | Vector2 vector1 = new Vector2(3, 5);
74 | Vector2 vector2 = new Vector2(-4, 2);
75 | vector1.add(vector2);
76 | assertEquals(-1, vector1.getX());
77 | assertEquals(7, vector1.getY());
78 |
79 | }
80 |
81 | @Test
82 | public void testVectorMovement() {
83 | Vector2 vector1 = new Vector2(2, 4);
84 | vector1.add(Vector2.UP);
85 | assertEquals(2, vector1.getX());
86 | assertEquals(3, vector1.getY());
87 | vector1.add(Vector2.RIGHT);
88 | assertEquals(3, vector1.getX());
89 | assertEquals(3, vector1.getY());
90 | vector1.add(Vector2.DOWN);
91 | assertEquals(3, vector1.getX());
92 | assertEquals(4, vector1.getY());
93 | vector1.add(Vector2.LEFT);
94 | assertEquals(2, vector1.getX());
95 | assertEquals(4, vector1.getY());
96 | }
97 |
98 | @Test
99 | public void testVectorEquality() {
100 | Set set = new HashSet<>();
101 | Vector2 vector1 = new Vector2(3, 5);
102 | Vector2 vector2 = new Vector2(2, 4);
103 | set.add(vector1);
104 | set.add(vector2);
105 | assertTrue(set.contains(vector1));
106 | assertTrue(set.contains(vector2));
107 | assertEquals(2, set.size());
108 | vector1.setX(2);
109 | vector1.setY(4);
110 | assertTrue(set.contains(vector1));
111 | assertTrue(set.contains(vector2));
112 | assertEquals(2, set.size());
113 | }
114 |
115 | @Test
116 | public void testVectorToString() {
117 | Vector2 vector = new Vector2(3, 5);
118 | assertEquals("3 5", vector.toString());
119 | }
120 |
121 | @Test
122 | public void testVectorToTooltip() {
123 | Vector2 vector = new Vector2(3, 5);
124 | assertEquals("pos: (3, 5)", vector.toTooltip());
125 | }
126 | }
--------------------------------------------------------------------------------
/src/test/resources/log4j2.properties:
--------------------------------------------------------------------------------
1 | # Configuration
2 | name = PropertiesConfig
3 | status = WARN
4 |
5 | appender.console.type = Console
6 | appender.console.name = CONSOLE
7 | appender.console.layout.type = PatternLayout
8 | appender.console.layout.pattern = [%d{yyyy/MM/dd HH:mm:ss}][GF] %-5p : %c{1} - %m%n
9 |
10 | rootLogger.level = warn
11 | rootLogger.appenderRef.console.ref = CONSOLE
12 |
--------------------------------------------------------------------------------