KAZIK/tools/tests/pyramid_test.inc
Игорь Федосеев ca62db53e9 feat: implement native billiards, scratch tickets, first-person dice, and city wake scene
- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests
- Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects
- First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective
- City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation
- World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests
- Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
2026-10-16 12:37:40 +03:00

316 lines
7.8 KiB
PHP

.data
pyrTestStage3D dd 0
pyrTestRack db "build\actions\pyramid-rack.bmp",0
pyrTestAim db "build\actions\pyramid-aim.bmp",0
pyrTestStrike db "build\actions\pyramid-strike.bmp",0
pyrTestPenalty db "build\actions\pyramid-penalty.bmp",0
pyrTestChoice db "build\actions\pyramid-choice.bmp",0
pyrTestWin db "build\actions\pyramid-win.bmp",0
.code
RunBilliardsChoiceTest3D PROTO
PyramidTestLedger3D PROC uses ebx esi edi
xor esi,esi
xor ebx,ebx
xor edi,edi
pyr_test_ledger_ball:
cmp poolActive3D[esi*4],1
jne @F
inc ebx
cmp pyrOwner3D[esi*4],-1
jne pyr_test_ledger_bad
jmp pyr_test_ledger_next
@@:
cmp pyrOwner3D[esi*4],0
jl pyr_test_ledger_bad
cmp pyrOwner3D[esi*4],1
ja pyr_test_ledger_bad
inc edi
pyr_test_ledger_next:
inc esi
cmp esi,16
jb pyr_test_ledger_ball
add ebx,edi
cmp ebx,16
jne pyr_test_ledger_bad
mov eax,pyrScore3D
add eax,pyrScore3D[4]
cmp eax,edi
jne pyr_test_ledger_bad
xor eax,eax
ret
pyr_test_ledger_bad:
mov eax,1
ret
PyramidTestLedger3D ENDP
RunPyramidTest3D PROC uses ebx esi edi
local oldBank:DWORD,oldSeed:DWORD,oldAI:DWORD,oldMode:DWORD,ticks:DWORD,value:DWORD
mov eax,bankroll
mov oldBank,eax
mov eax,rngSeed3D
mov oldSeed,eax
mov eax,poolAI3D
mov oldAI,eax
mov eax,engineMode
mov oldMode,eax
mov engineMode,MODE_POOL
mov poolAI3D,0
call ClearKeys3D
mov pyrTestStage3D,1
call ResetPool3D
call PyramidTestLedger3D
test eax,eax
jnz pyr_test_fail
call RenderPool3D
invoke WriteActionSnapshot3D,OFFSET pyrTestRack
; Old Q8 squares wrapped at 256 pixels and potted a distant ball.
mov poolX3D,286*FP_1
mov poolY3D,50*FP_1
invoke PoolPocketBall3D,0
cmp poolActive3D,1
jne pyr_test_fail
mov poolX3D,34*FP_1
mov poolY3D,180*FP_1
invoke PoolPocketBall3D,0
cmp poolActive3D,1
jne pyr_test_fail
mov pyrTestStage3D,2
call ResetPool3D
mov poolBreak3D,0
invoke PoolAimPoint3D,250*FP_1,115*FP_1+FP_1/2
test pyrFine3D,7
jz pyr_test_fail
mov poolX3D[12*4],100*FP_1
mov poolY3D[12*4],90*FP_1
mov poolX3D[4],160*FP_1
mov poolY3D[4],90*FP_1
invoke PyramidSelect3D,12
cmp pyrCue3D,12
jne pyr_test_fail
invoke PoolAimPoint3D,200*FP_1,90*FP_1
call RenderPool3D
cmp pyrTarget3D,-1
je pyr_test_fail
invoke WriteActionSnapshot3D,OFFSET pyrTestAim
call PoolShoot3D
cmp poolState3D,POOL_STRIKE
jne pyr_test_fail
mov poolTime3D,120
call RenderPool3D
invoke WriteActionSnapshot3D,OFFSET pyrTestStrike
mov deltaTime3D,120
call HandlePool3D
cmp poolVX3D[12*4],0
jle pyr_test_fail
cmp poolVX3D,0
jne pyr_test_fail
mov pyrTestStage3D,3
call ResetPool3D
mov poolBreak3D,0
mov poolFirst3D,1
mov poolActive3D,0
mov poolPocket3D,1
mov poolPotted3D,1
call PoolFinishShot3D
cmp poolFoul3D,0
jne pyr_test_fail
cmp pyrScore3D,1
jne pyr_test_fail
cmp poolPlayer3D,0
jne pyr_test_fail
cmp pyrCue3D,0
je pyr_test_fail
call PoolFinishShot3D
cmp pyrScore3D,1
jne pyr_test_fail
call PyramidTestLedger3D
test eax,eax
jnz pyr_test_fail
mov pyrTestStage3D,4
call ResetPool3D
mov poolBreak3D,0
mov poolFirst3D,-1
mov poolActive3D[3*4],0
mov poolActive3D[9*4],0
mov poolPotted3D,208h
call PoolFinishShot3D
cmp poolState3D,POOL_PENALTY
jne pyr_test_fail
cmp poolActive3D[3*4],1
jne pyr_test_fail
cmp poolActive3D[9*4],1
jne pyr_test_fail
cmp poolPlayer3D,1
jne pyr_test_fail
call RenderPool3D
invoke WriteActionSnapshot3D,OFFSET pyrTestPenalty
invoke PyramidPenalty3D,4
invoke PyramidPenalty3D,5
cmp pyrScore3D[4],1
jne pyr_test_fail
cmp poolActive3D[5*4],1
jne pyr_test_fail
call RenderPool3D
invoke WriteActionSnapshot3D,OFFSET pyrTestChoice
invoke PyramidChoice3D,1
cmp poolPlayer3D,0
jne pyr_test_fail
call PyramidTestLedger3D
test eax,eax
jnz pyr_test_fail
; Invalid break has partial-rack choices; the penalty is not erased.
call ResetPool3D
mov poolFirst3D,1
mov poolBreakRails3D,6
call PoolFinishShot3D
cmp pyrIllegalBreak3D,1
jne pyr_test_fail
invoke PyramidPenalty3D,0
invoke PyramidChoice3D,2
cmp poolBreak3D,1
jne pyr_test_fail
cmp poolActive3D,1
jne pyr_test_fail
cmp pyrScore3D[4],1
jne pyr_test_fail
call PyramidTestLedger3D
test eax,eax
jnz pyr_test_fail
mov pyrTestStage3D,5
; Three object cushions, or two plus an object crossing, is a legal break.
call ResetPool3D
mov poolFirst3D,1
mov poolBreakRails3D,0Eh
call PoolFinishShot3D
cmp poolFoul3D,0
jne pyr_test_fail
call ResetPool3D
mov poolFirst3D,1
mov poolBreakRails3D,6
mov pyrHistoryCross3D[4],1
call PoolFinishShot3D
cmp poolFoul3D,0
jne pyr_test_fail
mov pyrTestStage3D,6
; Legal completion needs ordered events along the same transfer chain.
call ResetPool3D
mov poolBreak3D,0
mov poolFirst3D,1
invoke PyramidRail3D,1,0
invoke PyramidRail3D,1,0
cmp pyrValidEnd3D,0
jne pyr_test_fail
invoke PyramidRail3D,1,1
cmp pyrValidEnd3D,1
jne pyr_test_fail
call ResetPool3D
mov poolFirst3D,1
mov pyrPreviousX3D[4],159*FP_1
mov poolX3D[4],161*FP_1
invoke PyramidCross3D,1
invoke PyramidRail3D,2,0
cmp pyrValidEnd3D,0
jne pyr_test_fail
invoke PyramidRail3D,1,0
cmp pyrValidEnd3D,1
jne pyr_test_fail
call ResetPool3D
mov poolFirst3D,1
invoke PyramidRail3D,1,0
mov pyrPreviousX3D[4],159*FP_1
mov poolX3D[4],161*FP_1
invoke PyramidCross3D,1
cmp pyrValidEnd3D,1
jne pyr_test_fail
call ResetPool3D
mov poolFirst3D,1
invoke PyramidRail3D,1,0
mov poolX3D[4],80*FP_1
mov poolX3D[8],90*FP_1
invoke PyramidContact3D,1,2
invoke PyramidRail3D,2,1
cmp pyrValidEnd3D,1
jne pyr_test_fail
mov pyrTestStage3D,7
; The real bot must pot through geometry, not inject a pocket result.
call ResetPool3D
mov poolBreak3D,0
mov poolPlayer3D,1
mov poolAI3D,0
mov esi,2
pyr_test_ai_clear:
mov poolActive3D[esi*4],0
inc esi
cmp esi,16
jb pyr_test_ai_clear
mov poolX3D,160*FP_1
mov poolY3D,115*FP_1
mov poolX3D[4],160*FP_1
mov poolY3D[4],70*FP_1
call PoolChooseAI3D
cmp pyrCue3D,0
jne pyr_test_fail
call PoolShoot3D
mov deltaTime3D,240
call HandlePool3D
mov deltaTime3D,16
mov ticks,0
pyr_test_ai_tick:
call HandlePool3D
inc ticks
cmp ticks,1000
ja pyr_test_fail
cmp poolState3D,POOL_MOVING
je pyr_test_ai_tick
cmp pyrScore3D[4],1
jb pyr_test_fail
cmp poolPocket3D[4],1
jne pyr_test_fail
mov pyrTestStage3D,8
call ResetPool3D
mov poolBreak3D,0
mov poolFirst3D,9
mov poolPotted3D,01FEh
mov esi,1
pyr_test_winning_balls:
mov poolActive3D[esi*4],0
mov poolPocket3D[esi*4],1
inc esi
cmp esi,9
jb pyr_test_winning_balls
call PoolFinishShot3D
cmp pyrScore3D,8
jne pyr_test_fail
cmp poolWinner3D,0
jne pyr_test_fail
cmp poolState3D,POOL_RESULT
jne pyr_test_fail
call PyramidTestLedger3D
test eax,eax
jnz pyr_test_fail
call RenderPool3D
invoke WriteActionSnapshot3D,OFFSET pyrTestWin
call RunBilliardsChoiceTest3D
test eax,eax
jnz pyr_test_choice_fail
mov eax,oldBank
cmp bankroll,eax
jne pyr_test_fail
mov eax,oldSeed
cmp rngSeed3D,eax
jne pyr_test_fail
mov eax,oldAI
mov poolAI3D,eax
mov eax,oldMode
mov engineMode,eax
call ClearKeys3D
xor eax,eax
ret
pyr_test_choice_fail:
ret
pyr_test_fail:
mov eax,pyrTestStage3D
add eax,920
ret
RunPyramidTest3D ENDP
include tools\tests\billiards_choice_test.inc