Stick and Lucky Punch are sad in gen 2

Stick (renamed to Leek in newer gens) and Lucky Punch are held items that apply their effects exclusively to Farfetch'd and Chansey respectively.

Their effect is to raise by 2 the critical stage, an hidden statistic that determines the likelihood of a Pokémon to perform a critical hit.

However, in generation 2, they have a slightly different effect: they set the critical stage to 2 and ignore all other effects.

This is never beneficial, and it's in fact detrimental most of the time. The Scope item combined with a move with high critical ratio reaches crit stage 3 and stage 4 can be reached with Focus Energy or Dire Hit: in all those cases the crit stage will be 2 with a Stick or a Lucky Punch.

The code

Let's take a look at the code in the disassembly to see how critical hits are determined in generation 2.

The code that interests us is under the label BattleCommand_Critical in engine/battle/effect_commands.asm.

Let's comment it piece by piece:

    BattleCommand_Critical:
    ; Determine whether this attack's hit will be critical.

We start by setting wCriticalHit to 0, meaning that by default the current attack is not a critical.

        xor a
        ld [wCriticalHit], a

Then we check if the current move has a base power greater than 0 (which would mean it's an attacking move): if not the attack can't be a critical and we return.

        ld a, BATTLE_VARS_MOVE_POWER
        call GetBattleVar
        and a
        ret z

Next we do the usual turn check with hBattleTurn and we load the address to the held item in hl and the Pokémon species in a.

        ldh a, [hBattleTurn]
        and a
        ld hl, wEnemyMonItem
        ld a, [wEnemyMonSpecies]
        jr nz, .Item
        ld hl, wBattleMonItem
        ld a, [wBattleMonSpecies]

Now that we have the values we need we can start checking for any bonuses, but first we set c, which contains our critical stage, to 0.

    .Item:
        ld c, 0

First we check if the current Pokémon is Chansey. If it's not we skip directly to the Farfetch'd check, if it is we check if the current item is Lucky Punch.

If the item is not the Lucky Punch we skip over the Farfetch'd check and directly to Focus Energy (which is correct, as we have already established that the Pokémon is Chansey), if it is we load 2 in c and immediately skip to the tally, which determines the crit chance based on c, skipping everything in between.

        cp CHANSEY
        jr nz, .Farfetchd
        ld a, [hl]
        cp LUCKY_PUNCH
        jr nz, .FocusEnergy

    ; +2 critical level
        ld c, 2
        jr .Tally

Farfetch'd's (that was fun to write) check works the same as Chansey's just with different values for the species and item.

    .Farfetchd:
        cp FARFETCH_D
        jr nz, .FocusEnergy
        ld a, [hl]
        cp STICK
        jr nz, .FocusEnergy

    ; +2 critical level
        ld c, 2
        jr .Tally

The Focus Energy check raises c by 1 if Focus Energy is active, but this time it doesn't skip anything.

    .FocusEnergy:
        ld a, BATTLE_VARS_SUBSTATUS4
        call GetBattleVar
        bit SUBSTATUS_FOCUS_ENERGY, a
        jr z, .CheckCritical

    ; +1 critical level
        inc c

The next check is for the move: if the current move is in the list at data/moves/critical_hit_moves.asm the critical stage is raised by 2.

    .CheckCritical:
        ld a, BATTLE_VARS_MOVE_ANIM
        call GetBattleVar
        ld de, 1
        ld hl, CriticalHitMoves
        push bc
        call IsInArray
        pop bc
        jr nc, .ScopeLens

    ; +2 critical level
        inc c
        inc c

Once again we check the user item, if it's a Scope Lens we raise the stage by 1. Note that here we jump to the tally if the item is not a Scope Lens, but this time no code is skipped, because this is the last check.

    .ScopeLens:
        push bc
        call GetUserItem
        ld a, b
        cp HELD_CRITICAL_UP ; Increased critical chance. Only Scope Lens has this.
        pop bc
        jr nz, .Tally

    ; +1 critical level
        inc c

All the code between the Farfetch'd check and this point is skipped completely if Stick's or Lucky Punch's effects are active.

Now it's time to determine the probability: the table is at data/battle/critical_hit_chances.asm: we simply add c bytes to the CriticalHitChances address, obtaining the address of the byte that encodes the probability out of 255.

    .Tally:
        ld hl, CriticalHitChances
        ld b, 0
        add hl, bc
        call BattleRandom
        cp [hl]
        ret nc
        ld a, 1
        ld [wCriticalHit], a
        ret

Speculation and fix

I'm not sure why these items are coded like this, it might be an oversight: maybe they moved some code around or they added the other checks later in development and forgot to update the jrs. Maybe it was intended, it's hard to know with no information.

Fixing this is really simple, you just need to update the jrs to go to the Focus Energy check instead of to the tally, like this:

        cp CHANSEY
        jr nz, .Farfetchd
        ld a, [hl]
        cp LUCKY_PUNCH
        jr nz, .FocusEnergy

    ; +2 critical level
        ld c, 2
    -   jr .Tally
    +   jr .FocusEnergy

    .Farfetchd:
        cp FARFETCH_D
        jr nz, .FocusEnergy
        ld a, [hl]
        cp STICK
        jr nz, .FocusEnergy

    ; +2 critical level
        ld c, 2
    -   jr .Tally

Conclusion

If you decide to use Chansey or Farfetch'd in generation 2, use these items only if you plan to not use moves with high critical ratio, if you do (and are fine with farming Mystery Gift) the Scope Lens has a better effect.