npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

simplegameframe

v1.0.0

Published

Framework for rule based games

Downloads

4

Readme

Un framework per giochi basati su regole

Simple Game Frame

Durante la mia breve esperienza con i giochi da tavolo ho potuto notare che buona parte di questi seguono dei principi di base molto simili, quindi ho pensato di formulare un modello pseudomatematico-semiformale che potesse descrivere questi principi di base per poi tradurlo in JavaScript per verificarne la correttezza e magari cimentarmi anche nella riscrittura di alcuni giochi.

Definizione ~quasi~Formale

Lo stato del gioco è una tupla (o un semplice insieme?) che contiene tutti
i dati che possono cambiare nel gioco es punteggio, giocatori, notifiche ecc.
Gli elementi della tupla dello stato del gioco possono essere diversi a seconda
del gioco: un gioco di carte può avere il mazzo, le mani del giocatore e il
punteggio mentre un gioco di dadi avrà solamente i punteggi

STATE := { s : stato del gioco } = <s>

Una regola è una funzione che può causare un cambio dello stato del gioco

           r(s)
RULE := ───────────
        <s> ─> <s'>

PLAYERS := { p : un giocatore }

Il giocatore è colui che chiama le regole e riceve le notifiche sullo
svolgimento della partira.
L'applicaione di una regola può modificare la percezione che i giocatori
hanno della partita stessa (sia lo stesso giocatore che anche altri giocatori),
quindi l'applicazione di una regola può causare modifiche allo stato globale
del gioco e anche notificare ai giocatori l'evento.
Le notifiche avvenute fanno parte dello stato.

U ⊆ PLAYERS

U<s> ⊆ STATE := { U<s> : <s> ⊆ STATE relativo a U ⊆ PLAYERS }

                  p.do(r)    
PLAYERS::DO := ──────────────
               U<s> ──> U<s'>

ES.
Un giocatore pesca una carta da un mazzo:
- lo stato del gioco si aggiorna
- ai giocatori viene notificato che c'è stato un cambio di stato
- al giocatore che ha pecato la carta viene notificata quale carta ha pescato

L'applicazione di una regola può anche lasciare lo stato invariato.
ES. una regola che viene rigettata.

    p.do(r)   
 ─────────────
 <s> ────> <s>

Una regola può portare lo stato in FINAL STATE.

FINAL STATE := f ∈ STATE

   r(s)
───────────
<s> ─> <f>

Se un gioco è in FINAL STATE i giocatori non possono cambiare lo stato
invocando altre regole.

   p.do(r)
─────────────
p<f> ──> p<f>

A questo punto si può descrivere un gioco come un insieme di regole.

SOMEGAME := { r1, r2, r3, ...rN }

Una partita a un gioco è una successione di regole invocate da un giocatore.

MATCH(SOMEGAME) := { pA.do(rX), pB.do(rY), ...pK.do(rF) }

Questa sequenza cusa una serie di cambi di stato nella partita fino al
ragiungimento dello stato finale.

                        pA.do(rX)       pB.do(rY)            pK.do(rF)   
MATCH(SOMEGAME) := { ──────────────, ───────────────, ... ────────────── }
                     <s> ────> <s'>  <s'> ────> <s">      <sN> ────> <f> 

Implementazione e interfaccie

Le classi implementate sono

  • Rule per rappresentare una regola
  • Storage per contenere lo stato
  • Game è una interfaccia per il gioco
  • Player astrae il giocatore, cioé applica le regole e riceve le notifiche
  • Notification per avvertire un giocatore di un evento, es cambio di stato a seguito dell'applicazione di una regola
  • Alcune entità es Dice

TODO più meno per priorità

  • storage deve triggerare gli eventi on notifications e unlock anche su istanze del gioco diverse, quindi in caso di storage condivisi (non storage memory) anche su processi diversi, in modo che le notification vengono triggerate anche su riferimenti diversi in diversi processi

    • quando fai storage file le istanze di storage file nei processi si devono appendere alle modifiche dei path per poter triggerare gli eventi anche loro

    • per fare i test serve un istanza condivisa di storage memory *

    in generale fare bene il memory dovrebbe far uscire fuori la classe per lo storage dei file facilmente. Quindi sarebbe buono separare database e farlo il più simile a come sarà storage file (mah... poi si perderebbe il fatto che memory è l'unico per istanza). Nota che gli eventi dello storage non devono portare con se a risorsa modificata, al massimo solo alune info tipo il path.

    Open negli storage deve essere atomica veramente per risorsa: non deve essere possibile mai che due open con modifier throw sulla stessa risorsa ritornino entrambe. Una deve sollevare un GameError

  • file storage

  • giochi, esempi, test e documentazione

    • dice esempio cli e integrare il test
    • gioco esempio web server + test
    • più documentazione
  • mongo storage

  • sql storage

  • more entities (Card, Deck, Hand, Pown, Board)

Note Se read e lock devono notificare, devono farlo a livello di istanza, cioè io leggo da istanza x di storage e istanza x triggra, le altre no.

Write e lock devono triggerare e lo devono fare a livello globale, quindi se uno storage in un istanza di un gioco in un processo scrive, l'evento deve arrivare anche agli altri storage dello stesso tipo e configurati ugualmente, anche in processi diversi

  • creo un istanza sorage
  • storage triggera quando viene scritta una risorsa
    • es quando viene aggiunta una notifica, essendo risorse anche le notifiche
  • se viene aggiunta una notifica al giocatore deve arrivare l'evento che è arrivata una notifica
  • potrebbe non dover essere notify a triggerate direttamente, bensi una catena di eventi:
    • ~game in join~ player nel costruttore si appende all'evento dello storage (preso dal game)
    • quando parte un evento di scrittura di una notifica nello storage questa viene notificata al player
    • in destroy vengono rimossi gli handler.

Note sotrage file, watch e linux

Su linux fx.watch {recursive: true} non funziona, watch -d -t -g du -sb; potrebbe essere il degno fallback. No è na merda.. dai..

Si potrebbero dedicare un file agli eventi write e uno a gli eventi unlock dello storage e si fa watch di quei file, dopo le scritture si scrive su quel file il path del file modificato, così si possono triggerare gli eventi e passare il path della risorsa modificata Ricorda: quei file servono solo per l'evento. Nient'altro. Mai!!! Non usarli mai per vedere che ci sta di aperto. Vanno scritti e letti solo per sollevare l'evento.