tetr.js development thread

Started by simonlc, March 17, 2013, 10:49:15 AM

Previous topic - Next topic

farter

a simple problem..
ARR set to 1 and works as it's 2...

yeah seems frame counting is always a problem..
in the code of nullpomino, i found the numbers on every speed (or say delay) table smaller than those on wiki by just 1.......
too many times one says that one other is inaccurate, one frame more, or one less, etc.
and i had no idea about how long the das time is, which is used by me on nullpo now....
100ms or 85ms...
lol

another problem, any skin/BG change doesn't take effect until the window gets resized... i tried on chromium, linux.

and i gotta playing this a lot recently.

simonlc

#91
So I updated the game a bit, I've fixed most of the lag in Firefox by pre rendering the block skins as images and drawing those onto the screen. This saves it from having to render a new block every single time at 60fps. The 20G bug is fixed, and and I've done some other minor improvements. I'll have a lot of free time this week, so hopefully I can scratch off everything on this giant todo list I have.

@farter, yes I have yet to make the changes reflect instantly, that should be out in the next update.

simonlc

Quote from: Integration
The input of a certain time is written to one variable. If you interprete that variable as a binary number, then
  • its last digit tells you, if your hard drop key is pressed
  • its 2nd last digit tells you, if your soft drop key is pressed
  • its 3rd last digit tells you, if your left movement key is pressed
  • its 4th last digit tells you, if your right movement key is pressed
  • its 5th last digit tells you, if your rotate counterclockwise key is pressed
  • ... and so on ...
If the current input is different from the last frame, its value and frame number is stored to an array, which is written to the replay file at the end of the game. In the replay file, you'll find lines like those:

0.r.108=4
0.r.114=20
0.r.119=21
0.r.122=5
0.r.125=4
0.r.132=5
0.r.134=1
0.r.138=9
0.r.140=8
0.r.144=24
0.r.148=28
0.r.151=21
0.r.152=17
0.r.153=1
0.r.159=0
0.r.166=1

Those keys are pressed in the corresponding frames:

108-113: left
114-118: left, rotate ccw
119-121: left, rotate ccw, drop
122-124: left, drop
125-131: left
132-133: left, drop
134-137: drop
138-139: right, drop
140-143: right
144-147: right, rotate ccw
148-150: left, right, rotate ccw
151-151: drop, left, rotate ccw
152-152: drop, rotate ccw
153-158: drop
159-155: no key pressed
156-???: drop

[fumen]110@7eLOki2qb2kBvqbvaBKsbSubytbynBDnbDhBAAA[/fumen]
I'm looking at the replay files right now, and it doesn't seem to be based on the frame index, but rather the milliseconds elapsed since the last key. Would that be correct?

Here's an example of me just mashing my hard drop key until I lock out.

0.r.126=1
0.r.124=0
0.r.118=1
0.r.116=0
0.r.112=1
0.r.111=0
0.r.103=1
0.r.101=0
0.r.98=1
0.r.96=0
0.r.89=1
0.r.87=0
0.r.80=1
0.r.78=0
0.r.75=1
0.r.73=0
0.r.57=1
0.r.53=0
0.r.42=1
0.r.35=0
0.r.34=1
0.r.30=0
0.r.24=1
0.r.194=1
0.r.191=0
0.r.187=1
0.r.186=0
0.r.183=1
0.r.180=0
0.r.176=1
0.r.166=0
0.r.163=1
0.r.148=0
0.r.144=1
0.r.142=0
0.r.137=1
0.r.134=0
0.r.132=1
0.r.129=0


Is there any importance to any of the other junk in the replay file (in terms of 40l mode)? It seems to mostly all be useless apart from a few game settings like DAS.

XaeL

#93
Quote from: simonlc
I'm looking at the replay files right now, and it doesn't seem to be based on the frame index, but rather the milliseconds elapsed since the last key. Would that be correct?

I'm not sure what you quoted (replays from nullpo?)

If so, if i were you i'd stick to milliseconds from start of game rather than diffs.



QuoteLike many setups here, it is useful if your opponent doesn't move and you get 4 Ts in a row.

simonlc

Quote from: XaeL
I'm not sure what you quoted (replays from nullpo?)

If so, if i were you i'd stick to milliseconds from start of game rather than diffs.
The thing I quoted is an explanation of how replays in Nullpo are written by Integration. Though the replays that I have aren't like that.

Why wouldn't you use diffs? Seems much better than using timestamps, easy to calculate, and smaller file size.

Integration

#95
The lines in NullpoMino replay files aren't sorted somehow. Perhaps it is hashed. If you sort your lines by frames, you get the following:

0.r.24=1
0.r.30=0
0.r.34=1
0.r.35=0
0.r.42=1
0.r.53=0
0.r.57=1
0.r.73=0
0.r.75=1
0.r.78=0
0.r.80=1
0.r.87=0
0.r.89=1
0.r.96=0
0.r.98=1
0.r.101=0
0.r.103=1

... which means you mashed your harddrop key roughly every 10th frame (0.16 seconds, meh this goes faster).

[!--quoteo--][div class=\\\'quotetop\\\']QUOTE[/div][div class=\\\'quotemain\\\'][!--quotec--]Is there any importance to any of the other junk in the replay file (in terms of 40l mode)? It seems to mostly all be useless apart from a few game settings like DAS.[/quote]
Most settings (like spawning orientations and directions) aren't important for you. The only important settings are those, which can be modified in your game: DAS, ARR, gravity, soft drop, lock delay. It's your choice if you also save the graphics options (block skin etc.). Do you also want to reach compatibility with NullpoMino replay files? It seems to be a lot of work until you could simulate 100%ly NullpoMino's system.

One more word to  NullpoMino: It doen't save the pieces order. Instead it saves a randomizer seed. In the replay file you find a line like this: 0.replay.randSeed=-10b460a2bf5236fe. NullpoMino uses the java class Math.random. When the game begins, a random variable is initialized: r = new Random(seed);. From time to time the current state of the random variable is prompted: r.nextInt(n), where n is a small integer (like 7).

[!--quoteo--][div class=\\\'quotetop\\\']QUOTE[/div][div class=\\\'quotemain\\\'][!--quotec--]Why wouldn't you use diffs? Seems much better than using timestamps, easy to calculate, and smaller file size.[/quote]
If you've got 8 inputs, you can save the inputs of one frame (where inputs change) within 1 byte. I don't think saving the input differences would lead to much smaller file sizes. Or did you mean saving the temporal difference between the frames in which new inputs happened?

[!--quoteo--][div class=\\\'quotetop\\\']QUOTE[/div][div class=\\\'quotemain\\\'][!--quotec--]If so, if i were you i'd stick to milliseconds from start of game rather than diffs.[/quote]
If you (Simonlc) stay with this frame based input system, I'd use frames but save the achieved time. Achieved time = end time - start time - paused timed. This way it's harder to cheat (if users aren't allowed to modify replays). When replaying, I'd stretch the shown timer, if a player's framerate wasn't accurate. For example: game was x frames long (first frame = 0, last frame = x), final time was t seconds. If you're in frame y in the replay, then show t*y/x seconds (instead of y/60 seconds).

simonlc

Thanks for the awesome post again Integration.

I would like to eventually have my game's replays be downloaded in Nullpo format, as well as be able to read Nullpo replays for sprint. But for now I will just start out making my own format, which will probably resemble this a lot.

In the replay file I found this line:

linerace.pieceSequence=[piece\=1, x\=3, y\=18, direction\=0, time\=72, rotations\=0, moves\=0][piece\=3, x\=3, y\=16, direction\=1, time\=138, rotations\=1, moves\=0][piece\=6, x\=3, y\=15, direction\=0, time\=195, rotations\=0, moves\=0][piece\=0, x\=3, y\=11, direction\=1, time\=255, rotations\=1, moves\=0][piece\=2, x\=4, y\=9, direction\=0, time\=312, rotations\=0, moves\=0][piece\=4, x\=3, y\=6, direction\=1, time\=372, rotations\=1, moves\=0][piece\=5, x\=3, y\=4, direction\=0, time\=443, rotations\=0, moves\=0][piece\=2, x\=4, y\=3, direction\=1, time\=502, rotations\=1, moves\=0][piece\=5, x\=3, y\=1, direction\=0, time\=571, rotations\=0, moves\=0][piece\=4, x\=3, y\=-1, direction\=1, time\=623, rotations\=1, moves\=0]


I haven't tested it, but it seems to be the piece sequence, which would eliminate the need for me to use the seed.

I've been thinking for a while on how to implement time along with the frame based system. Though it wouldn't really be for anti-cheat, more so for accuracy. As this is client side code, there's really no way to prevent cheating.

Thanks for the help, this will make adding replays a breeze.

XaeL

Quote from: simonlc
I've been thinking for a while on how to implement time along with the frame based system. Though it wouldn't really be for anti-cheat, more so for accuracy. As this is client side code, there's really no way to prevent cheating.
The way nullpo does it is the following:

at start of game, use sys.getMillis
at end of game, use sys.getMillis
During game, just increment frame, use dumb busy-wait to wait long enough for frame.

Time taken = end - start. Disregard how many frames were used.

My solution:
Drop the frames based system. Using a pure millisecond system is far better.



QuoteLike many setups here, it is useful if your opponent doesn't move and you get 4 Ts in a row.

Integration

Oh, I didn't know that NullpoMino League Edition would handle things differently. Probably, it still needs the seed. Belzebub must have added the line for advanced statistics and Fumen export.
  • piece ID: 0 -> I, 1 -> L, 2 -> O, 3 -> Z, 4 -> T, 5 -> J, 6 -> S
  • x: column in which piece was dropped
  • y: row in which piece was dropped
  • direction: orientation in which piece was dropped ( 0 -> up, 1 -> right, 2 -> down, 3 -> left )
  • time: ID of the frame in which piece was dropped
  • rotations: how often piece was rotated
  • moves: how often piece was moved to left or right
Do you also plan to add a scoreboard for each mode? If cheating is a problem, then weekly highscores could be more handy than alltime highscores: At the beginning of a session users are asked for their names. Each player (=name) can only have one spot on each table. If you improve your weekly highscore, the score will stay on the table for a week (or until you improve that score). If you won't improve your current score within the following week, you won't be mentioned on the table anymore (even if you played yesterday and just scored slightly worse). The best 20 to 30 scores (and replays) are saved, only the best 10 are shown.

simonlc

I've been deploying a lot of fixes, namely the menu arrows in chrome are fixed, the 20G bug is fixed, pieces are rendered off canvas once and reused (instead of rendered every single block), multiple rotate keys pressed at once are handled properly, the stack is darker than the falling piece, and falling piece and ghost are only rendered if there is a movement (instead of at 60fps).

Quote from: XaeL
The way nullpo does it is the following:

at start of game, use sys.getMillis
at end of game, use sys.getMillis
During game, just increment frame, use dumb busy-wait to wait long enough for frame.

Time taken = end - start. Disregard how many frames were used.

My solution:
Drop the frames based system. Using a pure millisecond system is far better.
I really want to do something like this, but essentially I would be forced to run the game at 1000fps to have 1ms accuracy for things like gravity and DAS. Having something run every 16ms rather than every 1ms is a good computerize.

Quote from: Integration
Oh, I didn't know that NullpoMino League Edition would handle things differently. Probably, it still needs the seed. Belzebub must have added the line for advanced statistics and Fumen export.
  • piece ID: 0 -> I, 1 -> L, 2 -> O, 3 -> Z, 4 -> T, 5 -> J, 6 -> S
  • x: column in which piece was dropped
  • y: row in which piece was dropped
  • direction: orientation in which piece was dropped ( 0 -> up, 1 -> right, 2 -> down, 3 -> left )
  • time: ID of the frame in which piece was dropped
  • rotations: how often piece was rotated
  • moves: how often piece was moved to left or right
Do you also plan to add a scoreboard for each mode? If cheating is a problem, then weekly highscores could be more handy than alltime highscores: At the beginning of a session users are asked for their names. Each player (=name) can only have one spot on each table. If you improve your weekly highscore, the score will stay on the table for a week (or until you improve that score). If you won't improve your current score within the following week, you won't be mentioned on the table anymore (even if you played yesterday and just scored slightly worse). The best 20 to 30 scores (and replays) are saved, only the best 10 are shown.
Hmm well I'll have something working soon so I can see if I really want to read the seed or not. Your highscore idea sounds good, but I think not having all time scores would be a bit of a disappointment for some. Uploading replays like cultris will be done for sure. The community of Tetris is very small, so I don't think cheaters is much of a problem.

simonlc

So I just pushed a new version. I changed the DAS counter a little bit, it should start counting from when you press the key, not one frame after. Apart from that I don't think there's anything new to see, but for those interested I've been rewriting the input code so replays will be easier to make. It's just the very beginning as there's actually a lot of stuff to change for the replays to actually run by themselves with just a string of inputs.

Question: does anyone know how many frames there are in the nullpomino count down? In the league edition, my crappy tests counted 100. If no one knows I'll try looking in the code later. Seems that nullpo starts recording during the countdown, so to get accurate replays it would be good to know.


FelipeMayrink

As you said, is pretty early on yet, but how exactly would this replays be saved?
Would you create an account and they'll be saved there? Would it remember your IP address and save it from there? Or would it just let you be able to see your last game, and automatically "delete" if don't want to save it?

Also, the little "pause that doesn't pause" bug, can it be fixed? I don't know sh*t about programming, but I don't think it should be that much difficult to fix.
(again, noob here, if it is, I'm sorry)

simonlc

Quote from: FelipeMayrink
As you said, is pretty early on yet, but how exactly would this replays be saved?
Would you create an account and they'll be saved there? Would it remember your IP address and save it from there? Or would it just let you be able to see your last game, and automatically "delete" if don't want to save it?

Also, the little "pause that doesn't pause" bug, can it be fixed? I don't know sh*t about programming, but I don't think it should be that much difficult to fix.
(again, noob here, if it is, I'm sorry)
The replays will be saved in what's called the browser's local storage. It's what settings are currently saved in. Every site has a 5mb limit in your browser by default. If there's no local storage (or if it's disabled) it simply wont save. There will also be an option to download the replays as a file or open them in a fumen. Once there is multiplayer maybe saving some replays to the server might be possible.

The pause thing is still waiting on other features to be implemented to be finished, like the replays for example. Right now it's just a way to access the menus after a game is started since there is no other way.

FelipeMayrink


simonlc



Getting a little side tracked...


[!--ImageUrlBegin--][a href=\\\"http://i.imgur.com/p282S9x.jpg\\\" target=\\\"_new\\\"][!--ImageUrlEBegin--][img width=\\\"400\\\" class=\\\"attach\\\" src=\\\"http://i.imgur.com/p282S9x.jpg\\\" border=\\\'0\\\' alt=\\\"IPB Image\\\" /][!--ImageUrlEnd--][/a][!--ImageUrlEEnd--]