Add big (double-counting for ownership) followers

This commit is contained in:
s3lph 2021-11-07 20:45:14 +01:00
parent 709ee94ad6
commit 8ce67e4b78
2 changed files with 91 additions and 9 deletions

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
{% if not done %}
{% if not done and current_player.uuid != me.uuid %}
<meta http-equiv="refresh" content="3" />
{% endif %}
<style>
@ -22,6 +22,10 @@
stroke: cyan;
stroke-width: 3px;
}
svg .claimable.hover {
stroke: cyan;
stroke-width: 3px;
}
svg .empty {
fill: transparent;
@ -98,9 +102,15 @@
pointer-events: none;
}
input[type="number"], input[value="Place Tile"], select {
input[type="number"], input[value="Place Tile"], input[type="radio"], select {
display: none;
}
input[name="follower"]:checked + label.follower-label .follower {
stroke-width: 3px;
stroke: black;
}
svg [droppable="true"]
</style>
</head>
<body>
@ -121,6 +131,9 @@
<input type="submit" value="Place Tile" name="action" id="btn-place" />
{% endif %}
{% if phase == 'claim' %}
{% for follower in me.followers %}
{{ follower.resting_svg() }}
{% endfor %}
<select name="claim">
{{ claimable }}
</select>
@ -139,16 +152,46 @@
};
let claimables = document.getElementsByClassName('claimable');
for (let i = 0; i < claimables.length; ++i) {
claimables[i].setAttribute('droppable', true);
claimables[i].onclick = (e) => {
c.elements.claim.value = e.target.getAttribute('data-uuid');
document.getElementById('btn-claim').click();
};
};
follower = null;
document.addEventListener('dragstart', e => {
follower = e.target;
follower.style.opacity = 0.5;
e.dataTransfer.effectAllowed = 'move';
});
document.addEventListener('dragenter', e => {
e.target.classList.add('hover');
e.dataTransfer.dropEffect = 'move';
});
document.addEventListener('dragleave', e => {
e.target.classList.remove('hover');
});
document.addEventListener('dragend', e => {
follower.style.opacity = '';
});
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
follower.style.opacity = '';
if (!e.target.hasAttribute('data-uuid')) {
return;
}
c.elements.follower.value = follower.getAttribute('data-uuid');
c.elements.claim.value = e.target.getAttribute('data-uuid');
console.log(c.elements.follower.value + ' ' + c.elements.claim.value);
document.getElementById('btn-claim').click();
});
</script>
{% else %}
{% else %}{# my turn #}
It is <font color="{{ current_player.color.value.html }}">{{ game._players[current_player.uuid].name }}'s</font> turn.
{% endif %}
{% endif %}
{% endif %}{# my turn #}
{% endif %}{# done #}
<table border="1">
<tr><td>Name</td><td>Followers</td><td>Score</td></tr>
{% for player in players | sort(attribute='score', reverse=true) %}

View file

@ -305,13 +305,15 @@ class Resource:
b.joined = a
return a
def claim(self, player, card):
def claim(self, player, card, fuuid = None):
a = self.root()
if len(a.owners) > 0:
raise RuntimeError('Cannot claim already-claimed resource')
if len([1 for f in player.followers if f.resource is None]) == 0:
raise RuntimeError('Player has no followers left')
for f in player.followers:
if fuuid and f.uuid != fuuid:
continue
if f.resource is None:
a.owners.add(f)
f.claim(self, card)
@ -333,7 +335,7 @@ class Resource:
owners = {}
for follower in r.owners:
owners.setdefault(follower.player.uuid, 0)
owners[follower.player.uuid] += 1
owners[follower.player.uuid] += follower.weight
if not game_end:
r.unclaim()
nmax = max(owners.values(), default=0)
@ -698,6 +700,7 @@ class Follower:
self.cy = None
self.lx = 50
self.ly = 50
self.weight = 1
def claim(self, r, card):
if self.resource is not None:
@ -749,6 +752,37 @@ class Follower:
tmpl = env.get_template(f'carcassonne/follower.svg')
return tmpl.render(x=(self.cx+xoff)*100, y=(self.cy+yoff)*100, lx=self.lx, ly=self.ly, color=self.player.color.value.html)
def resting_svg(self):
svg = ''
color = '#666666'
drag = ''
if self.resource is None:
svg += f'<input type="radio" id="follower-{self.uuid}" name="follower" value="{self.uuid}" />'
color = self.player.color.value.html
drag = 'draggable="true"'
svg += f'<label class="follower-label" data-uuid="{self.uuid}" for="follower-{self.uuid}" {drag}><svg width="30" height="40" viewBox="-15 -20 30 40"><path class="follower" fill="{color}" d="M -5 -5 C -20 -20, 20 -20, 5 -5 L 10 0 L 10 5 L 5 0 L 5 10 L 10 15 L 5 15 L 0 10 L -5 15 L -10 15 L -5 10 L -5 0 L -10 5 L -10 0 Z" /></svg></label>'
return svg
class BigFollower(Follower):
def __init__(self, player):
super().__init__(player)
self.weight = 2
def svg(self, env, xoff, yoff):
return super().svg(env, xoff, yoff).replace(')" d=', ') scale(1.5)" d=', 1)
def resting_svg(self):
svg = ''
color = '#666666'
drag = ''
if self.resource is None:
svg += f'<input type="radio" id="follower-{self.uuid}" name="follower" value="{self.uuid}" />'
color = self.player.color.value.html
drag = 'draggable="true"'
svg += f'<label class="follower-label" data-uuid="{self.uuid}" for="follower-{self.uuid}" {drag}><svg width="30" height="40" viewBox="-15 -20 30 40"><path class="follower" fill="{color}" transform="scale(1.5)" d="M -5 -5 C -20 -20, 20 -20, 5 -5 L 10 0 L 10 5 L 5 0 L 5 10 L 10 15 L 5 15 L 0 10 L -5 15 L -10 15 L -5 10 L -5 0 L -10 5 L -10 0 Z" /></svg></label>'
return svg
class Carcassonne(Puzzle):
@ -773,7 +807,6 @@ class Carcassonne(Puzzle):
def add_player(self, uuid: UUID) -> None:
p = Player(uuid, len(self._turn_order))
self._players[uuid] = p
self._followers.extend(p.followers)
self._turn_order.append(uuid)
self._turn += 1
@ -791,6 +824,10 @@ class Carcassonne(Puzzle):
def begin(self, options, urlbase):
self._urlbase = urlbase
self._deck = Card.generate_deck(options.getall('extensions'), self._field)
for player in self._players.values():
if 'inns-cathedrals' in options.getall('extensions'):
player.followers.append(BigFollower(player))
self._followers.extend(player.followers)
random.shuffle(self._turn_order)
self.next_turn()
@ -864,9 +901,11 @@ class Carcassonne(Puzzle):
if self._phase != Phase.CLAIM:
return
cuuid = action.get('claim')
fuuid = action.get('follower', None)
if cuuid:
cuuid = UUID(hex=cuuid)
self._claimable[cuuid].claim(self._players[puuid], self._card)
fuuid = UUID(hex=fuuid) if fuuid else None
self._claimable[cuuid].claim(self._players[puuid], self._card, fuuid)
self.next_turn()
except BaseException as e:
print(e)