Primi prototipi del funzionamento dei regolamenti e spiegazioni di cose nel README
parent
39c793583b
commit
5aad886817
@ -0,0 +1,80 @@
|
|||||||
|
package lupus
|
||||||
|
|
||||||
|
var (
|
||||||
|
AuraBianca = "bianca"
|
||||||
|
AuraNera = "nera"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
FazioneBuoni = "buoni"
|
||||||
|
FazioneCattivi = "cattivi"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Contadino = Ruolo{
|
||||||
|
Uid: "contadino",
|
||||||
|
Nome: "Contadino",
|
||||||
|
Fazione: FazioneBuoni,
|
||||||
|
Aura: AuraBianca,
|
||||||
|
}
|
||||||
|
Lupo = Ruolo{
|
||||||
|
Uid: "lupo",
|
||||||
|
Nome: "Lupo",
|
||||||
|
Fazione: FazioneCattivi,
|
||||||
|
Aura: AuraNera,
|
||||||
|
}
|
||||||
|
Fattucchiera = Ruolo{
|
||||||
|
Uid: "fattucchiera",
|
||||||
|
Nome: "Fattucchiera",
|
||||||
|
Fazione: FazioneCattivi,
|
||||||
|
Aura: AuraNera,
|
||||||
|
}
|
||||||
|
Indemoniato = Ruolo{
|
||||||
|
Uid: "indemoniato",
|
||||||
|
Nome: "Indemoniato",
|
||||||
|
Fazione: FazioneCattivi,
|
||||||
|
Aura: AuraBianca,
|
||||||
|
}
|
||||||
|
Kamikaze = Ruolo{
|
||||||
|
Uid: "kamikaze",
|
||||||
|
Nome: "Kamikaze",
|
||||||
|
Fazione: FazioneBuoni,
|
||||||
|
Aura: AuraBianca,
|
||||||
|
}
|
||||||
|
Guardia = Ruolo{
|
||||||
|
Uid: "guardia",
|
||||||
|
Nome: "Guardia",
|
||||||
|
Fazione: FazioneBuoni,
|
||||||
|
Aura: AuraBianca,
|
||||||
|
}
|
||||||
|
Cacciatore = Ruolo{
|
||||||
|
Uid: "cacciatore",
|
||||||
|
Nome: "Cacciatore",
|
||||||
|
Fazione: FazioneBuoni,
|
||||||
|
Aura: AuraBianca,
|
||||||
|
}
|
||||||
|
Medium = Ruolo{
|
||||||
|
Uid: "medium",
|
||||||
|
Nome: "Medium",
|
||||||
|
Fazione: FazioneBuoni,
|
||||||
|
Aura: AuraBianca,
|
||||||
|
}
|
||||||
|
Veggente = Ruolo{
|
||||||
|
Uid: "veggente",
|
||||||
|
Nome: "Veggente",
|
||||||
|
Fazione: FazioneBuoni,
|
||||||
|
Aura: AuraBianca,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ruoli è una lista di ruoli comuni, l'ordine è puramente casuale
|
||||||
|
var RuoliMap = map[string]Ruolo{
|
||||||
|
Contadino.Uid: Contadino,
|
||||||
|
Lupo.Uid: Lupo,
|
||||||
|
Fattucchiera.Uid: Fattucchiera,
|
||||||
|
Indemoniato.Uid: Indemoniato,
|
||||||
|
Guardia.Uid: Guardia,
|
||||||
|
Cacciatore.Uid: Cacciatore,
|
||||||
|
Medium.Uid: Medium,
|
||||||
|
Veggente.Uid: Veggente,
|
||||||
|
}
|
@ -1,132 +0,0 @@
|
|||||||
package lupus
|
|
||||||
|
|
||||||
// Ruleset si occupa di far avanzare la partita, per ora un'implementazione di questa interfaccia è meglio se non ha stato (TODO: Forse sarebbe meglio come struct di funzioni)
|
|
||||||
type Ruleset interface {
|
|
||||||
// Start viene chiamata all'inizio di una partita per inizializzare una partita partendo da alcune info di configurazione
|
|
||||||
Start(PartitaConfig) PartitaState
|
|
||||||
|
|
||||||
// Update prende lo stato della partita e ne ritorna uno nuovo eventualmente utilizzando delle "UserResponse" fatte precedentemente all'utente (alla prima chiamata questa lista è vuota), successivamente c'è una corrispondenza tra lo slice di "[]UserRequest" ritornato ed il successivo slice "[]UserResponse" ricevuto.
|
|
||||||
Update(state PartitaState, responses []UserResponse) (PartitaState, []UserRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PartitaConfig è un config minimale per creare il primo stato della partita
|
|
||||||
type PartitaConfig struct {
|
|
||||||
Players []string
|
|
||||||
RoleCounts map[Ruolo]int
|
|
||||||
}
|
|
||||||
|
|
||||||
// PartitaState rappresenta lo stato della partita
|
|
||||||
type PartitaState struct {
|
|
||||||
// Players è una mappa da username a giocatore
|
|
||||||
Players []Player `json:"players"`
|
|
||||||
// Time indica la fase corrente del gioco (la parità indica notte/giorno e si inizia da "Notte 0")
|
|
||||||
Time uint `json:"time"`
|
|
||||||
// PhaseActions indica quali azioni sono state fatte in una certa fase
|
|
||||||
Actions []Action `json:"actions"`
|
|
||||||
// Won inizialmente è nil e diventa &"FazioneBuoni" o &"FazioneCattivi" quando una delle due fazioni viene dichiarata vincitrice
|
|
||||||
Won *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Player struct {
|
|
||||||
Username string `json:"username"`
|
|
||||||
Ruolo Ruolo `json:"ruolo"`
|
|
||||||
Vivo bool `json:"vivo"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ruolo struct {
|
|
||||||
Uid string `json:"uid"`
|
|
||||||
Nome string `json:"nome"`
|
|
||||||
Fazione string `json:"fazione"`
|
|
||||||
Aura string `json:"aura"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Action struct {
|
|
||||||
Uid string `json:"uid"`
|
|
||||||
Time uint `json:"time"` // Time indica in quale fase è stata compiuta l'azione
|
|
||||||
Player string `json:"player"`
|
|
||||||
TargetPlayer string `json:"targetPlayer"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
AuraBianca = "bianca"
|
|
||||||
AuraNera = "nera"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
FazioneBuoni = "buoni"
|
|
||||||
FazioneCattivi = "cattivi"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Contadino = Ruolo{
|
|
||||||
Uid: "contadino",
|
|
||||||
Nome: "Contadino",
|
|
||||||
Fazione: FazioneBuoni,
|
|
||||||
Aura: AuraBianca,
|
|
||||||
}
|
|
||||||
Lupo = Ruolo{
|
|
||||||
Uid: "lupo",
|
|
||||||
Nome: "Lupo",
|
|
||||||
Fazione: FazioneCattivi,
|
|
||||||
Aura: AuraNera,
|
|
||||||
}
|
|
||||||
Fattucchiera = Ruolo{
|
|
||||||
Uid: "fattucchiera",
|
|
||||||
Nome: "Fattucchiera",
|
|
||||||
Fazione: FazioneCattivi,
|
|
||||||
Aura: AuraNera,
|
|
||||||
}
|
|
||||||
Indemoniato = Ruolo{
|
|
||||||
Uid: "indemoniato",
|
|
||||||
Nome: "Indemoniato",
|
|
||||||
Fazione: FazioneCattivi,
|
|
||||||
Aura: AuraBianca,
|
|
||||||
}
|
|
||||||
Guardia = Ruolo{
|
|
||||||
Uid: "guardia",
|
|
||||||
Nome: "Guardia",
|
|
||||||
Fazione: FazioneBuoni,
|
|
||||||
Aura: AuraBianca,
|
|
||||||
}
|
|
||||||
Cacciatore = Ruolo{
|
|
||||||
Uid: "cacciatore",
|
|
||||||
Nome: "Cacciatore",
|
|
||||||
Fazione: FazioneBuoni,
|
|
||||||
Aura: AuraBianca,
|
|
||||||
}
|
|
||||||
Medium = Ruolo{
|
|
||||||
Uid: "medium",
|
|
||||||
Nome: "Medium",
|
|
||||||
Fazione: FazioneBuoni,
|
|
||||||
Aura: AuraBianca,
|
|
||||||
}
|
|
||||||
Veggente = Ruolo{
|
|
||||||
Uid: "veggente",
|
|
||||||
Nome: "Veggente",
|
|
||||||
Fazione: FazioneBuoni,
|
|
||||||
Aura: AuraBianca,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ruoli è una lista di ruoli comuni, l'ordine è puramente casuale
|
|
||||||
var RuoliMap = map[string]Ruolo{
|
|
||||||
Contadino.Uid: Contadino,
|
|
||||||
Lupo.Uid: Lupo,
|
|
||||||
Fattucchiera.Uid: Fattucchiera,
|
|
||||||
Indemoniato.Uid: Indemoniato,
|
|
||||||
Guardia.Uid: Guardia,
|
|
||||||
Cacciatore.Uid: Cacciatore,
|
|
||||||
Medium.Uid: Medium,
|
|
||||||
Veggente.Uid: Veggente,
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserRequest struct {
|
|
||||||
TargetPlayer string
|
|
||||||
|
|
||||||
Request any // TODO: Work in progress
|
|
||||||
}
|
|
||||||
type UserResponse struct {
|
|
||||||
TargetPlayer string
|
|
||||||
|
|
||||||
Response any // TODO: Work in progress
|
|
||||||
}
|
|
@ -0,0 +1,85 @@
|
|||||||
|
package lupus
|
||||||
|
|
||||||
|
// PartitaConfig è un config minimale per creare il primo stato della partita
|
||||||
|
type PartitaConfig struct {
|
||||||
|
Players []string
|
||||||
|
RoleCounts map[Ruolo]int
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitaState rappresenta lo stato della partita
|
||||||
|
type PartitaState struct {
|
||||||
|
// Players è una mappa da username a giocatore
|
||||||
|
Players []Player `json:"players"`
|
||||||
|
// Time indica la fase corrente del gioco (la parità indica notte/giorno e si inizia da "Notte 0")
|
||||||
|
Time uint `json:"time"`
|
||||||
|
// PhaseActions indica quali azioni sono state fatte in una certa fase
|
||||||
|
Actions []Action `json:"actions"`
|
||||||
|
// Won inizialmente è nil e diventa &"FazioneBuoni" o &"FazioneCattivi" quando una delle due fazioni viene dichiarata vincitrice
|
||||||
|
Won *string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PartitaState) IsNotte() bool { return p.Time%2 == 0 }
|
||||||
|
func (p PartitaState) IsGiorno() bool { return p.Time%2 == 1 }
|
||||||
|
|
||||||
|
func (p PartitaState) NumeroGiorno() uint { return (p.Time + 1) / 2 }
|
||||||
|
|
||||||
|
type Player struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Ruolo Ruolo `json:"ruolo"`
|
||||||
|
Vivo bool `json:"vivo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action struct {
|
||||||
|
Uid string `json:"uid"`
|
||||||
|
Time uint `json:"time"` // Time indica in quale fase è stata compiuta l'azione
|
||||||
|
Player string `json:"player"`
|
||||||
|
TargetPlayer string `json:"targetPlayer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ruolo struct {
|
||||||
|
Uid string `json:"uid"`
|
||||||
|
Nome string `json:"nome"`
|
||||||
|
Fazione string `json:"fazione"`
|
||||||
|
Aura string `json:"aura"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func RuoloMainCmd(player Player, state PartitaState) (cmd PlayerCommand, noop bool) {
|
||||||
|
switch player.Ruolo {
|
||||||
|
case Veggente, Lupo, Cacciatore, Guardia, Kamikaze:
|
||||||
|
alivePlayers := []string{}
|
||||||
|
for _, p := range state.Players {
|
||||||
|
if p.Vivo {
|
||||||
|
alivePlayers = append(alivePlayers, p.Username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlayerCommand{
|
||||||
|
TargetPlayer: player.Username,
|
||||||
|
Request: ChoosePlayerCmd{alivePlayers},
|
||||||
|
}, false
|
||||||
|
case Medium:
|
||||||
|
deadPlayers := []string{}
|
||||||
|
for _, p := range state.Players {
|
||||||
|
if !p.Vivo {
|
||||||
|
deadPlayers = append(deadPlayers, p.Username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlayerCommand{
|
||||||
|
TargetPlayer: player.Username,
|
||||||
|
Request: ChoosePlayerCmd{deadPlayers},
|
||||||
|
}, false
|
||||||
|
case Fattucchiera:
|
||||||
|
allPlayers := []string{}
|
||||||
|
for _, p := range state.Players {
|
||||||
|
allPlayers = append(allPlayers, p.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlayerCommand{
|
||||||
|
TargetPlayer: player.Username,
|
||||||
|
Request: ChoosePlayerCmd{allPlayers},
|
||||||
|
}, false
|
||||||
|
default:
|
||||||
|
return PlayerCommand{}, true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package lupus
|
||||||
|
|
||||||
|
// Ruleset si occupa di far avanzare la partita
|
||||||
|
type Ruleset struct {
|
||||||
|
// Start viene chiamata all'inizio di una partita per inizializzare una partita partendo da alcune info di configurazione
|
||||||
|
Start func(PartitaConfig) PartitaState
|
||||||
|
|
||||||
|
// Update prende lo stato della partita e ne ritorna uno nuovo eventualmente utilizzando delle "UserResponse" fatte precedentemente all'utente (alla prima chiamata questa lista è vuota), successivamente c'è una corrispondenza tra lo slice di "[]UserRequest" ritornato ed il successivo slice "[]UserResponse" ricevuto.
|
||||||
|
Update func(state PartitaState, responses []PlayerMessage) (PartitaState, []PlayerCommand)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cmd interface{ Cmd() }
|
||||||
|
type Msg interface{ Msg() }
|
||||||
|
|
||||||
|
// PlayerCommand rappresenta un "comando" per un certo giocatore, nella fattispecie può dire di mostrare al giocatore un messaggio o anche un prompt che chiede qualcosa all'utente
|
||||||
|
type PlayerCommand struct {
|
||||||
|
TargetPlayer string
|
||||||
|
|
||||||
|
Request Cmd // TODO: Work in progress
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlayerMessage è una risposta da parte del giocatore ad un comando
|
||||||
|
type PlayerMessage struct {
|
||||||
|
TargetPlayer string
|
||||||
|
|
||||||
|
Response Msg // TODO: Work in progress
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cmd & Msg
|
||||||
|
//
|
||||||
|
|
||||||
|
type ChoosePlayerCmd struct {
|
||||||
|
Players []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ChoosePlayerCmd) Cmd() {}
|
||||||
|
|
||||||
|
type ChoosePlayerMsg struct {
|
||||||
|
Player string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ChoosePlayerMsg) Msg() {}
|
Loading…
Reference in New Issue