Page 1 sur 1

[MUD] Inventaire léger/Sauvegarde

Publié : mar. 28/juin/2011 10:29
par MonchauxantZ
Bonjour :)
Vu que c'est mon premier message, autant que je me présente, je suis donc MonchauxantZ, développeur à Over Online G&L, petit groupe de créateurs amateurs...
Pour info, je suis pas mal de forums, dont l'assez connu "GameCorp".

Nous créions un jeu, mais par un retard des graphistes, les développeurs (dont moi) on décidé de créer un jeu sympa sans images : un MUD (Multi-User-Dungeons).
Vous savez peut-être qu'un MUD se joue généralement par Telnet pour la rapidité, mais on a préféré le faire en PureBasic, langage qu'on connaît bien, pour le faire : de plus, après son téléchargement, le joueur pourra y jouer sans être forcément connecté à Internet, et pourra donc faire les quêtes non-communautaires et xp un peu. Si il se reconnecte à Internet, les données seront renvoyées au serveur et il sera donc connecté.

Seulement on a un petit problème :D
On aimerait faire un système d'inventaire simple et rapide, pas trop trop lourd et donc pas 50 lignes :) (Comme j'en ai vu par ici...)
Petite ébauche de code :

Code : Tout sélectionner

Structure Inventaire

    Nom_Objet.l
    Type_Objet.l
    Desc_objet.l
    Quantite_objet.l
    
EndStructure
    
Dim Sac.Inventaire(200)
Au-dessus, c'est la structure de l'inventaire dans "joueur.pbi"

Code : Tout sélectionner

Chance_drop=Random(9)+1
If Chance_Drop < 5
Inventaire(Nbr_Objet)\Nom_objet = Dropcommun$
EndIf
If Chance_Drop < 4
Inventaire(Nbr_Objet)\Nom_objet = Droppeucommun$
EndIf
If Chance_Drop < 2
Inventaire(Nbr_Objet)\Nom_objet = Droprare$
EndIf
If Chance_Drop = 1
Inventaire(Nbr_Objet)\Nom_objet = Droptresrare$
Au-dessus, c'est le drop, relié à un monstre, prenons pour exemple le rat, ci-dessous :

Code : Tout sélectionner

Creature$="Rat"
Pv_Creature=Random(19)+1
Atk_Creature=Random(9)+1
Def_Creature=Random(19)+1
Exp_Creature=2

Dropcommun$="Potion"
Typecommun="Conso"
Desccommun="Rend 20 pv"

Droppeucommun$="Peau de rat"
Typepeucommun="Divers"
Descpeucommun="A manger pour ce soir ?"

Dropprare$="Dent de rat"
Typerare="Divers"
Descrare="Tranchant, attention."

Droptresrare$="Epee du rat"
Typetrsrare="Equip"
Desctresrare="Une epee en dents de rat"
Voilà. Seulement, est t-il possible d'optimiser ce code, ou est-t-il faussé ?
Egalement, comment faire pour savoir quand un objet est déjà dans l'inventaire, et ajouter 1 à sa quantité ?


...

Seconde question :)
J'ai du mal avec les sauvegardes, les createfile et autres commandes de ce genre...

Voilà donc le fichier save.pbi :

Code : Tout sélectionner

Enumeration
#SaveP
#SaveA
#SaveD
#SaveV
#SaveVM
#SavePM
#SavePMM
EndEnumeration



Procedure SavePseudo(Son_Pseudo$) 
  If CreateFile(#SaveP,"SauvePseudo.ood") 
    WriteStringN(#SaveP, Son_Pseudo$) 
    CloseFile(#SaveP) 
  EndIf 
EndProcedure

Procedure SaveMdp(Son_Mdp$) 
  If CreateFile(#SaveMdP,"SauvePassword.ood") 
    WriteStringN(#SaveMdP, Son_Mdp$) 
    CloseFile(#SaveMdP) 
  EndIf 
EndProcedure

Procedure SaveXP(Son_XP) 
  If CreateFile(#SaveXP,"SauveExp.ood") 
    WriteLong(#SaveXP, Son_XP) 
    CloseFile(#SaveXP) 
  EndIf 
EndProcedure

Procedure SaveAtk(Son_Atk) 
  If CreateFile(#SaveA,"SauveAtk.ood") 
    WriteLong(#SaveA, Son_Atk) 
    CloseFile(#SaveA) 
  EndIf 
EndProcedure  
Et ainsi de suite pour la défense, l'équipement...

Ces procédures sont inclues dans le fichier du jeu, mais je pense qu'on pourrait réduire la taille du fichier save.pbi :)
Voilà, c'est tout :D

Re: [MUD] Inventaire léger/Sauvegarde

Publié : mar. 28/juin/2011 11:14
par Geo Trouvpatou
Salut à toi.

Pas trop de temps donc je répond vite fait à ta 2ème question.
La procedure SaveToutEtNImporteQuoi permet de remplacer toutes tes autres procédures.

Code : Tout sélectionner

Enumeration
      #SaveP
      #SaveA
      #SaveMdP
      #SaveXP
EndEnumeration

Procedure SavePseudo(Son_Pseudo$)
      If CreateFile(#SaveP,"SauvePseudo.ood")
            WriteStringN(#SaveP, Son_Pseudo$)
            CloseFile(#SaveP)
      EndIf
EndProcedure

Procedure SaveMdp(Son_Mdp$)
      If CreateFile(#SaveMdP,"SauvePassword.ood")
            WriteStringN(#SaveMdP, Son_Mdp$)
            CloseFile(#SaveMdP)
      EndIf
EndProcedure

Procedure SaveXP(Son_XP)
      If CreateFile(#SaveXP,"SauveExp.ood")
            WriteLong(#SaveXP, Son_XP)
            CloseFile(#SaveXP)
      EndIf
EndProcedure

Procedure SaveAtk(Son_Atk)
      If CreateFile(#SaveA,"SauveAtk.ood")
            WriteLong(#SaveA, Son_Atk)
            CloseFile(#SaveA)
      EndIf
EndProcedure  

SavePseudo("azerty")
SaveMdp("01aze")
SaveXP(102)
SaveAtk(80)


Procedure SaveToutEtNImporteQuoi(nomFichier$, valeur$, type$ = "string")
      
      resultat = CreateFile(#PB_Any, nomFichier$)
      
      If resultat
            
            If type$ = "string"
                  WriteStringN(resultat, valeur$)
            ElseIf type$ = "long"
                  WriteLong(resultat, Val(valeur$))
            EndIf
            
            CloseFile(resultat)   
      EndIf
      
EndProcedure


SaveToutEtNImporteQuoi("Toto.ood", "Seigneur") ; enregistrement en WriteStringN
SaveToutEtNImporteQuoi("Toto2.ood", "100", "long") ; enregistrement enWriteLong
Après il y a peut-être mieux.

Bye.

Re: [MUD] Inventaire léger/Sauvegarde

Publié : mar. 28/juin/2011 11:55
par Backup
oui il y a mieux ;)

voir la librairie "Preference" du Purebasic
qui permet de sauver dans un seul fichier , des informations hierarchisés

du point de vue programmeur, c'est comparable a un acces Direct
tu peux modifier aisément qu'une partie du fichier, sans que cela n'altere l'ensemble du fichier ...

une fois qu'on y a gouté, on ne décroche plus ! :)

Code : Tout sélectionner

;
; ------------------------------------------------------------
;
;   PureBasic - Preference example file
;
;    (c) 2002 - Fantaisie Software
;
; ------------------------------------------------------------
;

If CreatePreferences("Preferences.prefs")
  PreferenceGroup("Global")
    WritePreferenceString("ApplicationName", "MP3 Player")
    WritePreferenceString("Version", "1.1b")

  PreferenceComment(" This is the Window dimension")
  PreferenceComment("")

  PreferenceGroup("Window")
    WritePreferenceLong ("WindowX", 123)
    WritePreferenceLong ("WindowY", 124)
    WritePreferenceFloat("WindowZ", -125.5)

  ClosePreferences()
EndIf


OpenPreferences("Preferences.prefs")

  PreferenceGroup("Window")   ; <------voir le fichier avec un editeur pour comprendre ce que ça donne !! 
    Debug ReadPreferenceLong ("WindowX", 0)
    Debug ReadPreferenceLong ("WindowY", 0)
    Debug ReadPreferenceFloat("WindowZ", 0)
    
  PreferenceGroup("Global")
    Debug ReadPreferenceString("ApplicationName", "")
    Debug ReadPreferenceString("Version", "")
    
ClosePreferences()


ici par exemple on pourrai ne changer que la partie "Window" sans modifier le reste
avec un :

Resultat = ExaminePreferenceGroups()
if PreferenceGroupName() ="Window"
endif

Resultat = NextPreferenceGroup()


ceci :

Code : Tout sélectionner

Chance_drop=Random(9)+1
If Chance_Drop < 5
Inventaire(Nbr_Objet)\Nom_objet = Dropcommun$
EndIf
If Chance_Drop < 4
Inventaire(Nbr_Objet)\Nom_objet = Droppeucommun$
EndIf
If Chance_Drop < 2
Inventaire(Nbr_Objet)\Nom_objet = Droprare$
EndIf
If Chance_Drop = 1
Inventaire(Nbr_Objet)\Nom_objet = Droptresrare$ 
deviens :

Code : Tout sélectionner

Chance_drop=Random(9)+1
Select Chance_drop
      Case<5
            Inventaire(Nbr_Objet)\Nom_Objet = Dropcommun$
      Case < 4
            Inventaire(Nbr_Objet)\Nom_Objet = Droppeucommun$
      Case < 2
            Inventaire(Nbr_Objet)\Nom_Objet = Droprare$
      Case 1
            Inventaire(Nbr_Objet)\Nom_Objet = Droptresrare$ 
EndSelect
l'utilisation de select Case est plus claire qu'une serie de If-endif
et contient moins de lignes de codes au final ;)

Egalement, comment faire pour savoir quand un objet est déjà dans l'inventaire, et ajouter 1 à sa quantité ?
tu es obligé de parcourir l'inventaire
un truc dans le genre :

Code : Tout sélectionner

Procedure.s test_inventaire(nom_objet$)
      For i=0 To ArraySize(inventaire())
            If Inventaire(i)\Nom_Objet =nom_objet$)
                  ProcedureReturn "existe" ; on l'a deja donc on ne prends pas
            EndIf 
      Next i
      ; si on arrive là, on a pas trouvé l'objet
      ; on l'ajoute
      Redim Inventaire(Nbr_Objet+1)\Nom_Objet
      Inventaire(Nbr_Objet+1)\Nom_Objet = nom_objet$
      Inventaire(Nbr_Objet+1)\Quantite_objet.l=Inventaire(Nbr_Objet+1)\Quantite_objet.l+1
EndProcedure

mais pour ce genre de truc je te conseille l'utilisation des listes chainées a la place de Tableau ..
:)

Re: [MUD] Inventaire léger/Sauvegarde

Publié : mar. 28/juin/2011 13:34
par MonchauxantZ
Ah oui, merci :)
Je pense vraiment que je vais garder la version de Dobro, j'ai regardé les préférences, et c'est vrai, je sens que je ne vais pas pouvoir m'en passer :D
Vraiment intéressant comme commande...
Par contre, pour l'inventaire, le "For i=0 to ArraySize" ne peut-il pas être remplacé par "ForEach inventaire()" ?

Egalemment, pour les drops, je pensais que Select ne servait que pour les input() et autres commandes de texte de ce genre, mais je n'aurais jamais pensé l'utiliser comme ça x)

Sinon Géo, le code fonctionne mais c'est ce que je voulais éviter, trop grossir le code en Sauvegarde/Chargement.

Re: [MUD] Inventaire léger/Sauvegarde

Publié : mar. 28/juin/2011 16:27
par Backup
MonchauxantZ a écrit : Par contre, pour l'inventaire, le "For i=0 to ArraySize" ne peut-il pas être remplacé par "ForEach inventaire()" ?
c'est pourquoi j'ai ecris :
mais pour ce genre de truc je te conseille l'utilisation des listes chainées a la place de Tableau ..
Foreach -Next c'est réservé aux listes chainée ;)

Re: [MUD] Inventaire léger/Sauvegarde

Publié : jeu. 07/juil./2011 15:07
par MonchauxantZ
Ah lala, c'est encore moi x)

Petite erreur dans le mélange de nos bouts de code :

Quand je fais ca :

Code : Tout sélectionner

Structure Inventaire

    Nom_Objet.l
    Type_Objet.l
    Desc_objet.l
    Quantite_objet.l
    
EndStructure
    
Dim Inventaire(200)


Procedure.s test_inventaire(nom_objet$)
      For i=0 To ArraySize(inventaire())
            If Inventaire(i)\Nom_Objet =nom_objet$)
                  ProcedureReturn "existe" ; on l'a deja donc on ne prend pas
            EndIf 
      Next i
      ; si on arrive là, on a pas trouvé l'objet
      ; on l'ajoute
      ReDim Inventaire(Nbr_Objet+1)\Nom_Objet
      Inventaire(Nbr_Objet+1)\Nom_Objet = nom_objet$
      Inventaire(Nbr_Objet+1)\Quantite_objet.l=Inventaire(Nbr_Objet+1)\Quantite_objet.l+1
EndProcedure
Ca me met "Inventaire() n'est pas une liste, un tableau ou une structure."

Et aussi, pour :

Code : Tout sélectionner

;- Droper un objet
;_____________________________________________________________________________________________________________
drop:
Chance_drop=Random(9)+1
Select Chance_drop
      Case <5
            Inventaire(Nbr_Objet)\Nom_Objet = Dropcommun$
      Case < 4
            Inventaire(Nbr_Objet)\Nom_Objet = Droppeucommun$
      Case < 2
            Inventaire(Nbr_Objet)\Nom_Objet = Droprare$
      Case 1
            Inventaire(Nbr_Objet)\Nom_Objet = Droptresrare$ 
EndSelect
Return
Ca me met "Erreur de syntaxe" sur la ligne des "Case".

Ca fait un bout de temps que je cherche, mais je trouve pas :)

Re: [MUD] Inventaire léger/Sauvegarde

Publié : jeu. 07/juil./2011 16:18
par graph100
Pour ton 1er problème : ton tableau n'est pas déclaré en Global, sa portée est donc limitée au code principal.

Déclare le de la façon suivante :

Code : Tout sélectionner

Structure Inventaire 
	
	Nom_Objet.s
	
	Type_Objet.l 
	Desc_objet.l 
	Quantite_objet.l 
	
EndStructure 

Global Dim Inventaire.Inventaire(200) 
Global Nbr_Objet = 0

Procedure.s test_inventaire(nom_objet$) 
	For i = 0 To ArraySize(inventaire())
		If Inventaire(i)\Nom_Objet = nom_objet$
			ProcedureReturn "existe" ; on l'a deja donc on ne prend pas 
		EndIf  
	Next
	
	; si on arrive là, on a pas trouvé l'objet 
	; on l'ajoute 
	
	; 	ReDim Inventaire(Nbr_Objet + 1) <---------- à mon humble avis, cette ligne n'a pas lieux d'être
	
	Nbr_Objet + 1
	
	Inventaire(Nbr_Objet)\Nom_Objet = nom_objet$ 
	Inventaire(Nbr_Objet)\Quantite_objet.l = Inventaire(Nbr_Objet)\Quantite_objet.l + 1
	
	ProcedureReturn "Ajouté"
EndProcedure


Debug test_inventaire("Cuillère Magique")
J'ai de plus corrigé d'autre problèmes, dont le fait que ton tableau n'etais pas structuré, et donc que tu ne pouvais pas utiliser les champ de structure avec.
Fait attention, ce n'est pas parceque la structure et le tableau ont le même nom que le tableau est structuré par la structure.
Mais bien parce que le tableau est déclaré comme étant du type de la structure. (cf code corrigé)

Je pense que pour ton affaire un tableau n'est pas une bonne idée. Utilise plutot une map, comme suis :

Code : Tout sélectionner

Structure Inventaire 
	Nom_Objet.s
	
	Type_Objet.l 
	Desc_objet.l 
	Quantite_objet.l 
EndStructure 


Global NewMap Inventaire.Inventaire(200) ; créé une map avec 200 slots déjà alloués. si tu prévois un nombre d'objets plus grand, change ce nombre.


Procedure.s Test_Inventaire(nom_objet$) 
	
	If FindMapElement(Inventaire(), nom_objet$)
		ProcedureReturn "existe" ; on l'a deja donc on ne prend pas 
	Else
		; si on arrive là, on a pas trouvé l'objet 
		; on l'ajoute 
		
		Inventaire(nom_objet$)\Nom_Objet = nom_objet$ ; Ajoute un nouvel élément à la map, et affecte le nom_objet$ au champ \Nom_Objet de l'élément venant d'être créer, et référencé par la clé qui est la valeur de nom_objet$
		Inventaire()\Quantite_objet = 1 ; comme l'élément à déjà été créé, il est devenu l'élément courant, et on n'a pas besoin de repréciser la clé.
		
		ProcedureReturn "Ajouté"
	EndIf
	
EndProcedure


Debug test_inventaire("Cuillère Magique")
Debug test_inventaire("Cuillère Magique")
Dans ce cas là, mettre un champ Nom_Objet dans la structure est peut-être une perte de mémoire : On peut retrouver ce champ en utilisant la valeur de la clé qui référence l'élément avec 'MapKey()'



Pour ton 2ème problème : regarde l'aide, je crois que ce que tu veux faire n'est pas possible de cette façon, mais on peut y arrivé avec des astuces :

Code : Tout sélectionner

  Valeur = 2
  
  Select Valeur
    Case 1, 2, 3
      Debug "Valeur est 1, 2 ou 3"
      
    Case 10 To 20, 30, 40 To 50
      Debug "Valeur est entre 10 et 20, égale à 30 ou entre 40 et 50"
      
    Default
      Debug "Je ne sais pas"
      
  EndSelect
comme suis :

Code : Tout sélectionner

;- Droper un objet
;_____________________________________________________________________________________________________________
drop:
Chance_drop = Random(9) + 1

Select Chance_drop
			Case 0 To 5
						Inventaire(Nbr_Objet)\Nom_Objet = Dropcommun$
			Case 0 To 4
						Inventaire(Nbr_Objet)\Nom_Objet = Droppeucommun$
			Case 0 To 2
						Inventaire(Nbr_Objet)\Nom_Objet = Droprare$
			Case 1
						Inventaire(Nbr_Objet)\Nom_Objet = Droptresrare$ 
EndSelect
Return
Sauf que de la façon dont tu l'as fait, il est impossible que le code passe ailleurs que dans le 1er choix.
Il faut changer les conditions, ou bien inverser les Cases en commençant par le Case 1.

:arrow: :mrgreen:

Re: [MUD] Inventaire léger/Sauvegarde

Publié : jeu. 07/juil./2011 16:57
par Backup

Code : Tout sélectionner

Global NewMap Inventaire.Inventaire(200) ; créé une map avec 200 slots déjà alloués. si tu prévois un nombre d'objets plus grand, change ce nombre.
pour eviter ça , je lui avait conseillé les listes Chainées !
qui a mon avis sont les mieux adapté au probleme ;)

Re: [MUD] Inventaire léger/Sauvegarde

Publié : jeu. 07/juil./2011 23:46
par graph100
Je pense qu'avec les maps, il n'y a pas de soucis ^^, en effet ce paramètre est facultatif et préréglé à 512.
Je l'ai mis à 200 car en ce moment je fait attention à la place mémoire de mes applis.
C'est un détail en gros, si on veux être précis.

Il me semble que les map sont des listes chaines sans la chaine entre éléments et indexées avec une clé, ce qui est top pour un inventaire : bcp plus facile de chercher un élément.

Re: [MUD] Inventaire léger/Sauvegarde

Publié : ven. 08/juil./2011 0:52
par Backup
graph100 a écrit : bcp plus facile de chercher un élément.
oui c'est le seul avantage des maps... :)

pour une base de donnée une liste chainé est quand meme mieux
parcequ'on peut ajouter et enlever des elements a la volée

et sans connaitre a l'avance le nombre d'elements ...

enfin ... chacun fais bien comme il veut hein .. ;)

Re: [MUD] Inventaire léger/Sauvegarde

Publié : ven. 08/juil./2011 17:09
par MonchauxantZ
Ah, merci :mrgreen:
Je précise pour Dobro ma non-utilisation des listes chaînées :)
C'est le fait que je sois Lycéen et que nous utilisons déjà les listes chaînées en TI-BASIC, donc autant apprendre autre chose ^^
Egalement la facilité et la rapidité pour la recherche d'élément rend le jeu fluide et c'est ce que je voulais :)

Je me demande également comme j'ai pu oublier les Global :?
En tous cas, merci ;)