-
Notifications
You must be signed in to change notification settings - Fork 2
/
GameManager.java
executable file
·140 lines (119 loc) · 5.47 KB
/
GameManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package net.exkazuu.battle2048.game;
import com.google.common.collect.ImmutableMap;
import net.exkazuu.gameaiarena.api.Direction4;
import net.exkazuu.gameaiarena.api.Point2;
import net.exkazuu.gameaiarena.controller.LimitingSumTimeController;
import net.exkazuu.gameaiarena.controller.LimitingTimeController;
import net.exkazuu.gameaiarena.controller.Controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GameManager {
private static final Map<Character, Direction4> charToDirection = ImmutableMap.of(
'L', Direction4.LEFT, 'U', Direction4.UP, 'R', Direction4.RIGHT, 'D', Direction4.DOWN
);
private final Game _game;
private final List<Controller<Game, String[]>> _initCtrls;
private final List<Controller<Game, String[]>> _mainCtrls;
private final int _initTimeLimit;
private final int _mainTurnTimeLimit;
private final int _mainSumTimeLimit;
public final GameRecorder recorder;
public GameManager(List<Controller<Game, String[]>> initCtrls, List<Controller<Game, String[]>> mainCtrls, int initTimeLimit, int mainTurnTimeLimit, int mainSumTimeLimit) {
_game = new Game();
_initCtrls = initCtrls;
_mainCtrls = mainCtrls;
_initTimeLimit = initTimeLimit;
_mainTurnTimeLimit = mainTurnTimeLimit;
_mainSumTimeLimit = mainSumTimeLimit;
recorder = new GameRecorder();
}
public GameResult start() {
for (int playerIndex = 0; playerIndex < _initCtrls.size(); playerIndex++) {
LimitingTimeController<Game, String[]> controller = new LimitingTimeController<>(_initCtrls.get(playerIndex), _initTimeLimit);
String[] result = controller.run(_game);
if (controller.timeExceeded()) {
return killController(DefeatReason.TIME_LIMIT_EXCEEDED_AT_INIT, playerIndex);
}
this.recorder.add(new TurnRecord(playerIndex)
.setAIInput(Integer.toString(playerIndex))
.setAIOutput(result)
.setRuntime(controller.getLastConsumedMillisecond())
);
if (result.length != 2) {
return killController(DefeatReason.PRESENTATION_ERROR_AT_INIT, playerIndex);
}
int x, y;
try {
y = Integer.parseInt(result[0]) - 1;
x = Integer.parseInt(result[1]) - 1;
} catch (Exception e) {
return killController(DefeatReason.PRESENTATION_ERROR_AT_INIT, playerIndex);
}
DefeatReason reason = _game.advanceInitialPhase(playerIndex, new Point2(x, y));
if (reason != null) {
return killController(reason, playerIndex);
}
}
List<LimitingSumTimeController<Game, String[]>> limitingSumTimeControllers = new ArrayList<>();
for (Controller<Game, String[]> controller : _mainCtrls) {
limitingSumTimeControllers.add(new LimitingSumTimeController<>(controller, 0, _mainSumTimeLimit));
}
while (!_game.finished()) {
for (int playerIndex = 0; playerIndex < _mainCtrls.size(); playerIndex++) {
if (!_game.getMyBoard(playerIndex).canMove()) {
return killController(DefeatReason.CANNOT_MOVE_AT_MAIN, playerIndex);
}
LimitingSumTimeController<Game, String[]> limitingSumTimeController = limitingSumTimeControllers.get(playerIndex);
LimitingTimeController<Game, String[]> limitingTimeController = new LimitingTimeController<>(limitingSumTimeController, _mainTurnTimeLimit);
_game.setMyTimeLeft(playerIndex, limitingSumTimeController.getRestExceededMillisecond());
String[] result = limitingTimeController.run(_game);
if (limitingSumTimeController.timeExceeded() || limitingTimeController.timeExceeded()) {
return killController(DefeatReason.TIME_LIMIT_EXCEEDED_AT_MAIN_OR_ATTACK, playerIndex);
}
this.recorder.add(new TurnRecord(playerIndex)
.setAIInput(_game, playerIndex)
.setAIOutput(result)
.setRuntime(limitingTimeController.getLastConsumedMillisecond())
);
if (result.length < 5) {
return killController(DefeatReason.PRESENTATION_ERROR_AT_MAIN_OR_ATTACK, playerIndex);
}
if (result[0].length() != 1 || !charToDirection.containsKey(result[0].charAt(0))) {
return killController(DefeatReason.PRESENTATION_ERROR_AT_MAIN_OR_ATTACK, playerIndex);
}
Direction4 d = charToDirection.get(result[0].charAt(0));
int M, V;
try {
M = Integer.parseInt(result[1]);
V = Integer.parseInt(result[2]);
} catch (Exception e) {
return killController(DefeatReason.PRESENTATION_ERROR_AT_MAIN_OR_ATTACK, playerIndex);
}
if (result.length != 3 + M * 2) {
return killController(DefeatReason.PRESENTATION_ERROR_AT_MAIN_OR_ATTACK, playerIndex);
}
List<Point2> ps = new ArrayList<>();
for (int i = 0; i < M * 2; i += 2) {
try {
int y = Integer.parseInt(result[i + 3]) - 1;
int x = Integer.parseInt(result[i + 4]) - 1;
ps.add(new Point2(x, y));
} catch (Exception e) {
return killController(DefeatReason.PRESENTATION_ERROR_AT_MAIN_OR_ATTACK, playerIndex);
}
}
DefeatReason reason = _game.advanceMainAndAttackPhase(playerIndex, d, M, V, ps);
if (reason != null) {
return killController(reason, playerIndex);
}
}
}
return _game.judge();
}
private GameResult killController(DefeatReason reason, int playerIndex) {
_initCtrls.get(playerIndex).release();
_mainCtrls.get(playerIndex).release();
return _game.lose(playerIndex, reason);
}
}