In NES Tetris, blocks in the field can have 4 possible values: black, white, color1, color2, where color1 and color2 change for every level.
In NESTrisOCR master, color1 and color2 are read from fixed screen locations: the piece stats on the left. Blocks areas are read from target pieces, and to prevent accidental mis-calibration, the read areas are downscaled with antialiasing to a single pixel, representing the average color of the area.
This works well, but had minor drawbacks:
Since averaging is involved, and there are white bits in the color areas, the resultant computed colors are quite far from the actual colors used in the field (they're "washed out"). The algorithm for field scanning is forgiving however (finding the closest match of 4 colors), so it works well, but one could argue, it's "lucky" in a way.
There are many training mods out-there which replace the stats area by something else (e.g. das trainer with das stats, TAUS with useful game stats). Field scanning can't be done for these roms because there are no fixed location to read color1 and color2 from the screen.
NES Tetris has a systematic setup however, and reference colors can be hardcoded and looked up from a table by level.
On a "perfect" rendering system like an emulator, that should be good enough. black, white, color1, and color2 will render per specs. On console with capture cards however, gamma correction or various artefacts might make the 4 colors "less perfect".
Because the algorithm which finds the nearest color is forgiving (closest match to 4 supplied colors), hardcoded black, white, color1, and color2 could still work well as-is. Still, one might want more flexibility:
Ability to still read color1 and color2 from screen if there are fixed location to do so
Ability to read black and white from screen. These values represent the color range, which can be scaled to the full range (0-255) to interpolate the hardcoded colors.
This PR introduces a lookup system for color1 and color2 based on hardcoded values by level.
Approach
Introduce a reference color table by level (note: works till level 29 atm, TODO added to support higher)
Introduce ability to scan black and white (based on text in the Next box)
Introduce ability to interpolate colors from black and white references
Supply the black value for the preview scanner and spawn too, rather than each using their own hardcoded value
Move responsibility to decide scanning versus lookup to the strategies. This allow them to cache the 4 colors as they see fit.
modify scan_field() and the board methods to always take in 4 colors (black,white,color, color2), which is supplied by the strategy callers.
Tested to work well with Naive strategy with various setting combinations. On my box, everything works beautifully without the need to read any color or blak+white dynamically
Fastest strategy seems to work well-ish too, but preview is not being scanned for some reason. It's not an issue with the black luma since it works with naive. Something else I need to look into.
Notes:
All 4 colors are always stored in np.array(dtype=np.uint8) format to save some minor repeat transformations
The PR is being opened as draft for now to get some feedback first
Context
In NES Tetris, blocks in the field can have 4 possible values:
black
,white
,color1
,color2
, wherecolor1
andcolor2
change for every level.In NESTrisOCR master,
color1
andcolor2
are read from fixed screen locations: the piece stats on the left. Blocks areas are read from target pieces, and to prevent accidental mis-calibration, the read areas are downscaled with antialiasing to a single pixel, representing the average color of the area.This works well, but had minor drawbacks:
color1
andcolor2
from the screen.NES Tetris has a systematic setup however, and reference colors can be hardcoded and looked up from a table by level.
On a "perfect" rendering system like an emulator, that should be good enough.
black
,white
,color1
, andcolor2
will render per specs. On console with capture cards however, gamma correction or various artefacts might make the 4 colors "less perfect".Because the algorithm which finds the nearest color is forgiving (closest match to 4 supplied colors), hardcoded
black
,white
,color1
, andcolor2
could still work well as-is. Still, one might want more flexibility:color1
andcolor2
from screen if there are fixed location to do soblack
andwhite
from screen. These values represent the color range, which can be scaled to the full range (0-255) to interpolate the hardcoded colors.This PR introduces a lookup system for
color1
andcolor2
based on hardcoded values by level.Approach
black
value for the preview scanner and spawn too, rather than each using their own hardcoded valuescan_field()
and theboard
methods to always take in 4 colors (black,
white,
color, color2
), which is supplied by the strategy callers.Tested to work well with Naive strategy with various setting combinations. On my box, everything works beautifully without the need to read any color or blak+white dynamically
Fastest strategy seems to work well-ish too, but preview is not being scanned for some reason. It's not an issue with the black luma since it works with naive. Something else I need to look into.
Notes:
np.array(dtype=np.uint8)
format to save some minor repeat transformationsEnjoy! :D