Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
84278a111c | |||
f23319b7b8 | |||
b574014c95 | |||
7271267952 | |||
7ebff627eb | |||
bd35267bd3 | |||
965b7a5ad7 | |||
c194164e3c | |||
342fa0cca3 | |||
bcfc488c2e | |||
abccd2e51a | |||
1b9ccc65ab | |||
ebf7878397 | |||
c4746d2306 | |||
62f252130e | |||
1145fc7fa0 | |||
7191a778be | |||
90056d05e9 | |||
2092c52edb | |||
89d11ee759 | |||
4037822446 | |||
a1710cba4a | |||
644c28ae75 | |||
688641d749 | |||
c6def1169f | |||
0321296014 |
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "js-cardgame"]
|
||||
path = js-cardgame
|
||||
url = git@github.com:strupppi/js-cardgame.git
|
BIN
deck/b01.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/b02.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/b03.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/b04.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/b05.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/b06.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/b07.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/b08.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/b09.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/b10.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
deck/b11.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/b12.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/b13.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/back1.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
deck/g01.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
deck/g02.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/g03.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/g04.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/g05.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
deck/g06.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/g07.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/g08.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/g09.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/g10.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/g11.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/g12.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/g13.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/mask.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
deck/n1.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/n2.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/n3.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/n4.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
deck/r01.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/r02.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/r03.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/r04.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/r05.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/r06.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/r07.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
deck/r08.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/r09.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/r10.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/r11.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
deck/r12.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
deck/r13.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
deck/y01.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/y02.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/y03.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/y04.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/y05.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/y06.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/y07.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/y08.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
deck/y09.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/y10.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
deck/y11.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
deck/y12.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
deck/y13.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
deck/z1.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
deck/z2.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
deck/z3.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
deck/z4.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
1
js-cardgame
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4d88b9198cb335414600aab691bbe1ae5edb590c
|
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
starlette~=0.12.13
|
||||
responder~=2.0.5
|
@ -1,14 +1,17 @@
|
||||
# noinspection PyUnresolvedReferences
|
||||
from app_instance import api
|
||||
# noinspection PyUnresolvedReferences
|
||||
from views.api_views import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from views.home import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from views.temp_css import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from views.player import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from views.gplayer import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from views.js_cardgame import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from views.control import *
|
||||
|
||||
api.add_route("/static", static=True)
|
||||
api.add_route("/js", static=True)
|
||||
|
12
server.py
@ -1,21 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import random
|
||||
import socket
|
||||
import responder
|
||||
from app_instance import api
|
||||
from routes import *
|
||||
import wiz_game
|
||||
import argparse
|
||||
|
||||
|
||||
def main():
|
||||
print("main started")
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--port', metavar='port', default=8001, type=int, help='the port to bind to')
|
||||
parser.add_argument('--bindaddr', metavar='addr', default='127.0.0.1', help='the address to bind to')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
random.seed()
|
||||
wiz_game.the_game.start_game()
|
||||
|
||||
#api.run(port=8001, address="127.0.0.1")
|
||||
api.run(port=8001, address="192.168.42.1")
|
||||
api.run(port=args.port, address=args.bindaddr)
|
||||
exit(0)
|
||||
|
||||
|
||||
|
@ -22,10 +22,12 @@
|
||||
Winner: {{trick_winner}} with Card {{highest_card}}
|
||||
<a href="/control/next_trick/">start next trick</a>
|
||||
{% endif %}
|
||||
{% if hand_finished %}
|
||||
{% if round_finished %}
|
||||
Winner: {{trick_winner}} with Card {{highest_card}}
|
||||
<a href="/control/next_hand/">start next hand</a>
|
||||
<a href="/control/next_round/">start next round</a>
|
||||
{% endif %}
|
||||
<br>
|
||||
<a href="/control/undo_last/">undo last card</a>
|
||||
<!--
|
||||
<ul>
|
||||
<li>
|
||||
|
206
templates/home/gplayer.html
Normal file
@ -0,0 +1,206 @@
|
||||
{% extends "/shared/_layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<script>
|
||||
function playCard(card) {
|
||||
let player = "{{player}}";
|
||||
let c = card.toString();
|
||||
var msg = {
|
||||
type: "message",
|
||||
fct: "playcard",
|
||||
player: player,
|
||||
card: c
|
||||
};
|
||||
let t = JSON.stringify(msg);
|
||||
window.game_socket.send(t);
|
||||
}
|
||||
|
||||
function setTrumpColor(color) {
|
||||
let player = "{{player}}"
|
||||
var msg = {
|
||||
type: "message",
|
||||
fct: "setTrumpColor",
|
||||
player: player,
|
||||
color: color
|
||||
};
|
||||
let t = JSON.stringify(msg);
|
||||
window.game_socket.send(t);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div style="font-family:Wizzta; font-size:100px"></div>
|
||||
<div class="content">
|
||||
<script src="/js-cardgame/pixi.min.js"></script>
|
||||
<script src="/js-cardgame/js/card.js"></script>
|
||||
<script src="/js-cardgame/js/carddeck.js"></script>
|
||||
<script src="/js-cardgame/js/player.js"></script>
|
||||
<script src="/js-cardgame/js/game.js"></script>
|
||||
|
||||
<script>
|
||||
//let game = null;
|
||||
//window.game = null;
|
||||
|
||||
//window.onload = function()
|
||||
function setupGame(names, hand)
|
||||
{
|
||||
|
||||
PIXI.AbstractRenderer.autoDensity = true;
|
||||
let app = new PIXI.Application();
|
||||
app.renderer.view.style.position = "absolute";
|
||||
app.renderer.view.style.display = "block";
|
||||
|
||||
function resize()
|
||||
{
|
||||
let width = 1920;
|
||||
let height = 1080;
|
||||
let w = window.innerWidth;
|
||||
let h = window.innerHeight;
|
||||
let scale = Math.min(w/width, h/height)
|
||||
app.stage.scale.x = scale;
|
||||
app.stage.scale.y = scale;
|
||||
app.renderer.resize(w, h);
|
||||
}
|
||||
|
||||
function addResources(loader)
|
||||
{
|
||||
loader.add("mask", "/js-cardgame/deck/mask.png");
|
||||
loader.add("back", "/js-cardgame/deck/back1.jpg");
|
||||
for (let i = 0; i < 14; i++) {
|
||||
["r", "g", "b", "y"].forEach(function (c) {
|
||||
let name = c + ((i < 10) ? "0" + i : i);
|
||||
loader.add(name, "/js-cardgame/deck/" + name + ".jpg");
|
||||
});
|
||||
}
|
||||
for (let i = 1; i < 5; i++) {
|
||||
loader.add("z" + i, "/js-cardgame/deck/z" + i + ".jpg");
|
||||
loader.add("n" + i, "/js-cardgame/deck/n" + i + ".jpg");
|
||||
}
|
||||
}
|
||||
|
||||
resize();
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
app.renderer.backgroundColor = 0x222222;
|
||||
document.body.appendChild(app.view);
|
||||
|
||||
let loader = PIXI.Loader.shared;
|
||||
addResources(loader);
|
||||
loader.load(function(loader, resources)
|
||||
{
|
||||
game = new Game(app.stage, resources);
|
||||
//game.init(['Hubert', 'Struppi', 'Patrice', 'Steffi', "Max", "Renate"]);
|
||||
game.init(names)
|
||||
game.give_round(hand)
|
||||
//game.give_round(["z3", "b04", "r08", "g12", "y13", "r02", "b05", "b02", "b03", "g03", "g05"]);
|
||||
//game.play_card(0, 0, "z3");
|
||||
//game.play_card(1, 0, "y13");
|
||||
//game.play_card(2, 0, "b02");
|
||||
//game.play_card(3, 0, "r02");
|
||||
//game.play_card(4, 0, "y05");
|
||||
//game.play_card(5, 0, "g05");
|
||||
//game.give_trick_to(0);
|
||||
window.the_game = game;
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- <div class="content">
|
||||
<h1><span class="font-semi-bold">Gambling Foo</span> <span class="smaller">A RESTful gaming service</span></h1>
|
||||
<p class="lead">
|
||||
Play a nice game of cards?<br>
|
||||
<br>
|
||||
<strong>Player {{player+1}} view</strong><br>
|
||||
<strong> Table </strong><br>
|
||||
{% for player,card in played_cards %}
|
||||
||
|
||||
{{player.name}}: {{card}}
|
||||
{% endfor %}
|
||||
||
|
||||
<br>
|
||||
<sub>
|
||||
<strong>Tricks:</strong>
|
||||
{% for player,_ in last_trick %}
|
||||
||
|
||||
{{player.name}}: {{player.tricks_taken}}
|
||||
{% endfor %}
|
||||
||
|
||||
<br>
|
||||
<strong>Last Trick:</strong>
|
||||
{% for player,card in last_trick %}
|
||||
||
|
||||
{{player.name}}: {{card}}
|
||||
{% endfor %}
|
||||
||
|
||||
</sub>
|
||||
<br>
|
||||
<strong> Your cards: </strong>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Trump Card: {{trump_card}}</strong><br>
|
||||
<strong>Trump Color: {{trump_color}}</strong><br>
|
||||
</li>
|
||||
|
||||
{% for card in cards %}
|
||||
<li>
|
||||
<strong>>card {{loop.index}} is: {{card}} </strong><br>
|
||||
{% if playerActive and not choose_trump_color %}
|
||||
<!–
|
||||
<a href="/player/{{player}}/play/{{loop.index0}}">play card {{loop.index}}<{{card}}></a>
|
||||
<div style="background-color:#D94A38;width:170px;height:80px;margin:20px;padding-top:20px;color:#ffffff;font-weight:bold;font-size:18px;float:left;text-align:center;" onclick="playCard({{loop.index0}})">Play Me</div>
|
||||
–>
|
||||
<button onclick="playCard({{loop.index0}})">Play {{card}}</button>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if choose_trump_color and (player == choose_trump_player) %}
|
||||
<strong>Choose Trump Color:</strong>
|
||||
<!–
|
||||
<a href="/player/{{player}}/set_trump/r">Red></a>
|
||||
<a href="/player/{{player}}/set_trump/g">Green></a>
|
||||
<a href="/player/{{player}}/set_trump/b">Blue></a>
|
||||
<a href="/player/{{player}}/set_trump/y">Yellow ></a>
|
||||
–>
|
||||
<button onclick="setTrumpColor('r')">Red</button>
|
||||
<button onclick="setTrumpColor('g')">Green</button>
|
||||
<button onclick="setTrumpColor('b')">Blue</button>
|
||||
<button onclick="setTrumpColor('y')">Yellow</button>
|
||||
{% endif %}
|
||||
<!–
|
||||
<li>
|
||||
<strong>Movie by IMDB code</strong><br>
|
||||
<a href="/api/movie/tt0096754">GET /api/movie/{imdb_number}</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Top 10 Movies (by IMDB score)</strong><br>
|
||||
<a href="/api/movie/top">GET /api/movie/top</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong>All genres</strong><br>
|
||||
<a href="/api/movie/genre/all">GET /api/movie/genre/all</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Top movies for a given genres</strong><br>
|
||||
<a href="/api/movie/genre/sci-fi">GET /api/movie/genre/{genre}</a>
|
||||
</li>
|
||||
–>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p class="disclaimer">
|
||||
Spam Bacon Sausage + Spam
|
||||
Spam Spam Spam Spam Spam
|
||||
Spam Baked Beans Spam
|
||||
Spam Spam + Spam
|
||||
|
||||
</p>
|
||||
</div>-->
|
||||
|
||||
|
||||
{% endblock %}
|
@ -2,6 +2,26 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<script>
|
||||
|
||||
function setTrumpColor(color) {
|
||||
let player = "{{player}}"
|
||||
var msg = {
|
||||
type: "message",
|
||||
fct: "setTrumpColor",
|
||||
player: player,
|
||||
color: color
|
||||
};
|
||||
let t = JSON.stringify(msg);
|
||||
window.game_socket.send(t);
|
||||
}
|
||||
|
||||
function setupGame(player_names) {
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="content">
|
||||
<h1><span class="font-semi-bold">Gambling Foo</span> <span class="smaller">A RESTful gaming service</span></h1>
|
||||
<p class="lead">
|
||||
@ -42,16 +62,26 @@
|
||||
<li>
|
||||
<strong>>card {{loop.index}} is: {{card}} </strong><br>
|
||||
{% if playerActive and not choose_trump_color %}
|
||||
<!--
|
||||
<a href="/player/{{player}}/play/{{loop.index0}}">play card {{loop.index}}<{{card}}></a>
|
||||
<div style="background-color:#D94A38;width:170px;height:80px;margin:20px;padding-top:20px;color:#ffffff;font-weight:bold;font-size:18px;float:left;text-align:center;" onclick="playCard({{loop.index0}})">Play Me</div>
|
||||
-->
|
||||
<button onclick="playCard({{loop.index0}})">Play {{card}}</button>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if choose_trump_color and (player == choose_trump_player) %}
|
||||
<strong>Choose Trump Color:</strong>
|
||||
<!--
|
||||
<a href="/player/{{player}}/set_trump/r">Red></a>
|
||||
<a href="/player/{{player}}/set_trump/g">Green></a>
|
||||
<a href="/player/{{player}}/set_trump/b">Blue></a>
|
||||
<a href="/player/{{player}}/set_trump/y">Yellow ></a>
|
||||
-->
|
||||
<button onclick="setTrumpColor('r')">Red</button>
|
||||
<button onclick="setTrumpColor('g')">Green</button>
|
||||
<button onclick="setTrumpColor('b')">Blue</button>
|
||||
<button onclick="setTrumpColor('y')">Yellow</button>
|
||||
{% endif %}
|
||||
<!--
|
||||
<li>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<meta name="description" content="pyramid web application">
|
||||
<meta name="author" content="Pylons Project">
|
||||
|
||||
<title>Free Online Gamblingc</title>
|
||||
<title>Free Online Gambling</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
|
||||
@ -22,33 +22,113 @@
|
||||
<script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
<script>
|
||||
let socket = new WebSocket("wss://cowiz.struppi.name/ws");
|
||||
window.the_game = null
|
||||
// let socket = new WebSocket("wss://cowiz.struppi.name/ws");
|
||||
if (window.location.hostname == '127.0.0.1') {
|
||||
ws_schema = 'ws://';
|
||||
}
|
||||
else {
|
||||
ws_schema = 'wss://';
|
||||
}
|
||||
let socket = new WebSocket(ws_schema+window.location.host+'/ws');
|
||||
window.game_socket = socket
|
||||
|
||||
socket.onopen = function(e) {
|
||||
//alert("[open] Connection established");
|
||||
//alert("Sending to server");
|
||||
//socket.send("My name is John");
|
||||
let player = "{{player}}"
|
||||
var msg = {
|
||||
//type: "message",
|
||||
//fct: "requestInit",
|
||||
type: "message",
|
||||
fct: "getHand",
|
||||
player: player,
|
||||
};
|
||||
let t = JSON.stringify(msg);
|
||||
window.game_socket.send(t);
|
||||
};
|
||||
|
||||
socket.onmessage = function(event) {
|
||||
//alert(`[message] Data received from server: ${event.data}`);
|
||||
location.reload(true)
|
||||
let msg = JSON.parse(event.data);
|
||||
let fct = msg.fct;
|
||||
if (fct == "reload") {
|
||||
location.reload(true);
|
||||
}
|
||||
else if (fct == "getHand") {
|
||||
window.hand = msg.cards;
|
||||
let player = "{{player}}";
|
||||
var msg_out = {
|
||||
type: "message",
|
||||
fct: "requestInit",
|
||||
player: player,
|
||||
};
|
||||
let t = JSON.stringify(msg_out);
|
||||
window.game_socket.send(t);
|
||||
}
|
||||
else if (fct == "startGame") {
|
||||
let names = msg.names
|
||||
setupGame(names, window.hand)
|
||||
//alert('game is set up')
|
||||
}
|
||||
else if (fct == "cardPlayed") {
|
||||
let player_id = msg.player;
|
||||
let card_idx = msg.card_idx;
|
||||
let card = msg.card;
|
||||
let num_players = msg.num_players;
|
||||
cardPlayed(player_id, card_idx, card, num_players)
|
||||
}
|
||||
else {
|
||||
alert('unknown command: '+event.data);
|
||||
}
|
||||
};
|
||||
|
||||
socket.onclose = function(event) {
|
||||
if (event.wasClean) {
|
||||
//alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
|
||||
alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
|
||||
//alert('closed clean');
|
||||
} else {
|
||||
// e.g. server process killed or network down
|
||||
// event.code is usually 1006 in this case
|
||||
//alert('[close] Connection died');
|
||||
//alert('closed unclean');
|
||||
}
|
||||
};
|
||||
|
||||
socket.onerror = function(error) {
|
||||
alert(`[error] ${error.message}`);
|
||||
alert("[error]: "+error.message);
|
||||
};
|
||||
|
||||
|
||||
function playCard(card) {
|
||||
let player = "{{player}}";
|
||||
let c = card.toString();
|
||||
var msg = {
|
||||
type: "message",
|
||||
fct: "playcard",
|
||||
player: player,
|
||||
card: c
|
||||
};
|
||||
let t = JSON.stringify(msg);
|
||||
window.game_socket.send(t);
|
||||
}
|
||||
|
||||
function cardPlayed(player, card_idx, card, num_players) {
|
||||
let myself = "{{player}}";
|
||||
let player_idx = ((player + num_players) - myself) % num_players;
|
||||
window.the_game.play_card(player_idx, card_idx, card)
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {padding: 0; margin: 0}
|
||||
@font-face {
|
||||
font-family: "Wizzta";
|
||||
src: url("/js-cardgame/font/wizzta-vada-webfont.woff2") format("woff2"),
|
||||
url("/js-cardgame/font/wizzta-vada-webfont.woff") format("woff");
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -88,7 +168,7 @@
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
|
||||
<!-- <script src="https://oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script> -->
|
||||
<script src="/js-cardgame/jquery-3.5.1.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,39 +0,0 @@
|
||||
from responder import Response
|
||||
|
||||
from app_instance import api
|
||||
|
||||
response_count_max = 10
|
||||
|
||||
|
||||
@api.route("/api/search/{keyword}")
|
||||
def search_keyword(req, resp, keyword: str):
|
||||
resp.media = {'keyword': keyword, 'hits': "movie_dicts", 'truncated_results': "limited"}
|
||||
|
||||
|
||||
@api.route("/api/director/{director_name}")
|
||||
def search_director(_, resp, director_name: str):
|
||||
resp.media = {'keyword': director_name, 'hits': "movies_dicts", 'truncated_results': "limited"}
|
||||
|
||||
|
||||
@api.route("/api/movie/genre/{genre}")
|
||||
def movies_by_genre(_, resp: Response, genre: str):
|
||||
resp.media = {'genre': genre, 'hits': "hits_dicts", 'truncated_results': "limited"}
|
||||
|
||||
|
||||
@api.route("/api/movie/{imdb_number}")
|
||||
def search_imdb(_, resp, imdb_number: str):
|
||||
resp.media = {'foo': "bar"}
|
||||
|
||||
|
||||
@api.route("/api/movie/top")
|
||||
def top_movies(_, resp: Response):
|
||||
resp.media = {'keyword': "keyword", 'hits': "hits_dicts", 'truncated_results': "limited"}
|
||||
|
||||
|
||||
@api.route("/api/movie/genre/all")
|
||||
def all_genres(_, resp: Response):
|
||||
resp.media = {"all": "stuff"}
|
||||
|
||||
@api.route("/api/shuffle")
|
||||
def cards_shuffle(_, resp: Response):
|
||||
resp.media = {"shuffled": "done"}
|
@ -5,16 +5,15 @@ from wiz_game import the_game
|
||||
|
||||
@api.route("/control/")
|
||||
def index(req, resp):
|
||||
current_round = the_game.current_round
|
||||
hand_finished = the_game.is_hand_finished()
|
||||
round_finished = the_game.is_round_finished()
|
||||
trick_finished = the_game.is_trick_finished()
|
||||
|
||||
if hand_finished:
|
||||
if round_finished:
|
||||
trick_winner, highest_card = the_game.get_trick_winner()
|
||||
winner = trick_winner.name
|
||||
resp.content = api.template('home/control.html', deck=the_game.card_deck,
|
||||
trump_card=the_game.trump_card, trump_color=the_game.get_trump_color(),
|
||||
hand_finished=True, trick_finished=False, trick_winner=winner,
|
||||
round_finished=True, trick_finished=False, trick_winner=winner,
|
||||
highest_card=highest_card
|
||||
)
|
||||
elif trick_finished:
|
||||
@ -31,28 +30,40 @@ def index(req, resp):
|
||||
round_finished=False, trick_finished=False
|
||||
)
|
||||
|
||||
@api.route("/control/next_hand/")
|
||||
async def start_next_hand(req, resp):
|
||||
the_game.next_hand()
|
||||
for ws in the_game.websockets:
|
||||
try:
|
||||
await ws.send_text("reload")
|
||||
except Exception as e:
|
||||
print("ws: got {}".format(e))
|
||||
@api.route("/control/next_round/")
|
||||
async def start_next_round(req, resp):
|
||||
the_game.next_round()
|
||||
await the_game.send_page_reload()
|
||||
api.redirect(resp, '/control/', status_code=303)
|
||||
|
||||
|
||||
@api.route("/control/next_trick/")
|
||||
async def start_next_trick(req, resp):
|
||||
the_game.next_trick()
|
||||
for ws in the_game.websockets:
|
||||
try:
|
||||
await ws.send_text("reload")
|
||||
except Exception as e:
|
||||
print("ws: got {}".format(e))
|
||||
await the_game.send_page_reload()
|
||||
api.redirect(resp, '/control/', status_code=303)
|
||||
|
||||
|
||||
@api.route("/control/undo_last/")
|
||||
async def undo_last(req, resp):
|
||||
round_finished = the_game.is_round_finished()
|
||||
if the_game.played_cards:
|
||||
if not round_finished:
|
||||
p, c = the_game.played_cards.pop()
|
||||
the_game.active_player -= 1
|
||||
p.add_card(c)
|
||||
await the_game.send_page_reload()
|
||||
else:
|
||||
if the_game.num_tricks_played > 0:
|
||||
the_game.num_tricks_played -= 1;
|
||||
the_game.played_cards = the_game.last_trick;
|
||||
the_game.active_player = len(the_game.players) - 1
|
||||
player, _ = the_game.get_trick_winner()
|
||||
player.tricks_taken -= 1
|
||||
the_game.players_ordered = [p for p, _ in the_game.played_cards]
|
||||
p, c = the_game.played_cards.pop()
|
||||
p.add_card(c)
|
||||
await the_game.send_page_reload()
|
||||
|
||||
api.redirect(resp, '/control/', status_code=303)
|
||||
|
||||
#@api.route("/control/deal/{cards}")
|
||||
#def deal(req, resp, cards):
|
||||
# the_game.deal_cards(int(cards))
|
||||
# api.redirect(resp, '/control/', status_code=303)
|
||||
|
29
views/gplayer.py
Normal file
@ -0,0 +1,29 @@
|
||||
from app_instance import api
|
||||
from wiz_game import the_game
|
||||
from starlette.websockets import WebSocketDisconnect
|
||||
import asyncio
|
||||
|
||||
|
||||
# don't define here, it's defined elsewhere!
|
||||
#playing_lock = asyncio.Lock()
|
||||
|
||||
|
||||
@api.route("/gplayer/{player}")
|
||||
def show(req, resp, player: str):
|
||||
p = int(player)
|
||||
tcard = the_game.trump_card
|
||||
tcolor = the_game.get_trump_color()
|
||||
try:
|
||||
isActive = the_game.players_ordered[the_game.active_player].id == p
|
||||
except IndexError:
|
||||
isActive = False
|
||||
|
||||
prev_player = the_game.get_prev_player()
|
||||
if tcard and tcard.value == 'Z' and tcolor == '-':
|
||||
choose_trump_color = True
|
||||
else:
|
||||
choose_trump_color = False
|
||||
resp.content = api.template('home/gplayer.html', player=p, playerActive=isActive, choose_trump_player=prev_player,
|
||||
cards=the_game.players[p].cards, choose_trump_color=choose_trump_color,
|
||||
trump_card=tcard, trump_color=tcolor, played_cards=the_game.played_cards, last_trick=the_game.last_trick)
|
||||
|
56
views/js_cardgame.py
Normal file
@ -0,0 +1,56 @@
|
||||
import os
|
||||
|
||||
from app_instance import api
|
||||
|
||||
|
||||
@api.route("/js-cardgame/{file}")
|
||||
def css(req, resp, file):
|
||||
resp.headers['Content-Type'] = 'application/javascript'
|
||||
full_file = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'..',
|
||||
'js-cardgame',
|
||||
file
|
||||
)
|
||||
with open(full_file, encoding='utf-8') as fin:
|
||||
resp.content = fin.read()
|
||||
|
||||
@api.route("/js-cardgame/deck/{file}")
|
||||
def css(req, resp, file):
|
||||
resp.headers['Content-Type'] = 'image/jpeg'
|
||||
full_file = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'..',
|
||||
'deck/',
|
||||
file
|
||||
)
|
||||
with open(full_file, 'rb') as fin:
|
||||
resp.content = fin.read()
|
||||
|
||||
|
||||
@api.route("/js-cardgame/font/{file}")
|
||||
def css(req, resp, file):
|
||||
resp.headers['Content-Type'] = 'application/octet-stream'
|
||||
full_file = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'..',
|
||||
'js-cardgame',
|
||||
file
|
||||
)
|
||||
with open(full_file, 'rb') as fin:
|
||||
resp.content = fin.read()
|
||||
|
||||
|
||||
|
||||
@api.route("/js-cardgame/js/{file}")
|
||||
def css(req, resp, file):
|
||||
resp.headers['Content-Type'] = 'application/javascript'
|
||||
full_file = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'..',
|
||||
'js-cardgame',
|
||||
'js',
|
||||
file
|
||||
)
|
||||
with open(full_file, encoding='utf-8') as fin:
|
||||
resp.content = fin.read()
|
139
views/player.py
@ -3,22 +3,22 @@ from app_instance import api
|
||||
from wiz_game import the_game
|
||||
from starlette.websockets import WebSocketDisconnect
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
|
||||
playing_lock = asyncio.Lock()
|
||||
|
||||
|
||||
@api.route("/player/{player}")
|
||||
def show(req, resp, player: str):
|
||||
p = int(player)
|
||||
name = the_game.players[p].name
|
||||
tcard = the_game.trump_card
|
||||
tcolor = the_game.get_trump_color()
|
||||
#isActive = the_game.is_players_turn(p)
|
||||
try:
|
||||
isActive = the_game.players_ordered[the_game.active_player].id == p
|
||||
print("show p: {} | {}".format(the_game.players_ordered[the_game.active_player].id, p))
|
||||
except IndexError:
|
||||
isActive = False
|
||||
print("show p: {} | {}".format('None', p))
|
||||
|
||||
#active_player = the_game.active_player
|
||||
prev_player = the_game.get_prev_player()
|
||||
if tcard and tcard.value == 'Z' and tcolor == '-':
|
||||
choose_trump_color = True
|
||||
@ -29,58 +29,125 @@ def show(req, resp, player: str):
|
||||
trump_card=tcard, trump_color=tcolor, played_cards=the_game.played_cards, last_trick=the_game.last_trick)
|
||||
|
||||
|
||||
@api.route("/player/{player}/play/{card}")
|
||||
async def play(req, resp, player: str, card: str):
|
||||
lock = asyncio.Lock()
|
||||
p = int(player)
|
||||
c = int(card)
|
||||
|
||||
async with lock:
|
||||
async def play_card(player, card):
|
||||
global playing_lock
|
||||
async with playing_lock:
|
||||
try:
|
||||
isActive = the_game.players_ordered[the_game.active_player].id == p
|
||||
isActive = the_game.players_ordered[the_game.active_player].id == player
|
||||
except IndexError:
|
||||
isActive = False
|
||||
print("show p: {} | {}".format('None', p))
|
||||
if isActive:
|
||||
the_game.play_card(p, c)
|
||||
if the_game.is_hand_finished():
|
||||
print("hand finished")
|
||||
the_game.play_card(player, card)
|
||||
if the_game.is_round_finished():
|
||||
trick_winner, highest_card = the_game.get_trick_winner()
|
||||
trick_winner.take_trick()
|
||||
elif the_game.is_trick_finished():
|
||||
trick_winner, highest_card = the_game.get_trick_winner()
|
||||
trick_winner.take_trick()
|
||||
the_game.next_trick()
|
||||
await the_game.send_page_reload()
|
||||
|
||||
|
||||
async def play_card_js(player_id, card_idx):
|
||||
global playing_lock
|
||||
async with playing_lock:
|
||||
try:
|
||||
isActive = the_game.players_ordered[the_game.active_player].id == player_id
|
||||
except IndexError:
|
||||
isActive = False
|
||||
if isActive:
|
||||
card = the_game.play_card(player_id, card_idx)
|
||||
|
||||
if the_game.is_round_finished():
|
||||
trick_winner, highest_card = the_game.get_trick_winner()
|
||||
trick_winner.take_trick()
|
||||
#the_game.next_hand()
|
||||
elif the_game.is_trick_finished():
|
||||
print("trick finished")
|
||||
trick_winner, highest_card = the_game.get_trick_winner()
|
||||
trick_winner.take_trick()
|
||||
the_game.next_trick()
|
||||
|
||||
s = card.json_serialise()
|
||||
msg = {"type": "message", "fct": "cardPlayed", "card": s, "card_idx": card_idx,
|
||||
"player": player_id, "num_players": len(the_game.players)}
|
||||
for ws in the_game.websockets:
|
||||
try:
|
||||
await ws.send_json(msg)
|
||||
except Exception:
|
||||
the_game.websockets.remove(ws)
|
||||
|
||||
|
||||
@api.route("/player/{player}/play/{card}")
|
||||
async def play(req, resp, player: str, card: str):
|
||||
p = int(player)
|
||||
c = int(card)
|
||||
play_card(p, c)
|
||||
url = '/player/'+player
|
||||
for ws in the_game.websockets:
|
||||
try:
|
||||
await ws.send_text("reload")
|
||||
except Exception as e:
|
||||
print("ws: got {}".format(e))
|
||||
api.redirect(resp, url, status_code=303)
|
||||
|
||||
|
||||
@api.route("/player/{player}/set_trump/{trump}")
|
||||
async def set_trump_color(req, resp, player, trump):
|
||||
async def set_trump_color_rest(req, resp, player, trump):
|
||||
p = int(player)
|
||||
the_game.set_trump_color(trump)
|
||||
url = '/player/'+player
|
||||
for ws in the_game.websockets:
|
||||
try:
|
||||
await ws.send_text("reload")
|
||||
except Exception as e:
|
||||
print("ws: got {}".format(e))
|
||||
await the_game.send_page_reload()
|
||||
api.redirect(resp, url, status_code=303)
|
||||
|
||||
|
||||
async def set_trump_color(player, color):
|
||||
p = int(player)
|
||||
if p == the_game.players_ordered[-1].id:
|
||||
the_game.set_trump_color(color)
|
||||
await the_game.send_page_reload()
|
||||
|
||||
|
||||
async def initGame(player, ws):
|
||||
p = int(player)
|
||||
players = the_game.players[p:] + the_game.players[:p]
|
||||
n = [x.name for x in players]
|
||||
msg = {"type": "message", "fct": "startGame", "names": n}
|
||||
await ws.send_json(msg)
|
||||
|
||||
|
||||
async def getHand(player, ws):
|
||||
p = int(player)
|
||||
c = the_game.players[p].cards
|
||||
s = [x.json_serialise() for x in c]
|
||||
msg = {"type": "message", "fct": "getHand", "cards": s}
|
||||
await ws.send_json(msg)
|
||||
|
||||
|
||||
async def ws_handler(ws):
|
||||
await ws.accept()
|
||||
the_game.websockets.append(ws)
|
||||
while True:
|
||||
try:
|
||||
x = await ws.receive_json()
|
||||
fct = x['fct']
|
||||
if fct == 'playcard':
|
||||
p = int(x['player'])
|
||||
c = int(x['card'])
|
||||
await play_card_js(p, c)
|
||||
elif fct == 'setTrumpColor':
|
||||
player = x['player']
|
||||
color = x['color']
|
||||
await set_trump_color(player, color)
|
||||
elif fct == "requestInit":
|
||||
player = x['player']
|
||||
await initGame(player, ws);
|
||||
elif fct == "getHand":
|
||||
player = x['player']
|
||||
await getHand(player, ws)
|
||||
else:
|
||||
print("confused :(")
|
||||
except WebSocketDisconnect:
|
||||
the_game.websockets.remove(ws)
|
||||
break;
|
||||
|
||||
|
||||
@api.route('/ws', websocket=True)
|
||||
async def websocket(ws):
|
||||
await ws.accept()
|
||||
the_game.websockets.append(ws)
|
||||
try:
|
||||
foo = await ws.receive_text()
|
||||
except WebSocketDisconnect:
|
||||
the_game.websockets.remove(ws)
|
||||
task = asyncio.create_task(ws_handler(ws))
|
||||
the_game.ws_tasks.append(task)
|
||||
await task;
|
||||
|
||||
|
47
wiz_game.py
@ -1,7 +1,7 @@
|
||||
|
||||
import random
|
||||
from operator import attrgetter
|
||||
|
||||
|
||||
def chunks(lst, n):
|
||||
"""Yield successive n-sized chunks from lst."""
|
||||
for i in range(0, len(lst), n):
|
||||
@ -9,9 +9,10 @@ def chunks(lst, n):
|
||||
|
||||
|
||||
class Card:
|
||||
def __init__(self, color, value):
|
||||
def __init__(self, color, value, idx=None):
|
||||
self.color = color
|
||||
self.value = value
|
||||
self.idx = idx
|
||||
|
||||
def __str__(self):
|
||||
sc = self.color if self.color else ' '
|
||||
@ -21,6 +22,13 @@ class Card:
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
def json_serialise(self):
|
||||
if self.color and self.color != '-':
|
||||
s = "{}{:02d}".format(self.color, self.value)
|
||||
else:
|
||||
s = "{}{}".format(self.value.lower(), self.idx)
|
||||
return s
|
||||
|
||||
|
||||
def get_higher_card(card1: Card, card2: Card, trump_color: str):
|
||||
"""
|
||||
@ -28,7 +36,7 @@ def get_higher_card(card1: Card, card2: Card, trump_color: str):
|
||||
returns: True if card2 beats card1, otherwise False
|
||||
"""
|
||||
if card2.value == 'N':
|
||||
# no way to win in 'N' comes in second
|
||||
# no way to win if 'N' comes in second
|
||||
return False
|
||||
elif card1.value == 'Z':
|
||||
# no way to win if 'Z' was already played
|
||||
@ -72,6 +80,10 @@ class Player:
|
||||
def take_trick(self):
|
||||
self.tricks_taken += 1
|
||||
|
||||
def add_card(self, card):
|
||||
self.cards.append(card)
|
||||
self.cards = sorted(self.cards, key=attrgetter('color', 'value'))
|
||||
|
||||
|
||||
class WizGame:
|
||||
def __init__(self, player_names: list):
|
||||
@ -88,6 +100,7 @@ class WizGame:
|
||||
self.players_ordered = self.players
|
||||
self.last_trick = None
|
||||
self.websockets = []
|
||||
self.ws_tasks = []
|
||||
|
||||
def start_game(self):
|
||||
self.create_deck()
|
||||
@ -105,10 +118,10 @@ class WizGame:
|
||||
for color in ["b", "r", "g", "y"]:
|
||||
for val in range(1, 14):
|
||||
self.card_deck.append(Card(color, val))
|
||||
for _ in range(1, 5):
|
||||
self.card_deck.append(Card('-', 'Z'))
|
||||
for _ in range(1, 5):
|
||||
self.card_deck.append(Card('-', 'N'))
|
||||
for idx in range(1, 5):
|
||||
self.card_deck.append(Card('-', 'Z', idx))
|
||||
for idx in range(1, 5):
|
||||
self.card_deck.append(Card('-', 'N', idx))
|
||||
|
||||
def get_trump_color(self):
|
||||
card = self.trump_card
|
||||
@ -150,16 +163,16 @@ class WizGame:
|
||||
else:
|
||||
return True
|
||||
|
||||
def is_hand_finished(self):
|
||||
def is_round_finished(self):
|
||||
h = self.is_trick_finished()
|
||||
if h and self.num_tricks_played == self.current_round:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def next_hand(self):
|
||||
max_hands = len(self.card_deck)/len(self.players)
|
||||
if self.current_round <= max_hands:
|
||||
def next_round(self):
|
||||
max_rounds = len(self.card_deck)/len(self.players)
|
||||
if self.current_round <= max_rounds:
|
||||
self.current_round += 1
|
||||
self.start_player += 1
|
||||
if self.start_player >= len(self.players):
|
||||
@ -190,6 +203,7 @@ class WizGame:
|
||||
self.active_player += 1
|
||||
if self.is_trick_finished():
|
||||
self.num_tricks_played += 1
|
||||
return c # return card to calling function
|
||||
|
||||
def set_trump_color(self, trump_color):
|
||||
if self.trump_card.value != 'Z':
|
||||
@ -199,7 +213,6 @@ class WizGame:
|
||||
return False
|
||||
else:
|
||||
self.trump_card = Card(trump_color, 'Z')
|
||||
#self.trump_card.color = trump_color
|
||||
return True
|
||||
|
||||
def get_prev_player(self):
|
||||
@ -208,7 +221,15 @@ class WizGame:
|
||||
else:
|
||||
return self.start_player-1
|
||||
|
||||
async def send_page_reload(self):
|
||||
for ws in self.websockets:
|
||||
try:
|
||||
msg = {"type": "message", "fct": "reload"};
|
||||
await ws.send_json(msg)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
p = ["A", "B", "C", "D", "E"]
|
||||
|
||||
p = ["spam", "egg", "ham", "tomato"]
|
||||
the_game = WizGame(p)
|
||||
|
||||
|