Repository navigation
Reimpl/aiv state - #233
Draft
gynt wants to merge 85 commits into
Draft
Reimpl/aiv state#233gynt wants to merge 85 commits into
gynt wants to merge 85 commits into
Conversation
gynt
force-pushed
the
reimpl/AIVState
branch
2 times, most recently
from
September 26, 2026 23:44
d5e0ae2 to
4edefa0
Compare
gynt
force-pushed
the
reimpl/AIVState
branch
from
September 26, 2026 23:52
4edefa0 to
aa42e07
Compare
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… aivID branch Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…eax,eax Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ers differ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rs differ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… return Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ches Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d-calls Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…differ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ing with /GL The original keeps this in ecx across the call, which needs /GL on caller and callee and a direct call (resolver enabled). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reimplements the 37 functions of
OpenSHC::AI::AIVState.Measured with
reccmp-reccmp --target STRONGHOLDCRUSADER --resolve-wrapped-calls, with the global data resolvers enabled locally (tools/reimplementation-control/Enable-Reimplemented-Data.ps1, not committed). 26 of the 37 functions are at 100%.cmake/compiler-flags-gl.txtgainsexecuteDefaultCastleAIV.cppandfindAppropriateGridLocationForBuilding.cpp: the original keepsthisinecxacross that call. For the same reason the resolver offindAppropriateGridLocationForBuildingis set to implemented, andclearTheHeatmapsis set to implemented for the tail call inwipeAIVsAndHeatMaps.Functions below 100%
computeLargestSeparateArea0x4edd00aiDecideOnNewBuildings0x4f15c0aiPlaceFlag0x4ed240rotateAIV0x4ed0b0aiPlaceWoodcuttershut0x4efab0updateBuildingsStateAndUpdateAIBuildingDecisions0x4f1860recomputeHeatmaps0x4f0e80findAppropriateGridLocationForBuilding0x4eee10hostChecksLobbyAIVAvailability0x4ecbc0applyAIV0x4ef0d0executeDefaultCastleAIV0x4f0060In the diffs,
-is the original and+is this branch;@@marks skipped identical instructions.computeLargestSeparateArea- 98.78%Code is identical. The only difference is the name reccmp gives the stack-probe helper:
_chkstkin our build, an unnamed offset in the original. Not reachable from source.reccmp diff (2 differing lines)
aiDecideOnNewBuildings- 98.51%The original stores the initial values of
isPausingandstepIncrementbefore the branch of theaivID <= 0check; ours emits them after it, next to theresourceRebuildDelayload. Declaring the two locals before the check, or nesting the body inif (aivID > 0), moves the stores but disturbs the rest of the function (70-82%).reccmp diff (6 differing lines)
aiPlaceFlag- 98.25%Same instruction and same address. The access is
aics[aiType - 1].flagType, and its constant base lies just before the start of theAICStateglobal, so reccmp names it after the nearest preceding symbol. That symbol differs between the original (EntityState+705348) and our DLL (cached+4). Not reachable from source.reccmp diff (2 differing lines)
rotateAIV- 97.20%Only the order in which four array base addresses are materialised (
lea) before the copy loops differs. Swapping the two statements in the loop body (62.6%), reading the sources into locals first (27.8%) and a flat index forsteps(tie) were measured.reccmp diff (6 differing lines)
aiPlaceWoodcuttershut- 91.38%After the call to
findAppropriateWoodCutterGridLocationthe original comparesbuildingApproriateGridXPositionwith -1 in memory and then loads it; ours loads it and compares the register. Casts, a named local, nested positive conditions and/GLon caller plus both callees all compile to identical code. The trailing+lines are a compare-window artefact.reccmp diff (10 differing lines)
updateBuildingsStateAndUpdateAIBuildingDecisions- 90.83%In the start-of-day loop the original loads
currentPlayerFullIDArray[player]intoeaxand, on the path where it is -1 and the AI slot is 0, executes a redundantcmp eax, eax; je. That looks like a third== -1test with the constant replaced by the register known to hold it. Six ways of writing a redundant third condition (re-read, local, named constant, negated form) are all folded away by our build. The trailing+lines follow from the resulting size difference.reccmp diff (22 differing lines)
recomputeHeatmaps- 88.89%Three things. (1) Constant pooling: the original keeps
0x100000inebx, ours keeps0x90inbl. (2) In both tile loops the original computes y, then x, then divides; ours interleaves the load and the division. Namingy/xlocals in that order compiles to identical code. (3)test eax, 0x10001580is shown as<OFFSET>on our side because the flag mask looks like an address inside the DLL image - a reccmp artefact.reccmp diff (79 differing lines)
findAppropriateGridLocationForBuilding- 88.21%Loop rotation. The original reloads
algAIndexat the loop head, jumps back withjneand rematerialises the constant 1 inedievery iteration; ours reuses the register from the bottom test and setsediin a separate block before jumping back.while,do-whilewith the result inside or after the loop, and afor(;;)with the test at the top score 83.2-88.2%; split entry conditions and hoisted declarations tie.reccmp diff (31 differing lines)
hostChecksLobbyAIVAvailability- 68.63%The per-player availability test is instruction-identical. What differs is the outer loop: the original runs three induction variables (AI index in
ebx, a pointer into the received table inesi, a pointer intoaivFileAvailabilityPerAIArrayinedi) and ends the loop on the pointer; ours derives the received-table pointer from the other one (sub ebx, ecx/lea edx, [ebx + esi]) and ends on the index. That permutes the register roles from the firstpushon. Fourteen source variants (!=bound,uintindex, flat table index, hoisted or removed locals, post-increment store, if/else instead of early return) compile to identical code.reccmp diff (85 differing lines, first 110 diff lines shown)
applyAIV- 67.19%Register assignment in the first grid loop. The original keeps
yon the stack and spendsebxonaivID * 0x922; ours keepsyinebxand spills the product, which changes every stack slot and operand after it. Giving the loops their ownx/y, or sharing them differently, scores 40-55%;/GLscores 57%.reccmp diff (378 differing lines, first 150 diff lines shown)
executeDefaultCastleAIV- 53.56%Register and stack-slot assignment across the whole body. The original keeps the stockpile counter in
ebxwith a home slot at[esp+0x58], the constant 1 inebpand theplayerIDoffset only on the stack; ours keeps the stockpile counter inebpwithout a home slot, 1 inecxand the player offset inebx. The sequence of compares, calls and branches otherwise equals the original, except for the woodsman check (jg+jmpin the original, onejlein ours). Declaration order and placement of the leading locals move the score by less than half a point.reccmp diff (888 differing lines, first 170 diff lines shown)
🤖 Generated with Claude Code