Package: tetris-c
Python 2 Player Tetris Library implemented in C++Original title: Tetris with instant soft drop delay(branch python library)Following tetris guidelines, implemented in C++ for speed, actions are taken simultaneously, players turn-based with matching keys instead piece, can be used to train AI/whatever.with instant softdrop after specified time and short softdrop like DAS(not implemented in python lib yet)Separated from my tetris/pylibtestUsage Brief viewimporttetrisx=tetris.Container()# game objecty=x.copy()# deep copy if neededx.reset()# reset statex.seed_reset(n)# reset with rng seedstate=x.get_state()# shape (500,) numpy array, 1D so easier to use mp shared memory, more info belowshapes=x.get_shapes()# (7,4,4,4) 7 pieces 4 rotations and 4x4 shapex.step(ac1,ac2)RenderRenderer(mode,size)orRenderer().create_window(mode,size)mode 1: pixel size=sizemode 2: screen width=sizemode 3: screen height=sizer=tetris.Renderer(1,30) 
r.render(x)

# close window
r.close()Manually Install dependency:If you don't want to render/install sdl2 use my tetris_c_nore library insteadModify setup.py for include and lib directories of SDL2 if neededWindows:Visual Studio:vcpkg install sdl:x64-windowsMinGW:LinkMac/Linux:On Mac installbrew(package manager for mac)Install sdl2(sometimes libsdl2-dev) with package managerIn Depth InfoGame Stepaction is scalar int0:hold
1:hard drop
2:cw
3:ccw
4:left tap
5:right tap
6:left das
7:right das
8:soft drop
9:180Statesp1_state=state[0:232]p2_state=state[232:464]sum attackstate[464], negative is to p1
individual attacksstate[465:]Rewardstate[0] is reward127 is lose, 126 is win, otherwiseif harddrop (action==1)
    if lines_cleared
        rew=10 * (attack+ b2b *2)+2*lines
    rew+=b2b_not_broke
else rew=wallkickPython for extractinglines_cleared=(reward%10)//2atk=reward//10# b2b rewards 2 atk but is 1 in-gamewallkick=reward%5ifaction!=1else0b2b_not_broken=reward%5ifaction==1else0game doesn't auto reset on game over, check those signals and call reset on your ownStatesi piece goes to -2 so the value is +2 by default, if you want to draw current piece subtract that backx = state[1]Board is 30 high, bottom 21 is returned, y spawns at 9 normally but 8 if occupied, otherwise game over.Value returned to python starts at 8 so pieces spawn at 1 normally, could be negative if you navigate the piece off screeny = state[2]Distance to bottomsoftdropdist = state[3]Default is 10 actions will force harddropaction_count = state[4]Garbage cleared from last action, use for reward etcgarbage = state[5]hold_used = state[6]rotation = state[7]active = state[8]Draw active piece on current location(you have to check x negative yourself):board[x-2,y]=shape[active][rotation]Held can be -1 meaning not usedheld_piece = state[9]next_pieces = state[10:15]Cheat data(hidden queue)hidden_queue=state[15:22]Less cheating because you can manually count the bag:hidden_queue=sort(state[15:22])Boardstate[22:232].reshape(21,10)FeedbackAny ideas for improvements are welcome.State is mostly boolean/binary so it's possible I can optimise the code further to increase speed as use cases probably will be AI training that needs millions of iterations.if you want to read/change the code, tetrisboard is main logic including clear rewards, and env.cpp is the python wrapper+rendering+returning state