Woof, the latest level gave me a real challenge. Clearing level 6 getting all captives and staying alive!!
Simple enough level 6 is |C@ S aa>| As in {-1 => ‘east_wall’, 0 => ‘captive’, 1 => starting position, 2 => ‘space’, 3 =>’Thick Sludge’, 4 => ‘space’, 5 => ‘Archer’, 6 => ‘Archer’, 7 => ‘stairs’, 8 => ‘wall’}.
The Art of Not Dying (Too Much)
Some warriors play it safe, ensuring they’re always at a pristine 20 HP before moving forward, like a cautious grandma checking the weather before stepping outside. Not this warrior. This warrior laughs in the face of danger (and sometimes cries when an arrow lands in their knee). Instead of maxing out health, I let them gauge survival based on “Can I smack this guy into oblivion before they smack me harder?”
Now, this works great for your standard melee brutes—guys who need a personal invitation (and an axe to the face) before engaging. But then come the long-distance jerks. These guys, like the archers in Level 6, are weaklings on paper—7 health, 3 attack power—basically the medieval equivalent of a guy yelling insults from across the street.
BUT… thanks to their unfair ability to attack before my warrior even gets adjacent, they are sneaky little health taxes. Here’s how the “Archer Pain Tax” works:
- Warrior enters range. Turn ends.
- Archer says “Surprise!” Shoots. Warrior loses 3 HP.
- Warrior steps closer. Archer shoots again. Warrior now at -6 HP.
- Warrior finally attacks. Archer loses 5 HP.
- Archer, still alive, retaliates. Warrior now at -9 HP.
- Warrior attacks again. Archer dies.
So, killing an archer costs a whopping 9 HP, all because they get extra shots before I can say “Stop that!”

The real kicker? Archers turn a 2-turn melee fight into a 3-turn disaster. They demand more time, more HP, and more frustration as my warrior gets turned into a pincushion.
Since I’m aiming for a time bonus, fewer turns = better. That means the faster I close the gap, the better. And since my warrior doesn’t believe in wearing a helmet, dodging is apparently not an option.
So, the strategy? Minimize the time spent in the “Getting Shot Zone.”
And if all else fails? Hope the warrior brought some Band-Aids.
Arrgg, that extra archer right behind the first. After a beating of the first archer one must now take into account being hit by the one behind. An extra hit must be accounted for as well as the remaining gap.
Extra Archer… “Extra Pain”:
- Warrior in range attacks and kills archer. Turn ends.
- Archer Dies, no health lost for Warrior, next archer already in warrior range
- Warrior steps closer. Archer shoots. Warrior now at -12 HP.
- Warrior attacks. Archer loses 5 HP.
- Archer, still alive, retaliates. Warrior now at -15 HP.
- Warrior attacks again. Archer dies.
Total power needed calculation changed. Though only when the second Archer was found through recon. So, we get movement forward until the second archer appears. When the calculated need goes up the warrior retreats, recalculates and once more sets forward.
From how health is lost and then regained the calculated amount was 16. This is enough health to win the level with 1 health left.
I lowered health in the calculation rather than modifying the power. It made more sense to simulate a turn by removing health. Health can be lowered twice. If not within striking distance lower health by 1(this accounts for the first step into range). If there are two enemies, multiply by 2 the power. This accounts for the distance hit the warrior will take after defeating the first archer then moving into range.
health -= total_power unless enemy[0]-2 == @warrior_position
health -= total_power*2 if enemies.size > 1
File warrior_turn.rb was updated.
def next_turn
return attack if check.threat_in_front?
return walking(:backward) unless check.clear_to_east_wall?
return rest if check.health_needs_replenish?(warrior.health,@recon_team.warrior_position.first + 2)
return walking(:backward)
if check.distance_rest?(warrior.health) && check.step_back_from_distance_attack?
return rest if check.distance_rest?(warrior.health)
walking(:forward)
end
end
File recon_check.rb
# frozen_string_literal: true
require 'pry'
# Class looks for threats about to happen to warrior
class ReconCheck
attr_reader :warrior, :recon, :turn_end_health
ENEMIES = {
'Sludge' => { health: 12, power: 3 },
'Archer' => { health: 7, power: 3 },
'Thick Sludge' => { health: 24, power: 3 },
'Wizard' => { health: 3, power: 11 }
}.freeze
LONG_DISTANCE_ENEMIES = %w[Archer Wizard 'Thick Sludge'].freeze
STAIRS = %w[stairs].freeze
EAST_WALL = 'east_wall'.freeze
WEST_WALL = 'west_wall'.freeze
SPACE = 'space'.freeze
WALLS = [EAST_WALL, WEST_WALL].freeze
CAPTIVE = 'captive'.freeze
def initialize(recon_team, recon)
@recon = recon
@warrior_position = recon_team.warrior_position.first
@warrior_direction = recon_team.warrior_direction(@warrior_position)
end
def health_needs_replenish?(health, position)
return false unless enemy_on_next_space?(position)
enemy = recon[position]
return false unless enemy
return false if enemy[:name] == 'Archer'
enemy_stats = ENEMIES[enemy[:name]]
enemy_stats && (enemy_stats[:health] / 5) >= (health / enemy_stats[:power])
end
def distance_rest?(health)
enemies = recon.select { |space, value| (space - (@warrior_position+1)).abs <= 4 && LONG_DISTANCE_ENEMIES.include?(value[:name]) }.sort.to_h
return false if enemies.empty?# || enemies.keys.include?(@warrior_position+3)
enemy = enemies.first
total_power = ENEMIES.dig(enemy[1][:name], :power).to_i
total_enemy_health = ENEMIES.dig(enemy[1][:name],:health).to_i
health -= total_power unless enemy[0]-2 == @warrior_position
health -= total_power*2 if enemies.size > 1
(total_enemy_health / 5) >= (health / total_power)
end
def step_back_from_distance_attack?
recon.any? { |space, _| (space == @warrior_position + 2 || space == @warrior_position + 3) && LONG_DISTANCE_ENEMIES.include?(recon[space][:name]) }
end
def threat_in_front?
enemy_in_locations?(@warrior_position + 1, @warrior_position + 1)
end
def threat_from_behind?
enemy_in_locations?(@warrior_position - 2, @warrior_position)
end
def long_range_threat?
enemy_in_locations?(@warrior_position - 2, @warrior_position + 2)
end
def enemy_on_next_space?(position)
enemy_in_locations?(position, position)
end
def enemy_in_locations?(local1, local2)
recon.any? do |pos, space|
pos.between?(local1, local2) && ENEMIES.key?(space[:name])
end
end
def captive_in_area?
enemy_space = [recon[@warrior_position + 1], recon[@warrior_position - 1]]
enemy_space.map{|space| space[:name]}.uniq.include?(CAPTIVE)
end
def clear_to_east_wall?
return false unless east_wall_found?
spaces = recon.select{|key, _| key.between?(-1, @warrior_position) }
space_names = spaces.values.map{|d| d[:name]}.uniq
(space_names - [SPACE, EAST_WALL]).size == 0
end
def east_wall_found?
recon[-1]&.any? || false
end
def captive_is
space = recon[@warrior_position + 1]
return :backward if space.nil? || space[:name] != CAPTIVE
:forward
end
def long_distance_enemy?
enemy_spaces = [recon[@warrior_position + 1], recon[@warrior_position + 3]]
space_names = enemy_spaces.values.map{|space| space[:name]}.uniq.to_set
LONG_DISTANCE_ENEMIES.any?{|enemy| space_names.include?(enemy)}
end
def long_distance_attack?
return false if recon.empty?
recon.any? do |pos, space|
LONG_DISTANCE_ENEMIES.include?(space[:name]) && [@warrior_position + 1, @warrior_position + 3].include?(pos)
end
end
end
These updates get me past level 6 and still work for all prior levels. Level 7 needs an update but this one I expect not to be as mind bending. The issue on level 7 is going to be how I handle a “pivot” instead of just walking backwards. I may be able to attack backward too which could also fix the level 7 break. Anyways until next level up….


Leave a comment