Hi,
habe folgendes Problem:
Goldmine produziert 60 Barren die Stunde, Spieler hat um 12:00 Uhr 100 Barren auf Lager. Ok. Spieler guckt um 12:30 nach und hat nun 130 Barren auf Lager.
Klar wir berechnen delta-t und multiplizieren das mit der Produktionskapazität. Trivial, Simpel, Hosanna.
Jedoch:
Beispiel wie oben (Goldmine produziert 60, 100 auf Lager um 12:00), jedoch wird zusätzlich eine zweite Goldmine gebaut, die um 12:31:00 fertig ist.
Spieler guckt um 12:32:00 nach.
Müsste nun 133 Barren sehen.
Aber wie lasse ich da die Berechnung optimal laufen? Nota bene wenn
irgendwie auf x Planeten allerlei Schlunz (Prodgebäude) gebaut wird?
Ich meine ich bekäme das schon hin, aber die Lösungen, die mir
einfallen sind iterativ und daher O(n), ich würde aber gerne mit
O(1) auskommen.
Vorschläge anyone?
so long,
Marcel
Echtzeitberechnung - arithmetisches Problem
gepostet vor 19 Jahre, 3 Monate von marcelh
gepostet vor 19 Jahre, 3 Monate von Mudder
.. Nochmal ...
Minutenproduktion einer Goldmine: 0.25 Barren
12:00 Uhr: Letztes Ressourcenupdate
12:35 Uhr: Goldmine wird fertiggestellt
13:00 Uhr: User logt sich wieder ein und es findet das Update statt
Zuerst updaten wir die Gebäude. Dazu werden zuerst die Ressourcen bis zum Zeitpunkt der Gebäudedarstellung aktuallisiert. Sprich 35x 0.25 = 8.75 Barren.
Dann wird das Gebäude hinzugefügt was die Minutenproduktion auf 0.5 Barren/Minute erhöht. Und nun erfolgt wieder die "normale" Ressourcenaktuallisierung. 25x 0.5 = 12.5 Barren
Ergebniss: 21.25 Barren. Und dies wird bei der Useranzeige abgerundet sprich er hat nun 21 Barren mehr im Lager.
Du musst einfach immer die Zeitpunkte des letzten Updates speichern und bei Gebäudeaktuallisierungen ein Update bis zur Fertigstellung durchführen und somit mehrere einzelne Updates hintereinander durchführen.
Minutenproduktion einer Goldmine: 0.25 Barren
12:00 Uhr: Letztes Ressourcenupdate
12:35 Uhr: Goldmine wird fertiggestellt
13:00 Uhr: User logt sich wieder ein und es findet das Update statt
Zuerst updaten wir die Gebäude. Dazu werden zuerst die Ressourcen bis zum Zeitpunkt der Gebäudedarstellung aktuallisiert. Sprich 35x 0.25 = 8.75 Barren.
Dann wird das Gebäude hinzugefügt was die Minutenproduktion auf 0.5 Barren/Minute erhöht. Und nun erfolgt wieder die "normale" Ressourcenaktuallisierung. 25x 0.5 = 12.5 Barren
Ergebniss: 21.25 Barren. Und dies wird bei der Useranzeige abgerundet sprich er hat nun 21 Barren mehr im Lager.
Du musst einfach immer die Zeitpunkte des letzten Updates speichern und bei Gebäudeaktuallisierungen ein Update bis zur Fertigstellung durchführen und somit mehrere einzelne Updates hintereinander durchführen.
gepostet vor 19 Jahre, 3 Monate von Roi
Oder du bist faul....
Läßt die Minen fertigstellen....
Berechnest dann den Ertrag...
Ich denke, KEINER wird dies als Bug melden, da jeder ja ein PLUS daraus zieht *g*
Läßt die Minen fertigstellen....
Berechnest dann den Ertrag...
Ich denke, KEINER wird dies als Bug melden, da jeder ja ein PLUS daraus zieht *g*
gepostet vor 19 Jahre, 3 Monate von marcelh
Original von Mudder
Zuerst updaten wir die Gebäude.
Dann wird das Gebäude hinzugefügt
Und nun erfolgt wieder die "normale" Ressourcenaktuallisierung
...
Du musst einfach immer die Zeitpunkte des letzten Updates speichern und bei Gebäudeaktuallisierungen ein Update bis zur Fertigstellung durchführen und somit mehrere einzelne Updates hintereinander durchführen.
Aber genau das möchte ich ja gerne vermeiden, denn ich denke das kostet zuviel Rechenzeit.
ist ungefähr so wie
$sum += $_ for(1..$n);
gegen
$sum = ($n x $n+1)/2;
Meine Idee war, daß es möglich sein muß diese iterativen Prozesse
in eine Berechnungsvorschrift mit konstantem Zeitaufwand zu packen.
Also:
"Level 0" (gebäude produziert vor sich hin)
Ertrag = Produktion * Zeit
"Level 1" (level 0 + 1 geb. kommt hinzu)
Iterative Lösung:
Für alle relevanten Gebäude: DO
Ertrag += Produktion * Zeit
DONE
= O(n)!
Berechnungsvorschrift?
so long,
Marcel
gepostet vor 19 Jahre, 3 Monate von Mudder
So und jetzt sage ich offen und ehrlich: Ich hab kein Wort verstanden!
Und vor allem kapiere ich auch deinen Grundgedanken nicht..
Kannst du das auch nochmal für Nicht-Mathematik-Studenten erklären?
Und vor allem kapiere ich auch deinen Grundgedanken nicht..
Kannst du das auch nochmal für Nicht-Mathematik-Studenten erklären?
gepostet vor 19 Jahre, 3 Monate von marcelh
Original von Mudder
So und jetzt sage ich offen und ehrlich: Ich hab kein Wort verstanden!
Und vor allem kapiere ich auch deinen Grundgedanken nicht..
Kannst du das auch nochmal für Nicht-Mathematik-Studenten erklären?
Ok. Komplexitätstheorie in a Nutshell:
Beispiele
O(1) = konstante Laufzeit
O(n) = lineare Laufzeit
O(n * logn) = linear/logarithmisch
O(n^2) = quadratische Laufzeit
O(2^n) = exponentielle Laufzeit
O(1) bedeutet, daß egal wie groß/viele die Eingabeparameter sind,
die Berechnung des Endergebnisses immer gleich viel Zeit beansprucht.
Das muss nicht zwangsläufig "kurz" sein, sondern einfach nur "konstant"
Dementsprechend O(n*logn), daß ich bei n eingabeparametern eben
n*logn Operationen ausführen muss. Die besten Sortieralgorithmen
haben diese Komplexität.
O(n) ist klar, n Eingabewerte, n Berechnungen, also z.B. das
Zählen der Summe von 1 bis 100 auf die Vor-Gauss'sche Weise
Gauss hat daraus eben O(1) gemacht!
Quadratisch ist klar, z.B. die heute besten bekannten Algorithmen
für matrizenmultiplikation haben O(n^2,2), wenn man an die Sache
dämlich herangeht, hat eine Matrizenmultiplikation O(n^3) und
das ist ein gewaltiger Unterschied.
Und damit kommen wir auch schon zu den kaum praktikablen
Algorithmen, wie z.B. O(2^n) das ist z.B. das TSP - Travelling
Salesman Problem. Man geht davon aus, daß alles oberhalb O(n^8 )
mit herkömmlichen Computern unbenutzbar ist.
------------------------------------------
So. Was ich will ist eine O(1) (oder meinetwegenO(logn) ) Lösung
für dieses Ressourcenberechnungsproblem finden. Ich war vorhin
aufm Klo und habs eindeutig im Urin, daß es eine geben muss.
Es ist doch dämlich, wenn ich nur EINMAL nachsehe UND alle
Vorgänge linear sind, da was iteratives zu basteln. Dat mut nur
so hopp hopp. Weil:
Anfangsressourcen: n
Produktion pro Zeiteinheit: k
Zeiteinheiten: t
Nun wird die Produktion größer und wir sollten doch in der Lage
sein, k so zu modifizieren, daß wir an t nicht schrauben müssen.
Folglich würden wir einfach bei Endressourcen = n + k_mod * t
bleiben. Keiner kann mir erzählen, daß ich k ITERATIV approximieren
muss.
Oder doch?
so long,
Marcel
gepostet vor 19 Jahre, 3 Monate von Mudder
Ok ich als Dummer versuch das mal zu entziffern.
Du willst einen Durchschnittswert in der Produktionsvariable haben um diese beim Update nur mal der Zeit zu nehmen.
Produktion: 0,25 Barren
12:00 Uhr letztes Update
12:35 Uhr Gebäude fertig
13:00 Uhr neues Update
Es wären 35x 0,25 und 25x 0,5 Barren = Durchschnittswert 0,34517
Geh ich richtig in der Annahme, dass du nun eine Formel suchst die genau dies - fortlaufend - berechnet und immer den aktuellen Aktuallisierungswert ausgibt?
Du willst einen Durchschnittswert in der Produktionsvariable haben um diese beim Update nur mal der Zeit zu nehmen.
Produktion: 0,25 Barren
12:00 Uhr letztes Update
12:35 Uhr Gebäude fertig
13:00 Uhr neues Update
Es wären 35x 0,25 und 25x 0,5 Barren = Durchschnittswert 0,34517
Geh ich richtig in der Annahme, dass du nun eine Formel suchst die genau dies - fortlaufend - berechnet und immer den aktuellen Aktuallisierungswert ausgibt?
gepostet vor 19 Jahre, 3 Monate von marcelh
Original von Mudder
Geh ich richtig in der Annahme, dass du nun eine Formel suchst die genau dies - fortlaufend - berechnet und immer den aktuellen Aktuallisierungswert ausgibt?
So ziemlich. Allerdings eben nicht fortlaufend (iterativ, numerische approx.), sondern analytisch genau einmal bei Sichtung durch Player. Bummm batz - umgehend.
so long,
Marcel
gepostet vor 19 Jahre, 3 Monate von BLUESCREEN
Original von marcelh
Ich meine ich bekäme das schon hin, aber die Lösungen, die mir
einfallen sind iterativ und daher O(n), ich würde aber gerne mit
O(1) auskommen.
Was besseres als O(n) fällt mir so auch nicht ein - ich frage mich, ob das überhaupt möglich ist!?
Allerdings ist das IMHO nicht schlimm, denn was wirklich Zeit kostet sind die Datenbankabfragen. Die wiederum sind an sich auch O(n), aber ihre Anzahl ist O(1) und das ist schonmal sehr gut.
Ich habe zwar noch nie ein Echtzeit-BG entwickelt, aber ich würde das so lösen:
Der Zeitpunkt des letzten Updates ist bekannt, nennen wir ihn $u.
Was wir nun brauchen ist die Produktionszeit $p.
Beim Update zum Zeitpunkt $t wird nun die Liste der fertigen Gebäude durchgegangen und für jedes Gebäude (hier kommt unser O(n) ist Spiel), von dem natürlich die in der Vergangenheit liegende Fertigstellungszeit $f bekannt ist, wird folgendes berechnet:
$p+=(($u>$f)?($t-$u)$t-$f));
Am Ende folgt ein
$gesamtproduktion=$p*$produktion_pro_zeiteinheit;
Wie gesagt O(n), aber was solls, auf die DB-Last würde ich wesentlich mehr achten, als auf die paar simplen Berechnungen...
gepostet vor 19 Jahre, 3 Monate von marcelh
Original von BLUESCREEN
Was besseres als O(n) fällt mir so auch nicht ein - ich frage mich, ob das überhaupt möglich ist!?
Na ich hoffe.
Allerdings ist das IMHO nicht schlimm, denn was wirklich Zeit kostet sind die Datenbankabfragen. Die wiederum sind an sich auch O(n), aber ihre Anzahl ist O(1) und das ist schonmal sehr gut.
Die Datenbankabfragen spielen bei uns eine untergeordnete Rolle.
Mit der richtigen Technologie sind die nämlich praktisch eliminiert.
Abgesehen davon ist eine Datenbankabfrage nahezu immer O(logn),
weil siehe B-Trees.
Ich habe zwar noch nie ein Echtzeit-BG entwickelt, aber ich würde das so lösen:
...
Beim Update zum Zeitpunkt $t wird nun die Liste der fertigen Gebäude durchgegangen und für jedes Gebäude ...
Wie gesagt O(n), aber was solls, auf die DB-Last würde ich wesentlich mehr achten, als auf die paar simplen Berechnungen...
Naja eben. O(n). DB ist mir wirklich wurst, weil wie gesagt bei uns
"so schnell wie aus'm RAM". Aber ich habe hier in der Spezifikation
stehen, daß das Ding 1 mio Player aushalten muss und da sollte man
nun wirklich auf jeden Pups achten.
so long,
Marcel
gepostet vor 19 Jahre, 3 Monate von Drezil
Hmmm ... ich habs auch im gefühl, dass es da ne lösung gibt .. nur mir fällt bis dato auch nur der iterative weg ein ..
bei mir ist das prob noch nen bissl komplexer ..
a) produktion (sowohl pos. als auch negtiv)
b) bauaufträge (temporäre neg prod, da rohstoffe erst zur bauzeit abgezogen werden)
somit hab ich dein o.g. problem gleich in mehreren variationen..
was die berechnung bei mir dann aber auch noch berückichtigen müsste ist, dass man bauaufträge auch temporär anhalten kann oder alternativ die neg. produktion runtergefahren wird.. geht das auch in einer rechnung? ich bezweifel es ...
mein ansatz ist, das stück für stück zu machen, also immer soweit berechnen, bis ein neues ereignis eintritt, die prod neu berechnen, ggf. maßnahmen ergreifen (stoppen, etc.) und dann weiterberechnen ..
kann man sicher noch optimieren den ansatz und deine problemlösung würd mir schon arg weiterhelfen..
bei mir ist das prob noch nen bissl komplexer ..
a) produktion (sowohl pos. als auch negtiv)
b) bauaufträge (temporäre neg prod, da rohstoffe erst zur bauzeit abgezogen werden)
somit hab ich dein o.g. problem gleich in mehreren variationen..
was die berechnung bei mir dann aber auch noch berückichtigen müsste ist, dass man bauaufträge auch temporär anhalten kann oder alternativ die neg. produktion runtergefahren wird.. geht das auch in einer rechnung? ich bezweifel es ...
mein ansatz ist, das stück für stück zu machen, also immer soweit berechnen, bis ein neues ereignis eintritt, die prod neu berechnen, ggf. maßnahmen ergreifen (stoppen, etc.) und dann weiterberechnen ..
kann man sicher noch optimieren den ansatz und deine problemlösung würd mir schon arg weiterhelfen..
gepostet vor 19 Jahre, 2 Monate von BjoernLilleike
Ich kann das Problem auch nicht wirklich gut nachvollziehen.
Meine These dazu ist: Sei froh, dass der Spieler wirklich nur so selten reinguckt..
Mir würde tatsächlich eher Sorgen machen, dass da Gebäude womöglich schon seit Stunden fertig sind ohne dass das System dies merkt.
Daher würde ich grundsätzlich mit der Fertigstellung eines Bauwerks ein Update machen - ob der Spieler nun guckt oder nicht. Sonst hast du da böse Abhängigkeiten drin, die dir nochmal auf die Füße fallen können. Wenn beispielsweise irgendwann ein anderer Spieler den Ort ausspionieren können soll, sieht er nur die eine Goldmine, obwohl die andere womöglich schon fertig ist. Oder du müsstest auch bei Spionage eine Update-Prüfung machen, was am Ende sicher teurer kommt als bei einer bekannten Änderung zu prüfen.
Meine These dazu ist: Sei froh, dass der Spieler wirklich nur so selten reinguckt..
Mir würde tatsächlich eher Sorgen machen, dass da Gebäude womöglich schon seit Stunden fertig sind ohne dass das System dies merkt.
Daher würde ich grundsätzlich mit der Fertigstellung eines Bauwerks ein Update machen - ob der Spieler nun guckt oder nicht. Sonst hast du da böse Abhängigkeiten drin, die dir nochmal auf die Füße fallen können. Wenn beispielsweise irgendwann ein anderer Spieler den Ort ausspionieren können soll, sieht er nur die eine Goldmine, obwohl die andere womöglich schon fertig ist. Oder du müsstest auch bei Spionage eine Update-Prüfung machen, was am Ende sicher teurer kommt als bei einer bekannten Änderung zu prüfen.
gepostet vor 19 Jahre, 2 Monate von schokofreak
Stand 1:
10 Produktionsgebäude; Produktion 100 p.M oda was auch immer
Lager: 1000
Stand 2:
T + 2 Prod. Einheiten
10 Produktionsgebäude
Lager 1200
+ 1 Auftrag kommt hinzu... dauert 10 Prod. Einheiten
Stand 2b:
T+2 Prod. Einheiten
11 Produktionswerke (wovon 1 noch für 10 Runden im Bau)
Produktion 110 p.M; das neue Werk- welches erst in 10 Runden betriebsbereit ist wird schon einberechnet.
Lager 1200 - 1000 d. Produktion = 200
200 - 10 Runden bauzeit a 10 Produktion = 100
OFFSET (Theorie; Praxis) von +100
Stand 3:
T+7 Produ. Einheiten
11 Produktionswerke (wovon 1 noch für 10 Runden im Bau)
Produktion 110 p.M; 10 Werke / 1 noch in Bau
Lager = 100 + 11 * 5 = 155
OFFSET (Theorie; Praxis) von +50
Stand 4:
T+12 Produ. Einheiten
11 Produktionswerke
Produktion 110 p.M
Lager = 210
OFFSET = 0
Fazit: Auf dem Server gibt das ganze EINE Berechnung, welche Realtime ausgeführt werden kann.
Der Rest passiert auf dem Client; Ist reine Darstellung...
Der Client hat ja kein Problem den Offset 10 minuten lang mit der Produktionsmenge zu verrechnen.
Da der Client dafür zuständig ist, dass nur Aufträge bei genügend (EFFEKTIVEN) ress ausgeführt werden kann...
Hat der Server ne einfache berechnung:
1. Genug Ress vorhanden?
-> Ja: Bauen
-> Nein: Ist da ein Ress- Offset vorhanden Durch zeitlcih versetzten Bau
2. Wenn Offset: Genügend grosser Offset?
-> Ja: Bauen
-> Nein: Bauen
Das ganze benötigt weder Cron- Job ncoh sonstige Fehleranfällige Konstrukte.
Da normalerweise in 90 % aller Fälle auch nicht dermassen "genau" produziert wird dass die separate Offset- Berechnung bei weitgeren Bauaufträgen ausgeführt werden muss; Ist die benötigte Rechenzeit auch dort minimal. (n.B. kann die Quote an Offset- Bauten genial als Script- Protection- Auswerung Warscheinlcihkeit genutzt werden)
Benötigt nur ein bisschen Darstellungslogik.
Da sieht ihr den grund, wieso ich nicht begreiffe wieso ihr alle solch komische konstrukte mit Crons baut.
Gruss
10 Produktionsgebäude; Produktion 100 p.M oda was auch immer
Lager: 1000
Stand 2:
T + 2 Prod. Einheiten
10 Produktionsgebäude
Lager 1200
+ 1 Auftrag kommt hinzu... dauert 10 Prod. Einheiten
Stand 2b:
T+2 Prod. Einheiten
11 Produktionswerke (wovon 1 noch für 10 Runden im Bau)
Produktion 110 p.M; das neue Werk- welches erst in 10 Runden betriebsbereit ist wird schon einberechnet.
Lager 1200 - 1000 d. Produktion = 200
200 - 10 Runden bauzeit a 10 Produktion = 100
OFFSET (Theorie; Praxis) von +100
Stand 3:
T+7 Produ. Einheiten
11 Produktionswerke (wovon 1 noch für 10 Runden im Bau)
Produktion 110 p.M; 10 Werke / 1 noch in Bau
Lager = 100 + 11 * 5 = 155
OFFSET (Theorie; Praxis) von +50
Stand 4:
T+12 Produ. Einheiten
11 Produktionswerke
Produktion 110 p.M
Lager = 210
OFFSET = 0
Fazit: Auf dem Server gibt das ganze EINE Berechnung, welche Realtime ausgeführt werden kann.
Der Rest passiert auf dem Client; Ist reine Darstellung...
Der Client hat ja kein Problem den Offset 10 minuten lang mit der Produktionsmenge zu verrechnen.
Da der Client dafür zuständig ist, dass nur Aufträge bei genügend (EFFEKTIVEN) ress ausgeführt werden kann...
Hat der Server ne einfache berechnung:
1. Genug Ress vorhanden?
-> Ja: Bauen
-> Nein: Ist da ein Ress- Offset vorhanden Durch zeitlcih versetzten Bau
2. Wenn Offset: Genügend grosser Offset?
-> Ja: Bauen
-> Nein: Bauen
Das ganze benötigt weder Cron- Job ncoh sonstige Fehleranfällige Konstrukte.
Da normalerweise in 90 % aller Fälle auch nicht dermassen "genau" produziert wird dass die separate Offset- Berechnung bei weitgeren Bauaufträgen ausgeführt werden muss; Ist die benötigte Rechenzeit auch dort minimal. (n.B. kann die Quote an Offset- Bauten genial als Script- Protection- Auswerung Warscheinlcihkeit genutzt werden)
Benötigt nur ein bisschen Darstellungslogik.
Da sieht ihr den grund, wieso ich nicht begreiffe wieso ihr alle solch komische konstrukte mit Crons baut.
Gruss
gepostet vor 19 Jahre, 2 Monate von BLUESCREEN
Und wie siehts aus, wenn mehrere Gebäude im Bau sind?
gepostet vor 19 Jahre, 2 Monate von schokofreak
Auf dem Server hast du immer nur die einzig alleinige Berechnung:
- Bestand
- Zeitpunkt des Bestandes
- Zuwachs pro Zeiteinheit
Wenn 1 Gebäude in Auftrag gegeben wird, macht der Server das:
- Bestand um die Menge (Kosten) des Auftrages Reduzieren
- Bestand um die Menge reduzieren, welche das Gebäude bis zur Fertigstellung produzieren würde (also ZuwachsDurchGebäude * ZeitEinheitBisVertigstellung)
Sprich wenn da 10 Gebäude zu verschiedenen zeiten parallel in Auftrag gegeben werden... dann hat der Server genau gar nix zu rechnen.
Für die Darstellung sieht die Rechnung so aus:
Wir haben Bestand + Zeitpunkt Bestand + zeitDelta * ZuwachsProZeiteinheit. Das ist OHNE Berechnung des Offsets.
Nun iterieren wir durch jedes Gebäude im Bau:
Pro gebäude zählen wir vom obigen Wert ab:
(GesammtProduktionsZeit - geleisteteProduktionszeit) * ProduktionDesGebäudesProEinheit
Dann funktioniert das ganze mit beliebig vielen Gebäuden. Wer sich in statistik auskennt, kann das ganze noch viel stärker zusammenkürzen; schlussendlich kriegt man das ganze auf mehr oder weniger 2, 3 Divisionen / Multiplikationen welche keine Rechenzeit benötigen.
Wem das immer noch zu viel Rechenbelastung ist: Schmeisst die Berechnung in den Client (JavaScript) dann ist das ganze erst noch immer aktuell und man kann dem Benutzer schöne Charts zeigen.
Gruss
- Bestand
- Zeitpunkt des Bestandes
- Zuwachs pro Zeiteinheit
Wenn 1 Gebäude in Auftrag gegeben wird, macht der Server das:
- Bestand um die Menge (Kosten) des Auftrages Reduzieren
- Bestand um die Menge reduzieren, welche das Gebäude bis zur Fertigstellung produzieren würde (also ZuwachsDurchGebäude * ZeitEinheitBisVertigstellung)
Sprich wenn da 10 Gebäude zu verschiedenen zeiten parallel in Auftrag gegeben werden... dann hat der Server genau gar nix zu rechnen.
Für die Darstellung sieht die Rechnung so aus:
Wir haben Bestand + Zeitpunkt Bestand + zeitDelta * ZuwachsProZeiteinheit. Das ist OHNE Berechnung des Offsets.
Nun iterieren wir durch jedes Gebäude im Bau:
Pro gebäude zählen wir vom obigen Wert ab:
(GesammtProduktionsZeit - geleisteteProduktionszeit) * ProduktionDesGebäudesProEinheit
Dann funktioniert das ganze mit beliebig vielen Gebäuden. Wer sich in statistik auskennt, kann das ganze noch viel stärker zusammenkürzen; schlussendlich kriegt man das ganze auf mehr oder weniger 2, 3 Divisionen / Multiplikationen welche keine Rechenzeit benötigen.
Wem das immer noch zu viel Rechenbelastung ist: Schmeisst die Berechnung in den Client (JavaScript) dann ist das ganze erst noch immer aktuell und man kann dem Benutzer schöne Charts zeigen.
Gruss
gepostet vor 19 Jahre, 2 Monate von Drezil
und was ist, wenn die ress für das geb nciht am anfang, sondern kontinuirlich abgezogen werden?
was ist, wenn der ausbau gestoppt wird (sei es, weil der user das will, oder weil grad der planet geplündert wird und keine ress mehr da sind um die kontinuirlichen kosten zu begleichen)?
was ist, wenn der ausbau gestoppt wird (sei es, weil der user das will, oder weil grad der planet geplündert wird und keine ress mehr da sind um die kontinuirlichen kosten zu begleichen)?
gepostet vor 19 Jahre, 2 Monate von schokofreak
In dem Fall hast du eine neue Art vom Game erschaffen, welche ich bis jetzt noch nicht gesehen habe.
Dann benötigt man halt ein bisschen andere überlegungen und andere Codes... (is ja logisch, oda?)
Dann benötigt man halt ein bisschen andere überlegungen und andere Codes... (is ja logisch, oda?)
gepostet vor 19 Jahre, 2 Monate von Chojin
Ich hab jetzt zwar nicht alles mitgelesen, aber ich hab das problem eingedämmt. Jeder aufruf der bauwerk/forschungs/wasauchimmer seite überprüft ob eine aktion vollendet wurde und führt dann ein script aus, welches die neuen ertragswerte je tag in die datenbank schreibt.
nachdem es aber sein kann, dass sich jemand für 5 tage nicht einloggt und in dieser zeit keine rohstoffe bekommt, gibt es zusätzlich einen cronjob der alle 5 minuten die werte bei allen spielern prüft und die entsprechenden massnahmen einleitet. das ist naturlich, abhängig von der bau/forschungs/wasauchimmerzeit und der anzahl der spieler viel oder wenig zu tun für den Server.
reg4rds
chojin
nachdem es aber sein kann, dass sich jemand für 5 tage nicht einloggt und in dieser zeit keine rohstoffe bekommt, gibt es zusätzlich einen cronjob der alle 5 minuten die werte bei allen spielern prüft und die entsprechenden massnahmen einleitet. das ist naturlich, abhängig von der bau/forschungs/wasauchimmerzeit und der anzahl der spieler viel oder wenig zu tun für den Server.
reg4rds
chojin
gepostet vor 19 Jahre, 2 Monate von Mudder
Ich habe heute Abend rumexperimentiert und auch wenn es nicht so funktioniert wie ich mir das gewünscht hab (nämlich mit nur einem Update-Query) ist dies evtl. doch für einige ein Interessantes System.
Meine Methode benötigt 1 Update-Query mit einem SubQuery sowie einem "einfachen" Update-Query.
Ich habe hier mal ein einfaches Beispiel, welches Ihr am besten mal einrichtet (sofern Ihr es testen wollt).
`id` int(3) NOT NULL auto_increment,
`user` tinyint(2) NOT NULL default '0',
`name` varchar(30) collate latin1_general_ci NOT NULL default '',
`update` int(35) NOT NULL default '0',
`produktion` float(4,2) NOT NULL default '0.00',
`ressource` varchar(20) collate latin1_general_ci NOT NULL default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
CREATE TABLE `lager` (
`user` tinyint(2) NOT NULL default '0',
`ressource` varchar(20) collate latin1_general_ci NOT NULL default '',
`lager` decimal(20,4) NOT NULL default '0.0000'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
Dies sind die beiden Tabellen. Es wird jedes Gebäude einzelnd gespeichert, was bei komplexeren Spielen sicher auch den Vorteil hat, dass man individuelle Werte wie Produktionsauslastung oder Standort mit einsetzen kann.
Die zweite Tabelle speichert de Lagerbestände der User.. Alle einzelnd.. was man dann auch noch mit Standorten erweitern kann.
INSERT INTO `buildings` VALUES (2, 1, 'Goldmine 2', unix_timestamp(), 0.10, 'gold');
INSERT INTO `buildings` VALUES (3, 1, 'Eisenmine 1', unix_timestamp(), 0.20, 'eisen');
INSERT INTO `buildings` VALUES (4, 2, 'Goldmine 1', unix_timestamp(), 0.10, 'gold');
INSERT INTO `buildings` VALUES (5, 2, 'Eisenmine 1', unix_timestamp(), 0.20, 'eisen');
INSERT INTO `lager` VALUES (1, 'gold', 0.0000);
INSERT INTO `lager` VALUES (1, 'eisen', 0.0000);
INSERT INTO `lager` VALUES (2, 'gold', 0.0000);
INSERT INTO `lager` VALUES (2, 'eisen', 0.0000);
Dies sind nun mal ein paar Beispieldaten. 2 User, mit ein paar Minen. als sekündlicher Produktionswert sind nun 0.1 bzw. 0.2 eingetragen..
UPDATE buildings as b SET b.update = unix_timestamp() WHERE b.user = 1 AND b.update < unix_timestamp();
So nun aktuallisieren wir die Ressoucen im Lager des Users 1 (hier sollte man dann natürlich eine Variable verwenden) indem man mit dem Subquery die Differenz aus dem letzten Update und der aktuellen Zeit mal dem Produktionswert nimmt. Der Wert wird dann zum Lager hinzugefügt.
Ein Neubau wird mit dem timestamp eingetragen, zudem das Gebäude fertiggestellt wird. Dadurch ist der timestamp höher als der aktuelle und diese Gebäude werden aus der Aktuallisierung ausgeschlossen. Ist das Gebäude jedoch fertig, wird es sofort in die Produktionsaktuallisierung aufgenommen.
Das 2. Update dient dazu, dass der neue Aktuallisierungszeitpunkt gespeichert wird. (Dies liess sich leider nicht in den 1. Updatebefehl mit aufnehmen, da der Subquery die Tabelle blockiert)
Was meint Ihr? Verwendbar?
Meine Methode benötigt 1 Update-Query mit einem SubQuery sowie einem "einfachen" Update-Query.
Ich habe hier mal ein einfaches Beispiel, welches Ihr am besten mal einrichtet (sofern Ihr es testen wollt).
CREATE TABLE `buildings` (
`id` int(3) NOT NULL auto_increment,
`user` tinyint(2) NOT NULL default '0',
`name` varchar(30) collate latin1_general_ci NOT NULL default '',
`update` int(35) NOT NULL default '0',
`produktion` float(4,2) NOT NULL default '0.00',
`ressource` varchar(20) collate latin1_general_ci NOT NULL default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
CREATE TABLE `lager` (
`user` tinyint(2) NOT NULL default '0',
`ressource` varchar(20) collate latin1_general_ci NOT NULL default '',
`lager` decimal(20,4) NOT NULL default '0.0000'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
Dies sind die beiden Tabellen. Es wird jedes Gebäude einzelnd gespeichert, was bei komplexeren Spielen sicher auch den Vorteil hat, dass man individuelle Werte wie Produktionsauslastung oder Standort mit einsetzen kann.
Die zweite Tabelle speichert de Lagerbestände der User.. Alle einzelnd.. was man dann auch noch mit Standorten erweitern kann.
INSERT INTO `buildings` VALUES (1, 1, 'Goldmine 1', unix_timestamp(), 0.10, 'gold');
INSERT INTO `buildings` VALUES (2, 1, 'Goldmine 2', unix_timestamp(), 0.10, 'gold');
INSERT INTO `buildings` VALUES (3, 1, 'Eisenmine 1', unix_timestamp(), 0.20, 'eisen');
INSERT INTO `buildings` VALUES (4, 2, 'Goldmine 1', unix_timestamp(), 0.10, 'gold');
INSERT INTO `buildings` VALUES (5, 2, 'Eisenmine 1', unix_timestamp(), 0.20, 'eisen');
INSERT INTO `lager` VALUES (1, 'gold', 0.0000);
INSERT INTO `lager` VALUES (1, 'eisen', 0.0000);
INSERT INTO `lager` VALUES (2, 'gold', 0.0000);
INSERT INTO `lager` VALUES (2, 'eisen', 0.0000);
Dies sind nun mal ein paar Beispieldaten. 2 User, mit ein paar Minen. als sekündlicher Produktionswert sind nun 0.1 bzw. 0.2 eingetragen..
UPDATE lager AS l, buildings AS b SET l.lager = l.lager + (SELECT sum(b2.produktion * (unix_timestamp() - b2.update)) FROM buildings AS b2 WHERE b2.update < unix_timestamp() AND b2.user = 1 AND b2.ressource = l.ressource ) WHERE b.update < unix_timestamp() AND l.user = 1 AND l.ressource = b.ressource AND l.user = b.user;
UPDATE buildings as b SET b.update = unix_timestamp() WHERE b.user = 1 AND b.update < unix_timestamp();
So nun aktuallisieren wir die Ressoucen im Lager des Users 1 (hier sollte man dann natürlich eine Variable verwenden) indem man mit dem Subquery die Differenz aus dem letzten Update und der aktuellen Zeit mal dem Produktionswert nimmt. Der Wert wird dann zum Lager hinzugefügt.
Ein Neubau wird mit dem timestamp eingetragen, zudem das Gebäude fertiggestellt wird. Dadurch ist der timestamp höher als der aktuelle und diese Gebäude werden aus der Aktuallisierung ausgeschlossen. Ist das Gebäude jedoch fertig, wird es sofort in die Produktionsaktuallisierung aufgenommen.
Das 2. Update dient dazu, dass der neue Aktuallisierungszeitpunkt gespeichert wird. (Dies liess sich leider nicht in den 1. Updatebefehl mit aufnehmen, da der Subquery die Tabelle blockiert)
Was meint Ihr? Verwendbar?
gepostet vor 19 Jahre, 2 Monate von schokofreak
@ Mudder: ein klares Nein.
1. Das ganze muss entweder via Cron- Jobs regelmässig bei allen Accounts ausgeführt werden.
Ein Cron, welcher bei 1Mio User abläuft ist schlichtwegs undenkbar; Du müstes das Update SÄMTLICHER WERKE in einen SQL Update packen (was sichier möglich wäüre)
2. Wenn das ganze nicht Cron- Orientiert ist; Sondern primäer Aktions- Orientiert...
Dann hast du es nicht im griff, wie oft das ganze durchgeführt wird. Sprich sehr fleissige /überfleissie User) werden nicht ausgebremst. Zusätzlich ermöglicht das ganze mti einem Herumspielen der Request welche das Auslösen böse cheats. Es ist sowohl möglich, dass jemand unendlich Ress kriegt, als auch dass jemand nie mehr Ress kriegt (Rundungsproblem).
Deshalb 1 Spezifikation für ein System dass grosse Last aushält.
- Es darf KEINEN Cronjob geben.
- Eine Anzeige muss ohne Aktualisierung der Daten in der DB möglich sein. Sprich select; plus, minus, mal geteilt... -> ergeben Ausgabe
- Eine Abbuchung muss solange wie möglich Ohne weiterführendes DB Update / Lagerstandberechnung durchgeführt werden können. Das verringert einerseitz die Last. Viel wichtiger aber verringert es die Rundungsprobleme.
Sprich... SOLANGE der Bestand im lager zu Zeitpunkt X grösser als der auszugebende Preis ist.
Dann wird der Bestand rückwirkend um die Menge minimiert. OHNE den Bestand heute zu berechnen.
Fazit:
- Darstellung = 1 Select
- Abbuchung v. Ressourcen = 50 % der Fälle 1 Select / 1 Update ohne Berechnung; 50 % der Fälle 1 Select / 1 darauf basierende Komplettberechnung mit Update
Was dir automatisch auch die "Produktion" der WErke nach deinem System verhindert.
Gruss
1. Das ganze muss entweder via Cron- Jobs regelmässig bei allen Accounts ausgeführt werden.
Ein Cron, welcher bei 1Mio User abläuft ist schlichtwegs undenkbar; Du müstes das Update SÄMTLICHER WERKE in einen SQL Update packen (was sichier möglich wäüre)
2. Wenn das ganze nicht Cron- Orientiert ist; Sondern primäer Aktions- Orientiert...
Dann hast du es nicht im griff, wie oft das ganze durchgeführt wird. Sprich sehr fleissige /überfleissie User) werden nicht ausgebremst. Zusätzlich ermöglicht das ganze mti einem Herumspielen der Request welche das Auslösen böse cheats. Es ist sowohl möglich, dass jemand unendlich Ress kriegt, als auch dass jemand nie mehr Ress kriegt (Rundungsproblem).
Deshalb 1 Spezifikation für ein System dass grosse Last aushält.
- Es darf KEINEN Cronjob geben.
- Eine Anzeige muss ohne Aktualisierung der Daten in der DB möglich sein. Sprich select; plus, minus, mal geteilt... -> ergeben Ausgabe
- Eine Abbuchung muss solange wie möglich Ohne weiterführendes DB Update / Lagerstandberechnung durchgeführt werden können. Das verringert einerseitz die Last. Viel wichtiger aber verringert es die Rundungsprobleme.
Sprich... SOLANGE der Bestand im lager zu Zeitpunkt X grösser als der auszugebende Preis ist.
Dann wird der Bestand rückwirkend um die Menge minimiert. OHNE den Bestand heute zu berechnen.
Fazit:
- Darstellung = 1 Select
- Abbuchung v. Ressourcen = 50 % der Fälle 1 Select / 1 Update ohne Berechnung; 50 % der Fälle 1 Select / 1 darauf basierende Komplettberechnung mit Update
Was dir automatisch auch die "Produktion" der WErke nach deinem System verhindert.
Gruss
gepostet vor 19 Jahre, 2 Monate von Mudder
Hä?
Ich verstehe dein Problem nicht...
1. Cronjob habe ich nicht geplant, sondern Aktionsbedingte Aktuallisierung.
2. (Über-)Fleissige Spieler haben da keinen Vorsprung und cheaten seh ich auch keinen Ansatz,
Es wird dem Lager die Summe hinzugefügt, die das Gebäude produziert * der Zeitdifferenz zwischen dem letzten Update und der aktuellen Zeit.
Wie soll man da cheaten? Der Spieler kann das sekündlich aktuallisieren und es wird der sekündliche Wert hinzuaddiert. So und mit dem runden, daher werden ja auch Nachkommastellen gespeichert und dem Spieler werden nur die ganzen Barren angezeigt.. (bei 21.95135 sind das dann nur 21).
Also erkläre mir doch bitte wo du da eine Cheatmöglichkeit siehst!
Ich verstehe dein Problem nicht...
1. Cronjob habe ich nicht geplant, sondern Aktionsbedingte Aktuallisierung.
2. (Über-)Fleissige Spieler haben da keinen Vorsprung und cheaten seh ich auch keinen Ansatz,
Es wird dem Lager die Summe hinzugefügt, die das Gebäude produziert * der Zeitdifferenz zwischen dem letzten Update und der aktuellen Zeit.
Wie soll man da cheaten? Der Spieler kann das sekündlich aktuallisieren und es wird der sekündliche Wert hinzuaddiert. So und mit dem runden, daher werden ja auch Nachkommastellen gespeichert und dem Spieler werden nur die ganzen Barren angezeigt.. (bei 21.95135 sind das dann nur 21).
Also erkläre mir doch bitte wo du da eine Cheatmöglichkeit siehst!
gepostet vor 19 Jahre, 2 Monate von schokofreak
Das Problem ist das runden. Da du nicht unendlich Nachkommastellen hast.
Gruss
Gruss
gepostet vor 19 Jahre, 2 Monate von Mudder
Tschuldigung, aber deswegen die Methode als absolut unbrauchbar zu erklären finde ich doch deutlich übertrieben.
Ok wenns nun darum geht minütlich ein Barren Gold zu produzieren, dann ist es mit einem Produktionswert von 0,016+E Problematisch. Aber wenn man man nun sagt, dass das Gebäude sekündlich 0,0166 (= 0.996/Minute), dann kann damit trotzdem nicht "gecheatet" werden, da bei jedem User Sekündlich nur 0.966 gutgeschrieben wird.. und was du an Nachkommastellen brauchst ist ne Sache was du beim Produktionswert eingibst! Wenn Sekündlich 0.1 hinzugefügt wird, brauchst du auch im Lager nur eine Nachkommastelle.. gibst du als Produktionswert 0.568963 ein brauchst aber auch im Lager "nur" 6 Nachkommastellen. Im Script wird nirgendwo etwas geteilt und folglich wird der Nachkommastellenverbrauch auch nicht steigen.
Und die 0.996/Minute das ist dann nur ein Problem der Darstellungsweise im Spiel. Da das System für das "einfache" Stufenausbausystem ungeeignet ist entfällt es eh OGame-Spieler klar zu machen, dass sie evtl. mal eine Sekunde länger warten müssen. Und für BGs welche auf Details setzen wird es kein großes Problem sein wenn man die Produktionswerte einem gewissen Zeitmuster anzupassen und dies dem Spieler zu präsentieren.
Also tut mir wirklich leid, aber ich sehe dein Problem einfach nicht ...
Ok wenns nun darum geht minütlich ein Barren Gold zu produzieren, dann ist es mit einem Produktionswert von 0,016+E Problematisch. Aber wenn man man nun sagt, dass das Gebäude sekündlich 0,0166 (= 0.996/Minute), dann kann damit trotzdem nicht "gecheatet" werden, da bei jedem User Sekündlich nur 0.966 gutgeschrieben wird.. und was du an Nachkommastellen brauchst ist ne Sache was du beim Produktionswert eingibst! Wenn Sekündlich 0.1 hinzugefügt wird, brauchst du auch im Lager nur eine Nachkommastelle.. gibst du als Produktionswert 0.568963 ein brauchst aber auch im Lager "nur" 6 Nachkommastellen. Im Script wird nirgendwo etwas geteilt und folglich wird der Nachkommastellenverbrauch auch nicht steigen.
Und die 0.996/Minute das ist dann nur ein Problem der Darstellungsweise im Spiel. Da das System für das "einfache" Stufenausbausystem ungeeignet ist entfällt es eh OGame-Spieler klar zu machen, dass sie evtl. mal eine Sekunde länger warten müssen. Und für BGs welche auf Details setzen wird es kein großes Problem sein wenn man die Produktionswerte einem gewissen Zeitmuster anzupassen und dies dem Spieler zu präsentieren.
Also tut mir wirklich leid, aber ich sehe dein Problem einfach nicht ...
gepostet vor 19 Jahre, 2 Monate von Chojin
ich umgehe das aufgeführte Problem...
weil meine Minen erst dann mehr produzieren wenn auch mehr Arbeiter in der Mine schuften... und diese müssen erstmal vom Spieler zugewiesen werden, damit die Produktion steigt
reg4rds
chojin
weil meine Minen erst dann mehr produzieren wenn auch mehr Arbeiter in der Mine schuften... und diese müssen erstmal vom Spieler zugewiesen werden, damit die Produktion steigt
reg4rds
chojin
gepostet vor 19 Jahre, 2 Monate von Kampfhoernchen
Warum schreibst du von mir ab?