Finish go
This commit is contained in:
parent
5351850fa1
commit
6125ac5eab
3 changed files with 179 additions and 82 deletions
|
@ -1,14 +1,62 @@
|
||||||
|
|
||||||
let stones = document.getElementsByClassName('go-stone-empty');
|
function setupEventHandler() {
|
||||||
let inputRow = document.getElementById('go-input-row');
|
let stones = document.getElementsByClassName('go-stone-empty');
|
||||||
let inputCol = document.getElementById('go-input-col');
|
let inputRow = document.getElementById('go-input-row');
|
||||||
let inputPlace = document.getElementById('go-input-place');
|
let inputCol = document.getElementById('go-input-col');
|
||||||
|
let inputPlace = document.getElementById('go-input-place');
|
||||||
|
|
||||||
for (let i = 0; i < stones.length; ++i) {
|
for (let i = 0; i < stones.length; ++i) {
|
||||||
stones[i].onclick = (e) => {
|
stones[i].onclick = (e) => {
|
||||||
console.log('place');
|
console.log('place');
|
||||||
inputCol.value = stones[i].attributes['data-col'].value;
|
inputCol.value = stones[i].attributes['data-col'].value;
|
||||||
inputRow.value = stones[i].attributes['data-row'].value;
|
inputRow.value = stones[i].attributes['data-row'].value;
|
||||||
inputPlace.click();
|
inputPlace.click();
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let updateInterval = null;
|
||||||
|
if (document.getElementsByClassName('go-territory').length == 0) {
|
||||||
|
setInterval(update, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
req.addEventListener('load', (ev) => {
|
||||||
|
let parser = new DOMParser();
|
||||||
|
let doc = parser.parseFromString(req.responseText, 'text/html');
|
||||||
|
let currentField = document.querySelector('svg');
|
||||||
|
let newField = doc.querySelector('svg');
|
||||||
|
let currentStones = currentField.getElementsByClassName('go-stone');
|
||||||
|
let newStones = newField.getElementsByClassName('go-stone');
|
||||||
|
let newTerritory = doc.getElementsByClassName('go-territory');
|
||||||
|
let currentInfo = document.getElementById('gameinfo');
|
||||||
|
let newInfo = doc.getElementById('gameinfo');
|
||||||
|
if (newTerritory.length > 0) {
|
||||||
|
window.location.reload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < currentStones.length; ++i) {
|
||||||
|
if (doc.getElementById(currentStones[i].id) === null) {
|
||||||
|
currentStones[i].remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentInfo.classList[0] != newInfo.classList[0]) {
|
||||||
|
console.log(newInfo.classList[0]);
|
||||||
|
currentInfo.innerHTML = newInfo.innerHTML;
|
||||||
|
currentInfo.classList.remove(currentInfo.classList[0]);
|
||||||
|
currentInfo.classList.add(newInfo.classList[0]);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < newStones.length; ++i) {
|
||||||
|
if (document.getElementById(newStones[i].id) === null) {
|
||||||
|
currentField.append(newStones[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupEventHandler();
|
||||||
|
});
|
||||||
|
req.open('GET', window.location.href);
|
||||||
|
req.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupEventHandler();
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
{%- block body %}
|
{%- block body %}
|
||||||
<h1>Go: {{ game.human_id }}</h1>
|
<h1>Go: {{ game.human_id }}</h1>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST" id="gogame">
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="{{ 50 * boardsize }}" height="{{ 50 * boardsize }}" version="2.0">
|
<svg xmlns="http://www.w3.org/2000/svg" id="gogamesvg "width="{{ 50 * boardsize }}" height="{{ 50 * boardsize }}" version="2.0">
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="white-stone" fx="40%" fy="25%">
|
<radialGradient id="white-stone" fx="40%" fy="25%">
|
||||||
<stop offset="0%" stop-color="#ffffff" />
|
<stop offset="0%" stop-color="#ffffff" />
|
||||||
|
@ -45,15 +45,15 @@
|
||||||
{% for col in range(boardsize) %}
|
{% for col in range(boardsize) %}
|
||||||
<!-- {{ row }} {{ col }} {{ field[row][col] }} -->
|
<!-- {{ row }} {{ col }} {{ field[row][col] }} -->
|
||||||
{% if field[row][col] == 0 and current_player == colormap[player.uuid] and not abandoned and score is none %}
|
{% if field[row][col] == 0 and current_player == colormap[player.uuid] and not abandoned and score is none %}
|
||||||
<circle class="go-stone go-stone-empty go-stone-{{ colormap[player.uuid].name.lower() }}" data-row="{{ row }}" data-col="{{ col }}" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
<circle id="go-stone-{{ row }}-{{ col }}-empty" class="go-stone go-stone-empty go-stone-{{ colormap[player.uuid].name.lower() }}" data-row="{{ row }}" data-col="{{ col }}" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
||||||
{% elif field[row][col] == 1 %}
|
{% elif field[row][col] == 1 %}
|
||||||
<circle class="go-stone go-stone-white" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
<circle id="go-stone-{{ row }}-{{ col }}-white" class="go-stone go-stone-white" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
||||||
{% elif field[row][col] == 2 %}
|
{% elif field[row][col] == 2 %}
|
||||||
<circle class="go-stone go-stone-black" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
<circle id="go-stone-{{ row }}-{{ col }}-black" class="go-stone go-stone-black" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
||||||
{% elif field[row][col] == 5 %}
|
{% elif field[row][col] == 5 %}
|
||||||
<circle class="go-stone go-stone-dead go-stone-white" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
<circle id="go-stone-{{ row }}-{{ col }}-white-dead" class="go-stone go-stone-dead go-stone-white" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
||||||
{% elif field[row][col] == 6 %}
|
{% elif field[row][col] == 6 %}
|
||||||
<circle class="go-stone go-stone-dead go-stone-black" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
<circle id="go-stone-{{ row }}-{{ col }}-black-dead" class="go-stone go-stone-dead go-stone-black" cx="{{ col * 50 + 25 }}" cy="{{ row * 50 + 25 }}" r="20" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -61,65 +61,71 @@
|
||||||
{% for col in range(boardsize) %}
|
{% for col in range(boardsize) %}
|
||||||
<!-- {{ territory[row][col] }} -->
|
<!-- {{ territory[row][col] }} -->
|
||||||
{% if territory[row][col] == 3 %}
|
{% if territory[row][col] == 3 %}
|
||||||
<rect class="go-territory go-territory-white" x="{{ col * 50 + 20 }}" y="{{ row * 50 + 20 }}" width="10" height="10" />
|
<rect id="go-territory-{{ row }}-{{ col }}-white" class="go-territory go-territory-white" x="{{ col * 50 + 20 }}" y="{{ row * 50 + 20 }}" width="10" height="10" />
|
||||||
{% elif territory[row][col] == 4 %}
|
{% elif territory[row][col] == 4 %}
|
||||||
<rect class="go-territory go-territory-black" x="{{ col * 50 + 20 }}" y="{{ row * 50 + 20 }}" width="10" height="10" />
|
<rect id="go-territory-{{ row }}-{{ col }}-white" class="go-territory go-territory-black" x="{{ col * 50 + 20 }}" y="{{ row * 50 + 20 }}" width="10" height="10" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if abandoned %}
|
<div id="gameinfo" class="{% if abandoned or score is not none %}over{% elif current_player == colormap[player.uuid] %}active{% else %}passive{% endif %}">
|
||||||
<b>Game abandoned</b>
|
{% if abandoned %}
|
||||||
{% elif score is not none %}
|
<b>Game abandoned</b>
|
||||||
<b>
|
{% elif score is not none %}
|
||||||
{% if score > 0 %}
|
<b>
|
||||||
Black won with {{ score }} points.
|
{% if score > 0 %}
|
||||||
{% else %}
|
Black won with {{ score }} points.
|
||||||
White won with {{ -score }} points.
|
{% else %}
|
||||||
{% endif %}
|
White won with {{ -score }} points.
|
||||||
</b>
|
{% endif %}
|
||||||
{% elif current_player == colormap[player.uuid] %}
|
</b>
|
||||||
<input id="go-input-pass" name="go-input-submit" type="submit" value="Pass" />
|
{% elif current_player == colormap[player.uuid] %}
|
||||||
<input id="go-input-place" name="go-input-submit" type="submit" value="Place" />
|
{% if passed[0] %}White passed{% endif %}
|
||||||
<input id="go-input-row" name="go-input-row" type="hidden" value="-1" />
|
{% if passed[1] %}Black passed{% endif %}
|
||||||
<input id="go-input-col" name="go-input-col" type="hidden" value="-1" />
|
<input id="go-input-pass" name="go-input-submit" type="submit" value="Pass" />
|
||||||
{% endif %}
|
<input id="go-input-place" name="go-input-submit" type="submit" value="Place" />
|
||||||
|
<input id="go-input-row" name="go-input-row" type="hidden" value="-1" />
|
||||||
|
<input id="go-input-col" name="go-input-col" type="hidden" value="-1" />
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="{{ baseurl }}/{{ player.uuid }}/{{ game.uuid }}/play">Refresh</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for p in players.keys() %}
|
||||||
|
<li>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" version="2.0">
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="white-stone" fx="40%" fy="25%">
|
||||||
|
<stop offset="0%" stop-color="#ffffff" />
|
||||||
|
<stop offset="70%" stop-color="#dddddd" />
|
||||||
|
<stop offset="100%" stop-color="#bbbbbb" />
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="black-stone" fx="40%" fy="25%">
|
||||||
|
<stop offset="0%" stop-color="#444444" />
|
||||||
|
<stop offset="70%" stop-color="#222222" />
|
||||||
|
<stop offset="100%" stop-color="#000000" />
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
<circle class="go-stone go-stone-{{ colormap[p].name.lower() }}" cx="10" cy="10" r="9" />
|
||||||
|
</svg>
|
||||||
|
{% if p == player.uuid %}
|
||||||
|
<b>{{ game.players[p].name }}</b>
|
||||||
|
{% elif aiplayer is not none and p == aiplayer.uuid %}
|
||||||
|
GNU Go AI
|
||||||
|
{% else %}
|
||||||
|
{{ game.players[p].name }}
|
||||||
|
{% endif %}
|
||||||
|
: {{ captures[colormap[p].value-1] }}
|
||||||
|
{% if colormap[p].value == 1 %}
|
||||||
|
+ {{ komi }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<a href="{{ baseurl }}/{{ player.uuid }}/{{ game.uuid }}/play">Refresh</a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{% for p in players.keys() %}
|
|
||||||
<li>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" version="2.0">
|
|
||||||
<defs>
|
|
||||||
<radialGradient id="white-stone" fx="40%" fy="25%">
|
|
||||||
<stop offset="0%" stop-color="#ffffff" />
|
|
||||||
<stop offset="70%" stop-color="#dddddd" />
|
|
||||||
<stop offset="100%" stop-color="#bbbbbb" />
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="black-stone" fx="40%" fy="25%">
|
|
||||||
<stop offset="0%" stop-color="#444444" />
|
|
||||||
<stop offset="70%" stop-color="#222222" />
|
|
||||||
<stop offset="100%" stop-color="#000000" />
|
|
||||||
</radialGradient>
|
|
||||||
</defs>
|
|
||||||
<circle class="go-stone go-stone-{{ colormap[p].name.lower() }}" cx="10" cy="10" r="9" />
|
|
||||||
</svg>
|
|
||||||
{% if p == player.uuid %}
|
|
||||||
<b>{{ game.players[p].name }}</b>
|
|
||||||
{% else %}
|
|
||||||
{{ game.players[p].name }}
|
|
||||||
{% endif %}
|
|
||||||
: {{ captures[colormap[p].value-1] }}
|
|
||||||
{% if colormap[p].value == 1 %}
|
|
||||||
+ {{ komi }}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<script src="{{ baseurl }}/static/gogame.js"></script>
|
<script src="{{ baseurl }}/static/gogame.js"></script>
|
||||||
{%- endblock %}
|
{%- endblock %}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import re
|
||||||
from threading import Timer, Lock
|
from threading import Timer, Lock
|
||||||
|
|
||||||
from webgames.puzzle import Puzzle
|
from webgames.puzzle import Puzzle
|
||||||
|
from webgames.player import Player
|
||||||
|
|
||||||
class BoardSize(enum.Enum):
|
class BoardSize(enum.Enum):
|
||||||
SMALL = 9
|
SMALL = 9
|
||||||
|
@ -48,6 +49,7 @@ class GoPuzzle(Puzzle):
|
||||||
self._field = None
|
self._field = None
|
||||||
self._territory = None
|
self._territory = None
|
||||||
self._abandoned = False
|
self._abandoned = False
|
||||||
|
self.ai = None
|
||||||
self._timer = None
|
self._timer = None
|
||||||
self._tlock = Lock()
|
self._tlock = Lock()
|
||||||
self._captures = [0, 0]
|
self._captures = [0, 0]
|
||||||
|
@ -76,12 +78,16 @@ class GoPuzzle(Puzzle):
|
||||||
with self._tlock:
|
with self._tlock:
|
||||||
self._timer = Timer(ABANDON_TIMEOUT, self._shutdown)
|
self._timer = Timer(ABANDON_TIMEOUT, self._shutdown)
|
||||||
self._timer.start()
|
self._timer.start()
|
||||||
|
ailevel = int(options.get('go-input-ailevel', 10))
|
||||||
self.size = BoardSize(int(options.get('go-input-boardsize', BoardSize.MEDIUM.value)))
|
self.size = BoardSize(int(options.get('go-input-boardsize', BoardSize.MEDIUM.value)))
|
||||||
self.gnugo = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
self.gnugo = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
self.gnugo.connect('/run/gnugo.sock')
|
self.gnugo.connect('/run/gnugo.sock')
|
||||||
self._gtp(f'boardsize {self.size.value}')
|
self._gtp(f'boardsize {self.size.value}')
|
||||||
self._gtp('clear_board')
|
self._gtp('clear_board')
|
||||||
self._gtp(f'komi {self.komi}')
|
self._gtp(f'komi {self.komi}')
|
||||||
|
if len(self._players) == 1:
|
||||||
|
self.ai = Player('GnuGO AI')
|
||||||
|
self._players[self.ai.uuid] = self.ai.uuid
|
||||||
players = list(self._players.keys())
|
players = list(self._players.keys())
|
||||||
random.shuffle(players)
|
random.shuffle(players)
|
||||||
self.colormap[players[0]] = FieldState.BLACK
|
self.colormap[players[0]] = FieldState.BLACK
|
||||||
|
@ -95,16 +101,33 @@ class GoPuzzle(Puzzle):
|
||||||
self._field[i].append(0)
|
self._field[i].append(0)
|
||||||
self._territory[i].append(0)
|
self._territory[i].append(0)
|
||||||
self._urlbase = urlbase
|
self._urlbase = urlbase
|
||||||
|
# First move if GnuGO AI is black
|
||||||
|
if self.ai is not None:
|
||||||
|
self._gtp(f'level {ailevel}')
|
||||||
|
if self.colormap[self.ai.uuid] == FieldState.BLACK:
|
||||||
|
self._gtp('genmove_black')
|
||||||
|
self.current_player = FieldState(3 - self.current_player.value)
|
||||||
|
self.update_field()
|
||||||
|
|
||||||
def get_extra_options_html(self) -> str:
|
def get_extra_options_html(self) -> str:
|
||||||
return '''
|
options = '''
|
||||||
<label for="go-input-boardsize">Board Size: </label>
|
<label for="go-input-boardsize">Board Size: </label>
|
||||||
<select id="go-input-boardsize" name="go-input-boardize">
|
<select id="go-input-boardsize" name="go-input-boardsize">
|
||||||
<option value="9">9x9</option>
|
<option value="9">9x9</option>
|
||||||
<option value="13">13x13</option>
|
<option value="13" selected="selected">13x13</option>
|
||||||
<option value="19">19x19</option>
|
<option value="19">19x19</option>
|
||||||
</select>
|
</select>
|
||||||
'''
|
'''
|
||||||
|
if len(self._players) == 1:
|
||||||
|
options += '''
|
||||||
|
<p>
|
||||||
|
Press Play! to play against GNU Go or invite a second player.
|
||||||
|
<label for="go-input-ailevel">GNU Go Level: </label>
|
||||||
|
<input id="go-input-ailevel" name="go-input-ailevel" type="number" min="0" max="10" value="10" />
|
||||||
|
</p>
|
||||||
|
'''
|
||||||
|
return options
|
||||||
|
|
||||||
|
|
||||||
def add_player(self, uuid: UUID) -> None:
|
def add_player(self, uuid: UUID) -> None:
|
||||||
if len(self._players) >= 2:
|
if len(self._players) >= 2:
|
||||||
|
@ -128,14 +151,16 @@ class GoPuzzle(Puzzle):
|
||||||
for vertex in vertices:
|
for vertex in vertices:
|
||||||
if len(vertex.strip()) != 2:
|
if len(vertex.strip()) != 2:
|
||||||
continue
|
continue
|
||||||
y, x = vertex.strip()
|
x, y = vertex.strip()
|
||||||
col = int(x) - 1
|
row = int(y) - 1
|
||||||
row = self.colnames.index(y.upper())
|
col = self.colnames.index(x.upper())
|
||||||
if state == 'dead':
|
if state == 'dead':
|
||||||
if self._field[row][col] == FieldState.BLACK.value:
|
if self._field[row][col] == FieldState.BLACK.value:
|
||||||
self._field[row][col] = FieldState.BLACK_DEAD.value
|
self._field[row][col] = FieldState.BLACK_DEAD.value
|
||||||
|
self._territory[row][col] = FieldState.WHITE_TERRITORY.value
|
||||||
elif self._field[row][col] == FieldState.WHITE.value:
|
elif self._field[row][col] == FieldState.WHITE.value:
|
||||||
self._field[row][col] = FieldState.WHITE_DEAD.value
|
self._field[row][col] = FieldState.WHITE_DEAD.value
|
||||||
|
self._territory[row][col] = FieldState.BLACK_TERRITORY.value
|
||||||
elif state == 'black_territory':
|
elif state == 'black_territory':
|
||||||
self._territory[row][col] = FieldState.BLACK_TERRITORY.value
|
self._territory[row][col] = FieldState.BLACK_TERRITORY.value
|
||||||
elif state == 'white_territory':
|
elif state == 'white_territory':
|
||||||
|
@ -145,11 +170,10 @@ class GoPuzzle(Puzzle):
|
||||||
|
|
||||||
|
|
||||||
def process_action(self, player, action) -> None:
|
def process_action(self, player, action) -> None:
|
||||||
if self.colormap[player] != self.current_player:
|
if self.colormap[player] != self.current_player or self.gnugo is None:
|
||||||
return
|
return
|
||||||
if 'go-input-submit' not in action:
|
if 'go-input-submit' not in action:
|
||||||
return
|
return
|
||||||
self.current_player = FieldState(3 - self.current_player.value)
|
|
||||||
with self._tlock:
|
with self._tlock:
|
||||||
if self._abandoned:
|
if self._abandoned:
|
||||||
return
|
return
|
||||||
|
@ -173,17 +197,34 @@ class GoPuzzle(Puzzle):
|
||||||
try:
|
try:
|
||||||
ret = self._gtp(f'play {player} {self.colnames[col]}{row+1}')
|
ret = self._gtp(f'play {player} {self.colnames[col]}{row+1}')
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
self.current_player = FieldState[3 - self.current_player.value]
|
return
|
||||||
self.update_field()
|
if self.ai is None:
|
||||||
|
self.current_player = FieldState(3 - self.current_player.value)
|
||||||
|
elif self.gnugo is not None:
|
||||||
|
ai_color = self.colormap[self.ai.uuid].name.lower()
|
||||||
|
ai_resp = self._gtp(f'genmove_{ai_color}')
|
||||||
|
if 'pass' in ai_resp.lower():
|
||||||
|
if self.colormap[self.ai.uuid] == FieldState.BLACK:
|
||||||
|
self.black_passed = True
|
||||||
|
else:
|
||||||
|
self.white_passed = True
|
||||||
|
if self.black_passed and self.white_passed:
|
||||||
|
self._score_game()
|
||||||
|
else:
|
||||||
|
self.black_passed = False
|
||||||
|
self.white_passed = False
|
||||||
|
self.update_field()
|
||||||
|
|
||||||
def update_field(self):
|
def update_field(self):
|
||||||
|
if self.gnugo is None:
|
||||||
|
return
|
||||||
ret = self._gtp('showboard')
|
ret = self._gtp('showboard')
|
||||||
for line in ret.splitlines():
|
for line in ret.splitlines():
|
||||||
|
|
||||||
cm = re.match('.*(BLACK|WHITE) ... has captured (\\d+) stones.*', line)
|
cm = re.match('.*(BLACK|WHITE) ... has captured (\\d+) stones.*', line)
|
||||||
if cm is not None:
|
if cm is not None:
|
||||||
color = FieldState[cm[1]]
|
color = FieldState[cm[1]]
|
||||||
self._captures[2-color.value] = int(cm[2])
|
self._captures[color.value-1] = int(cm[2])
|
||||||
|
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if len(line) > 0 and line[0] in [str(i) for i in range(10)]:
|
if len(line) > 0 and line[0] in [str(i) for i in range(10)]:
|
||||||
|
@ -194,9 +235,9 @@ class GoPuzzle(Puzzle):
|
||||||
if token in ['.', '+']:
|
if token in ['.', '+']:
|
||||||
self._field[row][col] = FieldState.EMPTY.value
|
self._field[row][col] = FieldState.EMPTY.value
|
||||||
elif token == 'X':
|
elif token == 'X':
|
||||||
self._field[row][col] = FieldState.WHITE.value
|
|
||||||
elif token == 'O':
|
|
||||||
self._field[row][col] = FieldState.BLACK.value
|
self._field[row][col] = FieldState.BLACK.value
|
||||||
|
elif token == 'O':
|
||||||
|
self._field[row][col] = FieldState.WHITE.value
|
||||||
|
|
||||||
def serialize(self, player):
|
def serialize(self, player):
|
||||||
return {
|
return {
|
||||||
|
@ -214,6 +255,7 @@ class GoPuzzle(Puzzle):
|
||||||
ser = self.serialize(player)
|
ser = self.serialize(player)
|
||||||
return tmpl.render(player=player,
|
return tmpl.render(player=player,
|
||||||
players=self._players,
|
players=self._players,
|
||||||
|
aiplayer=self.ai,
|
||||||
komi=self.komi,
|
komi=self.komi,
|
||||||
score=self._score,
|
score=self._score,
|
||||||
game=game,
|
game=game,
|
||||||
|
@ -222,6 +264,7 @@ class GoPuzzle(Puzzle):
|
||||||
field=ser['field'],
|
field=ser['field'],
|
||||||
territory=ser['territory'],
|
territory=ser['territory'],
|
||||||
captures=ser['captures'],
|
captures=ser['captures'],
|
||||||
|
passed=[self.white_passed, self.black_passed],
|
||||||
boardsize=self.size.value,
|
boardsize=self.size.value,
|
||||||
colormap=self.colormap,
|
colormap=self.colormap,
|
||||||
current_player=self.current_player,
|
current_player=self.current_player,
|
||||||
|
|
Loading…
Reference in a new issue