update game and display player's hand
This commit is contained in:
parent
8964165e78
commit
75d8cba654
4 changed files with 252 additions and 57 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,4 +1,5 @@
|
|||
node_modules/
|
||||
package-lock.json
|
||||
build/
|
||||
__pycache__
|
||||
__pycache__
|
||||
restart.sh
|
||||
|
|
@ -7,10 +7,12 @@ from game.game import *
|
|||
from game.error import *
|
||||
|
||||
app = Flask(__name__)
|
||||
import threading
|
||||
CORS(app)
|
||||
|
||||
tiles = Tile.generateAll()
|
||||
current_game = None # Stockage de la partie actuelle
|
||||
game_lock = threading.Lock()
|
||||
|
||||
# ============= GET ================
|
||||
@app.route('/api/tiles', methods=['GET'])
|
||||
|
|
@ -60,65 +62,129 @@ def get_random_hand():
|
|||
def get_hand_with_draw():
|
||||
"""Crée une partie et retourne le hand_player avec une tuile piochée"""
|
||||
global current_game
|
||||
current_game = Game()
|
||||
current_game.draw_tile(current_game.hand_player)
|
||||
|
||||
hand_data = [
|
||||
{
|
||||
'id': tile.id,
|
||||
'family': str(tile.family),
|
||||
'value': str(tile.value),
|
||||
'svg': tile.get_img()
|
||||
}
|
||||
for tile in current_game.hand_player.tiles
|
||||
]
|
||||
|
||||
draw_data = {
|
||||
'id': current_game.hand_player.draw.id,
|
||||
'family': str(current_game.hand_player.draw.family),
|
||||
'value': str(current_game.hand_player.draw.value),
|
||||
'svg': current_game.hand_player.draw.get_img()
|
||||
} if current_game.hand_player.draw else None
|
||||
|
||||
return jsonify({'hand': hand_data, 'draw': draw_data})
|
||||
with game_lock:
|
||||
current_game = Game()
|
||||
current_game.draw_tile(current_game.hand_player)
|
||||
hand_data = [
|
||||
{
|
||||
'id': tile.id,
|
||||
'family': str(tile.family),
|
||||
'value': str(tile.value),
|
||||
'svg': tile.get_img()
|
||||
}
|
||||
for tile in current_game.hand_player.tiles
|
||||
]
|
||||
draw_data = {
|
||||
'id': current_game.hand_player.draw.id,
|
||||
'family': str(current_game.hand_player.draw.family),
|
||||
'value': str(current_game.hand_player.draw.value),
|
||||
'svg': current_game.hand_player.draw.get_img()
|
||||
} if getattr(current_game.hand_player, 'draw', None) else None
|
||||
return jsonify({'hand': hand_data, 'draw': draw_data})
|
||||
|
||||
@app.route('/api/discard', methods=['POST'])
|
||||
def discard_tile():
|
||||
"""Défausse une tuile de la main du joueur et pioche une nouvelle"""
|
||||
global current_game
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
|
||||
data = request.json
|
||||
tile_id = data.get('tile_id')
|
||||
|
||||
if tile_id is None:
|
||||
return jsonify({'error': 'tile_id manquant'}), 400
|
||||
|
||||
current_game.put_tile(current_game.hand_player, tile_id)
|
||||
current_game.draw_tile(current_game.hand_player)
|
||||
|
||||
# Retourner la main mise à jour
|
||||
hand_data = [
|
||||
{
|
||||
'id': tile.id,
|
||||
'family': str(tile.family),
|
||||
'value': str(tile.value),
|
||||
'svg': tile.get_img()
|
||||
}
|
||||
for tile in current_game.hand_player.tiles
|
||||
]
|
||||
|
||||
draw_data = {
|
||||
'id': current_game.hand_player.draw.id,
|
||||
'family': str(current_game.hand_player.draw.family),
|
||||
'value': str(current_game.hand_player.draw.value),
|
||||
'svg': current_game.hand_player.draw.get_img()
|
||||
} if current_game.hand_player.draw else None
|
||||
|
||||
return jsonify({'hand': hand_data, 'draw': draw_data})
|
||||
with game_lock:
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
data = request.json
|
||||
tile_id = data.get('tile_id')
|
||||
if tile_id is None:
|
||||
return jsonify({'error': 'tile_id manquant'}), 400
|
||||
current_game.put_tile(current_game.hand_player, tile_id)
|
||||
current_game.draw_tile(current_game.hand_player)
|
||||
hand_data = [
|
||||
{
|
||||
'id': tile.id,
|
||||
'family': str(tile.family),
|
||||
'value': str(tile.value),
|
||||
'svg': tile.get_img()
|
||||
}
|
||||
for tile in current_game.hand_player.tiles
|
||||
]
|
||||
draw_data = {
|
||||
'id': current_game.hand_player.draw.id,
|
||||
'family': str(current_game.hand_player.draw.family),
|
||||
'value': str(current_game.hand_player.draw.value),
|
||||
'svg': current_game.hand_player.draw.get_img()
|
||||
} if getattr(current_game.hand_player, 'draw', None) else None
|
||||
return jsonify({'hand': hand_data, 'draw': draw_data})
|
||||
|
||||
# ============== POST ================
|
||||
# ============== GAME MANAGEMENT ================
|
||||
|
||||
# Démarrer une nouvelle partie
|
||||
@app.route('/api/game/start', methods=['POST'])
|
||||
def start_game():
|
||||
global current_game
|
||||
with game_lock:
|
||||
current_game = Game()
|
||||
return jsonify({'status': 'started', 'state': current_game.get_state()})
|
||||
|
||||
# Récupérer l'état de la partie
|
||||
@app.route('/api/game/state', methods=['GET'])
|
||||
def game_state():
|
||||
global current_game
|
||||
with game_lock:
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
return jsonify({'state': current_game.get_state()})
|
||||
|
||||
# Passer au tour suivant
|
||||
@app.route('/api/game/next_turn', methods=['POST'])
|
||||
def game_next_turn():
|
||||
global current_game
|
||||
with game_lock:
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
current_game.next_turn()
|
||||
return jsonify({'state': current_game.get_state()})
|
||||
|
||||
# Déclarer Riichi
|
||||
@app.route('/api/game/riichi', methods=['POST'])
|
||||
def game_declare_riichi():
|
||||
global current_game
|
||||
with game_lock:
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
data = request.json
|
||||
player_id = data.get('player_id')
|
||||
if player_id is None:
|
||||
return jsonify({'error': 'player_id manquant'}), 400
|
||||
current_game.declare_riichi(player_id)
|
||||
return jsonify({'state': current_game.get_state()})
|
||||
|
||||
# Récupérer la main d'un joueur
|
||||
@app.route('/api/game/hand/<int:player_id>', methods=['GET'])
|
||||
def game_get_hand(player_id):
|
||||
global current_game
|
||||
with game_lock:
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
hand = current_game.get_hand(player_id)
|
||||
return jsonify({'hand': hand})
|
||||
|
||||
# Récupérer les défausses d'un joueur
|
||||
@app.route('/api/game/discards/<int:player_id>', methods=['GET'])
|
||||
def game_get_discards(player_id):
|
||||
global current_game
|
||||
with game_lock:
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
discards = current_game.get_discards(player_id)
|
||||
return jsonify({'discards': discards})
|
||||
|
||||
# Récupérer les actions possibles pour un joueur
|
||||
@app.route('/api/game/actions/<int:player_id>', methods=['GET'])
|
||||
def game_get_actions(player_id):
|
||||
global current_game
|
||||
with game_lock:
|
||||
if current_game is None:
|
||||
return jsonify({'error': 'Aucune partie en cours'}), 400
|
||||
actions = current_game.get_possible_actions(player_id)
|
||||
return jsonify({'actions': actions})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, port=5000)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,57 @@ from .wall import *
|
|||
import random as rd
|
||||
|
||||
class Game:
|
||||
def __init__(self):
|
||||
def __init__(self, wind=0 , yakus=False, red=False):
|
||||
self.wall = Wall()
|
||||
|
||||
self.hand_player = self.wall.draw_hand()
|
||||
self.bot_hands = [self.wall.draw_hand() for _ in range(3)]
|
||||
self.discard_player = []
|
||||
self.hidden_discard_player = []
|
||||
self.hands_bots = [self.wall.draw_hand() for _ in range(3)]
|
||||
self.discards_bots = [[] for _ in range(3)]
|
||||
self.hidden_discards_bots = [[] for _ in range(3)]
|
||||
|
||||
self.scores = [25000] * 4
|
||||
|
||||
self.winds = [
|
||||
wind % 4, # player
|
||||
(wind+1) % 4, # right of player
|
||||
(wind + 2) % 4, # front of player
|
||||
(wind +3) % 4 # left of player
|
||||
]
|
||||
|
||||
self.initial_est = (-wind) % 4
|
||||
self.turn = self.winds.index(0)
|
||||
|
||||
self.riichi = [False] * 4
|
||||
self.repeat = 0
|
||||
|
||||
self.end = False
|
||||
|
||||
def new_turn(self, repeat=False):
|
||||
if repeat:
|
||||
self.repeat += 1
|
||||
else:
|
||||
self.repeat = 0
|
||||
self.turn = (self.turn + 1) % 4
|
||||
if self.turn == self.initial_est:
|
||||
self.end = True
|
||||
for i in range(4):
|
||||
self.winds[self.turn + i] = i
|
||||
|
||||
self.turn = self.winds.index(0)
|
||||
|
||||
self.riichi = [False] * 4
|
||||
self.repeat = 0
|
||||
|
||||
self.wall = Wall()
|
||||
|
||||
self.hand_player = self.wall.draw_hand()
|
||||
self.discard_player = []
|
||||
self.hidden_discard_player = []
|
||||
self.hands_bots = [self.wall.draw_hand() for _ in range(3)]
|
||||
self.discards_bots = [[] for _ in range(3)]
|
||||
self.hidden_discards_bots = [[] for _ in range(3)]
|
||||
|
||||
def draw_tile(self, hand: Hand):
|
||||
tile = self.wall.draw()
|
||||
|
|
@ -17,4 +63,47 @@ class Game:
|
|||
|
||||
def put_tile(self, hand: Hand, id: int):
|
||||
self.wall.tiles.append(hand.discard_tile(id))
|
||||
self.wall.shuffle()
|
||||
self.wall.shuffle()
|
||||
|
||||
def next_turn(self):
|
||||
"""Passe au tour suivant."""
|
||||
pass
|
||||
|
||||
def get_state(self):
|
||||
"""Retourne l'état actuel de la partie (joueurs, scores, main, etc.)."""
|
||||
hand_tiles = list(getattr(self.hand_player, 'tiles', []))
|
||||
if getattr(self.hand_player, 'draw', None) is not None:
|
||||
hand_tiles = hand_tiles + [self.hand_player.draw]
|
||||
return {
|
||||
'scores': list(self.scores),
|
||||
'winds': list(self.winds),
|
||||
'turn': int(self.turn),
|
||||
'riichi': list(self.riichi),
|
||||
'repeat': int(self.repeat),
|
||||
'end': bool(self.end),
|
||||
'hand_player': [
|
||||
{
|
||||
'id': tile.id,
|
||||
'family': str(tile.family),
|
||||
'value': str(tile.value),
|
||||
'svg': tile.get_img()
|
||||
}
|
||||
for tile in hand_tiles
|
||||
]
|
||||
}
|
||||
|
||||
def declare_riichi(self, player_id):
|
||||
"""Déclare Riichi pour un joueur."""
|
||||
pass
|
||||
|
||||
def get_hand(self, player_id):
|
||||
"""Retourne la main d'un joueur."""
|
||||
pass
|
||||
|
||||
def get_discards(self, player_id):
|
||||
"""Retourne les tuiles défaussées d'un joueur."""
|
||||
pass
|
||||
|
||||
def get_possible_actions(self, player_id):
|
||||
"""Retourne les actions possibles pour un joueur."""
|
||||
pass
|
||||
|
|
@ -39,6 +39,22 @@
|
|||
.speech-bubble.visible {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
[id^="hand"] {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#tiles-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -48,7 +64,9 @@
|
|||
<div class="speech-text" id="speech-text"></div>
|
||||
</div>
|
||||
<div id="mascotte"></div>
|
||||
|
||||
|
||||
<div id="hand-0"></div>
|
||||
|
||||
<script src="/frontend/js/fr/texts.js"></script>
|
||||
<script>
|
||||
// Charger le menu
|
||||
|
|
@ -69,6 +87,27 @@
|
|||
? '<img class="explaining" src="/img/tilineau/explaining.png" alt="Tilineau">'
|
||||
: '<img src="/img/tilineau/idle.png" alt="Tilineau">';
|
||||
});
|
||||
|
||||
// Initialiser une partie au chargement du chapitre 5
|
||||
fetch('/api/game/start', { method: 'POST' })
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
console.log('Réponse API', data);
|
||||
if (data.state && data.state.hand_player) {
|
||||
displayHand(data.state.hand_player, 'hand-0');
|
||||
}
|
||||
})
|
||||
.catch(e => console.error('Erreur initialisation partie', e));
|
||||
|
||||
function displayHand(hand, displayId) {
|
||||
const display = document.getElementById(displayId);
|
||||
display.innerHTML = '';
|
||||
hand.forEach(tile => {
|
||||
const tileDiv = document.createElement('div');
|
||||
tileDiv.innerHTML = tile.svg;
|
||||
display.appendChild(tileDiv);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue