g | x | w | all
Bytes Lang Time Link
002Uiua250718T124254Znyxbird
026Nim250710T021357ZjanAkali
00205AB1E250707T070344ZKevin Cr
nanCommodore 64 Assembler250706T200830ZJani Joe
008x8664 machine code250706T142741Zm90
015Google Sheets250705T183116Zdoubleun
018Python 2250706T045802ZLucenapo
005Charcoal250705T193158ZNeil
002Vyxal 3250705T181738ZThemooni
015JavaScript ES6250705T165505ZArnauld

Uiua, 2 bytes

⌈÷

Try it!
⌈ ceiling ÷ division

Nim, 26 bytes

proc(a,b=0):int=(a+b-1)/%b

Try it online!

Explanation: Ceiling Integer Division

05AB1E, 2 bytes

Inputs in the order decay_per_tick, initial_strength.

Try it online or verify all test cases.

Explanation:

/   # Divide the (implicit) second input by the (implicit) first input
 î  # Ceil it
    # (after which the result is output implicitly)

Commodore 64 Assembler, 25 Bytes (6502/KickAssembler)

Being a purely 8bit processor, including the registers, 6502 can natively handle integers up to 255. As both strength and ticks can be up to 1000, we need to programmatically handle them as 16bit integers, which unfortunately increases the size of our routine quite a bit. An 8bit version of the routine would have taken just 12 bytes.

Input

Before calling the routine:

Output

After the routine:

Routine

TICKS:  ldx #0          // 2 Reset 16bit tick count lo byte.
        stx $3          // 2 Reset 16bit tick count hi byte.
zcheck: cmp #0          // 2 Is 16bit aura lo byte 0? Also sets Carry.
        bne tick        // 2 If not, do tick.
        cpy #0          // 2 If yes, is 16bit aura hi byte 0? Also sets Carry.
        beq done        // 2 If yes, aura is 0 and we're done.
tick:   inx             // 1 Increment tick count.
        bne !+          // 2 Did tick count lo byte roll over?
        inc $3          // 2 If it did, increment hi byte.
    !:  sbc $2          // 2 Subtract decay from aura lo (Carry set by zcheck).
        bcs zcheck      // 2 If aura lo didn't roll under, check if aura=0
        dey             // 1 If it did, decrement aura hi.
        bpl zcheck      // 2 If aura hi didn't roll under, check if aura=0
done:   rts             // 1 X = tick count lo byte, address $3 = hi byte.

Try It Out (in your favourite IDE or CLI)

To test the routine with the cases listed in the question, and some more, I decided to write a small test suite, because why the heck not. :) Two additional cases are for testing boundaries (1000 max aura, 1000 max ticks, 100 max decay).

BasicUpstart2(tests)

TICKS:  ldx #0          // 2 Reset 16bit tick count lo byte.
        stx $3          // 2 Reset 16bit tick count hi byte.
zcheck: cmp #0          // 2 Is 16bit aura lo byte 0? Also sets Carry.
        bne tick        // 2 If not, do tick.
        cpy #0          // 2 If yes, is 16bit aura hi byte 0? Also sets Carry.
        beq done        // 2 If yes, aura is 0 and we're done.
tick:   inx             // 1 Increment tick count.
        bne !+          // 2 Did tick count lo byte roll over?
        inc $3          // 2 If it did, increment hi byte.
    !:  sbc $2          // 2 Subtract decay from aura lo (Carry set by zcheck).
        bcs zcheck      // 2 If aura lo didn't roll under, check if aura=0
        dey             // 1 If it did, decrement aura hi.
        bpl zcheck      // 2 If aura hi didn't roll under, check if aura=0
done:   rts             // 1 X = tick count lo byte, address $3 = hi byte.

.print "ROUTINE SIZE: " + toIntString(* - TICKS) + " BYTES"

tests:  test(10,3,4)    // aura, decay, expected ticks
        test(5,5,1)
        test(0,10,0)
        test(1,10,1)
        test(1000,1,1000)
        test(1000,100,10)
        rts

.macro test(aura, decay, expected) {
GIVEN:  lda #decay      // Load decay to A...
        sta $2          // ...and store it to ZP address $2.
        lda #<aura      // Load 16bit aura lo byte to A.
        ldy #>aura      // Load 16bit aura hi byte to Y.
WHEN:   jsr TICKS       // CALL OUR ROUTINE.
THEN:   lda $3          // Load aura hi byte to A
        cmp #>expected  // Compare with hi byte of expected ticks
        bne fail        // If no match, branch to fail
        cpx #<expected  // Compare lo byte of ticks to expected
        bne fail        // If no match, branch to fail
succ:   print(s_act)    // Otherwise, print success message.
        jsr $bdcd       // Call ROM routine to print out 16bit integer.
        lda #$0d        // Call ROM routine to print out $0d (control
        jsr $ffd2       // code for pressing RETURN key).
        jmp done        // Test done.
fail:   print(f_act)    // Print 1st (actual) part of fail message.
        jsr $bdcd       // Call ROM routine to print out 16bit integer.
        print(f_exp)    // Print 2nd (expected) part of fail message.
        lda #>expected  // Load hi byte of expected ticks to A...
        ldx #<expected  // ...and lo byte to X.
        jsr $bdcd       // Call ROM routine to print out 16bit integer.
        lda #$0d        // Call ROM routine to print out $0d (control
        jsr $ffd2       // code for pressing RETURN key).
done:                   // Test completed.
}

.macro print(message) {
        pha             // Push A to stack.
        tya             // Move Y to A...
        pha             // ...and push it to stack as well.
        ldy #0          // Y=0
    !:  lda message,y   // Load char,y from message
        beq done        // If zero (null), we're done.
        jsr $ffd2       // Print char.
        iny             // Increment char index.
        bne !-          // If not rolled over, keep printing chars.
done:   pla             // Pull value of Y from stack to A...
        tay             // ...and move it to Y.
        pla             // Pull value of A from stack.
}

f_act:  .te "TEST FAILED! TICKS: " ; .by 0
f_exp:  .te ", EXPECTED: " ; .by 0
s_act:  .te "TEST PASSED! TICKS: " ; .by 0

screenshot after running the test suite

x86-64 machine code, 8 bytes

8D 44 37 FF 99 F7 F6 C3

Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes initial_strength and decay_per_tick as 32-bit integers in EDI and ESI, respectively, and returns a 32-bit integer in EAX.

In assembly:

f:  lea eax, [rdi + rsi - 1]    # Set EAX to the sum of the two values minus 1.
    cdq     # Sign-extend EAX, preparing for the next instruction.
    div esi # Divide by the decay value. The quotient goes into EAX.
    ret     # Return.

Google Sheets, 15 bytes

=ceiling(A1/B1)

Put initial_strength in cell A1, decay_per_tick in B1 and the formula in C1.

Python 2, 18 bytes

lambda x,y:-(-x/y)

Try it online!

x is initial strength, y is decay per tick.

Charcoal, 5 bytes

I⌈∕NN

Try it online! Link is to verbose version of code. Explanation: Suffers from potential floating-point inaccuracy.

    N   First input as a number
  ∕     Floating-point division by
   N    Second input as a number
 ⌈      Ceiling
I       Cast to string
        Implicitly print

There are a couple of approaches for precise arithmetic for 6 bytes:

I⊕÷⊖NN

Try it online! Link is to verbose version of code. Explanation: Decrements the numerator first, then increments the result.

I±÷±NN

Try it online! Link it to verbose version of code. Explanation: Negates the numerator, which turns the flooring effect of integer divide into a ceiling effect, then negates the result.

With all of the above answers, two bytes can be saved by taking input in JSON format e.g. [10, 3] which allows the s to be removed.

Vyxal 3, 2 bytes

÷⌈

Vyxal It Online!

÷⌈­⁡​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢‏‏​⁡⁠⁡‌­
÷   # ‎⁡div
 ⌈  # ‎⁢ceil
💎

Created with the help of Luminespire.

<script type="vyxal3">
÷⌈
</script>
<script>
    args=[["3","10"],["5","5"],["10","0"],["10","1"]]
</script>
<script src="https://themoonisacheese.github.io/snippeterpreter/snippet.js" type="module"/>

JavaScript (ES6), 15 bytes

Expects (initial_strength)(decay_per_tick).

s=>d=>~-s/d+1|0

Try it online!