Commit b6237c4d authored by ZettaScript's avatar ZettaScript
Browse files

Initial commit

parents
This diff is collapsed.
Ce programme est une implémentation du jeu Ğeconomicus pour jouer par Internet en client-serveur.
Ceci est la partie serveur, en python3.
Un logiciel client sera implémenté aussi, probablement en JavaScript pour être plus facile d'utilisation (pas d'installation pour le joueur).
Le serveur permettra d'héberger plusieurs parties, afin d'épargner aussi aux animateurs l'installation. Les parties pourront être crées à distance, depuis le client.
N'hésitez pas à me contacter si vous avez des idées ou des critiques concernant le principe ou ma manière d'implémenter, de coder... Il faut adapter les règles du jeu au support informatique, ce qui nécessite de faire des choix (par exemple, j'ai décidé de remplacer le système de billets par une valeur numérique, mais je garde le roulement des valeurs).
## Documentation
La classe Game représente une partie, et peut servir pour toute la durée d'un jeu, pour plusieurs systèmes monétaires.
La partie serveur, pour les interactions, ainsi que le système d'échanges ne sont pas encore implémentés. La classe de la monnaie dette non plus.
Le système de roulement des valeurs est aussi à faire.
Exemple :
import server
# Initialiser le jeu
game = server.Game("Partie de test", "Maître du jeu", ("127.0.0.1",8652), server.CONSTS.copy())
# Ajoutez autant de joueurs que vous voulez...
game.players.append(server.Player("Alice",("127.0.0.1",8653)))
game.players.append(server.Player("Bob",("127.0.0.1",8654)))
game.players.append(server.Player("Eve",("127.0.0.1",8655)))
# Démarrer une partie en monnaie libre
game.startGame(server.money_free)
game.newTurn()# Commencer le premier tour
game.endTurn()# Terminer le premier tour
game.newTurn()# Commencer le deuxième tour
game.endTurn()# Terminer le deuxième tour
print(game.players[0].wallet)# Les joueurs ont créé leur DU
print(server.moneySupply(game.players))# On peut voir la masse monétaire doubler de tour en tour
## Sources
http://www.trm.creationmonetaire.info/TheorieRelativedelaMonnaie.pdf
http://geconomicus.glibre.org/rules.html
https://www.youtube.com/watch?v=GMvQxk6mXhU
https://www.le-sou.org/2018/01/08/retour-experience-animation-jeu-geconomicus/
## Licence
Copyright 2018 Pascal Engélibert
> This file is part of Pygeconomicus-server.
>
> Pygeconomicus-server is free software: you can redistribute it and/or modify
> it under the terms of the GNU Affero General Public License as published by
> the Free Software Foundation, either version 3 of the License, or
> (at your option) any later version.
>
> Pygeconomicus-server is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU Affero General Public License for more details.
>
> You should have received a copy of the GNU Affero General Public License
> along with Pygeconomicus-server. If not, see <https://www.gnu.org/licenses/>.
La GNU AGPL impose de publier les sources d'une instance publiquement accessible de ce logiciel, si celles-ci sont modifiées. Pour faciliter cela, le serveur pourra générer et fournir une archive de son propre code source au client si celui-ci en fait la requête.
#!/usr/bin/env python3
"""
This file is part of Pygeconomicus-server.
Pygeconomicus-server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pygeconomicus-server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Pygeconomicus-server. If not, see <https://www.gnu.org/licenses/>.
"""
from utils import *
"""
Not implemented yet.
See money_free.py for a model.
"""
# Debt money
class MoneySystem():
name = "Monnaie dette"
def __init__(self):
pass
#!/usr/bin/env python3
"""
This file is part of Pygeconomicus-server.
Pygeconomicus-server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pygeconomicus-server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Pygeconomicus-server. If not, see <https://www.gnu.org/licenses/>.
"""
from utils import *
START_WALLET = 7
UDV = 1.0905 # UD Variation 109.05%/year is ~200%/8 years
# Free money
class MoneySystem():
name = "Monnaie libre"
def __init__(self, players, consts):
self.players = players
self.C = consts
self.UD = START_WALLET
self.UDV = UDV
# Init one player
def initPlayer(self, player, reborn=False):
if not reborn:
player.wallet = START_WALLET
# Init game part
def startGame(self):
# Init players
for player in self.players:
self.initPlayer(player, False)
self.low_value = self.C["N_VALUES"]-self.C["N_WVALUES"]
# New turn
def newTurn(self, turn):
if turn > 1:
# Create UD
M = moneySupply(self.players)
N = len(self.players)
# M[n] = M[n-1] + MAX( UD[n-1] ; M[n-1]*V ) with M=money supply, V=variation
# M[n] = M[n-y] + MAX( UD[n-y] ; M[n-y]*V^y ) with y=years since the last UD
self.UD = round(max(self.UD, (M*self.UDV**self.C["TURN_YEARS"]-M)/N), self.C["N_DIGITS"])
for player in self.players:
player.wallet += self.UD
# End turn
def endTurn(self):
pass
#!/usr/bin/env python3
"""
This file is part of Pygeconomicus-server.
Pygeconomicus-server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pygeconomicus-server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Pygeconomicus-server. If not, see <https://www.gnu.org/licenses/>.
"""
from sys import argv
from time import time
import configparser, socket, json, os
from random import randint, choice
import money_free, money_debt
from utils import *
# Default game constants
CONSTS = {
"N_VALUES": 4, # number of values types
"N_WVALUES": 1, # number of waiting values types
"TURN_DURATION": 300, # in seconds
"N_TURNS": 10, # number of turns in a game
"TURN_YEARS": 8, # number of years by turn
"LIFESPAN": 10, # max age
"N_DIGITS": 0, # number of decimals
"START_VALUES": 4 # number of random values for beginning
}
# Default server constants
PATH_CONF = "server.ini" # config file relative path
RECBUF = 1024 # reception buffer length
PROTOCOL_VERSIONS = [b"geco0"]# supported protocol versions
HOST = socket.gethostname() # server host name
PORT = 8651 # server port
games = []
class Player():
def __init__(self, name, address):
# Consts
self.name = name
self.address = address
# Vars
self.age = None
self.values = None
self.wallet = None
self.t_values = None
self.t_wallet = None
class Game():
def __init__(self, name, leader_name, leader_address, consts):
# Consts
self.name = name
self.creationtime = time()
self.leader_name = leader_name
self.leader_address = leader_address
self.C = consts
# Vars
self.players = [] # players list
self.money_system = None # the actual MoneySystem object
self.turn = None # current turn number
self.endturn = None # end turn timestamp
self.values = [None] * self.C["N_VALUES"] # values order (the last is the waiting value)
# Init one player
# pass reborn=False at beginning
# pass reborn=True when the player dies and reborns
def initPlayer(self, player, reborn):
if not reborn:
player.t_values = 0
player.t_wallet = 0
# Start with random values
player.values = [0] * self.C["N_VALUES"]
for i in range(self.C["START_VALUES"]):
player.values[randint(0, self.C["N_VALUES"]-self.C["N_WVALUES"])-1] += 1
# Init in MoneySystem
player.wallet = 0
self.money_system.initPlayer(player, reborn)
def feedPlayerReport(self, player):
player.t_values = player.values
player.t_wallet = player.wallet
# Init game part
def startGame(self, money_system):
self.money_system = money_system.MoneySystem(self.players, self.C)
self.turn = 0
self.values = list(range(self.C["N_VALUES"]))
# Init players
ages = []
age = 0
for i in range(len(self.players)):
ages.append(age)
age = (age+1) % self.C["LIFESPAN"]
for player in self.players:
age_p = choice(ages)
player.age = age_p
ages.remove(age_p)
self.initPlayer(player, False)
# New turn
def newTurn(self):
self.turn += 1
self.money_system.newTurn(self.turn)
# End turn
def endTurn(self):
self.money_system.endTurn()
# Kill some players
for player in self.players:
player.age += 1
if player.age >= self.C["LIFESPAN"]:
self.feedPlayerReport(player)
player.age = 0
self.initPlayer(player, True)
# Test routine
def test():
g = Game("lipsum","Yoda",("127.0.0.1",8652),CONSTS.copy())
g.players.append(Player("Alice",("127.0.0.1",8653)))
g.players.append(Player("Bob",("127.0.0.1",8654)))
g.players.append(Player("Eve",("127.0.0.1",8655)))
g.startGame(money_free)
return g
# Read config
def readConfig():
conf = configparser.ConfigParser()
conf.read(PATH_CONF)
if "Server" in conf:
if "Host" in conf["Server"]:
host = conf["Server"]["Host"]
if "Port" in conf["Server"]:
port = int(conf["Server"]["Port"])
if "Game" in conf:
for key, value in conf["Game"].items():
CONSTS[key] = value
"""
Partie serveur en dessous, pas encore fonctionnelle.
"""
if __name__ == "__main__":
# Config
readConfig()
HOST = getargv(argv, "-h", HOST)
POST = getargv(argv, "-p", PORT)
# Start server
loop = True
server_address = (HOST, PORT)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(server_address)
sock.listen(1)
print("Server started at "+str(server_address))
while loop:
client, addr = sock.accept()
paquet = b""
lf = 0
while True:
raw = client.recv(RECBUF)
if raw:
paquet += raw
if lf >= 0:
for c in raw:
if c == 10:# LF
lf += 1
elif c != 13:# CR
lf = 0
if lf > 1:
h = 0
else:
break
client.close()
# Parse paquet
try:
seps = [paquet.index(b"/")]
p_ver = paquet[:seps[0]]# protocol version
if not p_ver in PROTOCOL_VERSIONS:
print("Error: unsupported protocol version")
continue
seps.append(paquet.index(b"/", seps[0]+1))
seps.append(paquet.index(b"\n", seps[1]+1))
except ValueError:
print("Error: decoding header")
continue
p_lng = paquet[seps[0]+1:seps[1]]# data language
p_mod = chr(paquet[seps[1]+1])# mode
p_data_expected = p_mod in "pPQ"# if data expected
p_resp = p_mod in "IPQ"# if response expected by client
if p_data_expected:
try:
p_data = json.loads(p_raw)
except json.JSONDecodeError:
print("Error: decoding JSON")
continue
File added
#!/usr/bin/env python3
"""
This file is part of Pygeconomicus-server.
Pygeconomicus-server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pygeconomicus-server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Pygeconomicus-server. If not, see <https://www.gnu.org/licenses/>.
"""
# Server functions
def getargv(argv, arg, default=""):
if arg in argv and len(argv) > argv.index(arg)+1:
return argv[argv.index[arg]+1]
else:
return default
# Money functions
def moneySupply(players):
r = 0
for player in players:
r += player.wallet
return r
def relative(UD, amount):
return amount/UD
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment