18
\$\begingroup\$

Historical Background

The shield wall is a tactical war formation that dates back to at least 2500 BC. It consisted of warriors overlapping their shields with those of their companions to form a 'wall'. The appeal of the tactic comes from the fact that even the most unskilled warrior could fight in a wall as long as they had a shield and a weapon. Because of the proximity of the walls, there was little space to move around, and the battle usually became a shoving match fought with sharp weapons.

The Challenge

Your task is to create a program or function that, given two arrays/lists/vectors of warriors as input, decides the outcome of the battle. The lists will represent a single-line wall of shields, and they will follow a specific notation:

Vikings:

The nordic warriors had a fierce drive for battle. During the late 8th through the mid 11th centuries, Danish vikings invaded the kingdoms of Britain looking for riches and farmable land. For the purpose of this challenge, these are the vikings' warriors:

  • The Jarl: Usually found leading his men from the center of the wall, jarls were the leaders of the viking hordes. Takes 15 damage to die, and deals 2 damage per round.
  • The Berserker: Although fantasy has greatly twisted the image of the berserkers, these warriors were known to fight in a trance-like fury without any kind of protection other than their shields. Takes 6 damage to die, and deals 3 damage per round.
  • The Chieftain: Chieftains were rich men who had free men at their service. They'd usually have earned great glory and riches in battle. Takes 10 damage to die, and deals 2 damage per round.
  • The Free Men: Warriors that served a chieftain. They were sworn to fight for their lords until death. Takes 8 damage to die, and deals 1 damage per round.
  • The Skald: Skalds, usually translated as bards, were free men who were hired to write poems, stories or songs about the great deeds of the nordic warriors. Takes 8 damage to die, and gives each adjacent warrior 1 bonus damage. Skalds deal no damage. Warriors cannot gain more than 1 bonus damage this way.

Saxons:

The Saxons came to settle in Britain from continental Europe following the demise of the Roman Empire in the 5th century. For the purposes of this challenge, there are the saxons' warriors:

  • The Earl: Ealdormen, commonly called Earls, were members of the higher nobility. They usually held great streches of land and had hundreds or even thousands of sworn men. Takes 20 damage to die, and deals 1 damage per round.
  • The Knight: For lack of a better term, the knights were minor noblemen who owned some land. In most cases, knights were sworn servants to an Earl. Takes 10 damage to die, and deals 2 damage per round.
  • The Warrior: Common men, usually minor noblemen without land or peasants who served a knight. When adjacent to a Knight or Earl, warriors have a +1 damage bonus. Takes 8 damage to die, and deals 2 damage per round.
  • The Fyrd: The Fyrd was a militia-like group of free men, usually poor farmers, who'd bring any weapon (or weapon-like farming implement) they had to fight in the wall. Takes 5 damage to die, and deals 1 damage per round.
  • The Priest: Priests were highly valued in early Saxon culture, being heralds of the words of God. Priests take 15 damage to die, and prevent up to 1 damage each adjacent warrior would be dealt. Priests deal no damage. Priests cannot prevent more than 1 damage to a warrior.

The Wall

Walls meet each other at their centers. Each round, each warrior assigns damage to the warrior directly in front of it or, if there's no living warrior in front of it, the diagonally adjacent living warrior with least health remaining. If there is a tie, choose the warrior closer to the edge of the wall.

Example:

Vikings
[M,M,M,B,B,C,J,C,B,B,M,M,M]
[F,F,F,W,W,K,E,K,W,W,F,F,F]
Saxons

To make matters easier, let's convert these walls into numbers:
Round 0:
 M M M B B C  J  C  B B M M M
[8,8,8,6,6,10,15,10,6,6,8,8,8]
[5,5,5,8,8,10,20,10,8,8,5,5,5]
 F F F W W K  E  K  W W F F F

Round 1: Notice that 2 of the Saxons' warriors are adjacent to Knights, so they have a +1 damage bonus.
 M M M B B C J  C B B M M M
[7,7,7,4,3,8,14,8,3,4,7,7,7]
 | | | | | | || | | | | | |
[4,4,4,5,5,8,18,8,5,5,4,4,4]
 F F F W W K E  K W W F F F

Round 2: 
 M M M B B C J  C B B M M M
[6,6,6,2,0,6,13,6,0,2,6,6,6]
 | | | | | | || | | | | | |
[3,3,3,2,2,6,16,6,2,2,3,3,3]
 F F F W W K E  K W W F F F

Round 3: Remember to collapse the arrays to account for dead warriors. Also, notice that the 2 outermost Fyrd are now attacking the diagonally adjacent viking. 
   M M M B C J  C B M M M
  [4,5,4,0,4,12,4,0,4,5,4]
  /| | | | | || | | | | |\
[2,2,2,1,0,4,14,4,0,1,2,2,2]
 F F F W W K E  K W W F F F

Round 4: Notice once again the saxon Warriors next to the Knights dealing 3 damage:
   M M M C J  C M M M
  [2,4,1,2,11,2,1,4,2]
  /| | | | || | | | |\
[2,1,1,0,2,12,2,0,1,1,2]
 F F F W K E  K W F F F
Round 5:
 M M M C J  C M M M
[1,3,0,0,10,0,0,3,1]
 | | | | || | | | |
[1,0,0,0,10,0,0,0,1]
 F F F K E  K F F F

Round 6: 
    M M J M M
   [1,2,9,2,1]
     \| | |/   
     [0,8,0]
      F E F
Rounds 7 and 8:
      M M J M M         M M J M M
     [1,2,8,2,1]       [1,2,8,2,1]
         \|/               \|/ 
         [4]               [0]
          E                 E  

Output: Viking victory.

Rules:

  • Default Loopholes apply.
  • You can use any convenient IO method.
  • This is , so shortest code (in bytes, per language) wins.
  • You may not assume the lists will have the same length, but they will always be alignable at their centers (there will always be an odd number of warriors in each list if the lists are of different sizes).
  • You may output any truthy/falsey value. Please specify in your answer the equivalents of "Viking/Saxon victory".
  • The loser is determined when all the warriors of a wall are dead.
  • If you ever end up with walls that are not alignable during the code execution, align them as centrally as possible, leaving one extra warrior on the longer wall to the right side. E.g.:

      [M,M,M,J,M,M,M]
        [K,E,K,W];
    
          [B,B,B,J]    
    [K,K,W,W,K,E,K,W,W,K,K]
    
  • Feel free to try and test your code with any setup of walls, not just the ones in the test cases.

Test Cases:

V: [M,M,B,C,B,C,J,C,B,C,B,M,M]
S: [F,F,W,K,W,K,E,K,W,K,W,F,F]
O: Viking victory.
------------------------------
V: [M,M,M,M,M,M,M,M,M,M]
S: [W,W,W,W,W,W,W,W,W,W]
O: Saxon victory.
------------------------------
V: [B,C,M,B,C,M,M,C,B,M,C,B,M]
S:   [W,F,W,F,E,E,E,F,W,F,W]
O: Viking victory.
------------------------------
V:         [B,B,B,J,B,B,B]
S: [W,W,W,W,K,K,K,E,K,K,K,W,W,W,W]
O: Saxon victory.
------------------------------
V: [J]
S: [E]
O: Viking victory.
------------------------------
V: [C,C,C,C,B,B,M,M,M,M,J,J,J,M,M,M,M,B,B,C,C,C,C]
S: [K,K,K,K,K,K,K,K,K,K,W,E,W,K,K,K,K,K,K,K,K,K,K]
O: Saxon victory.
------------------------------
V: [M,M,S,C,B,J,B,C,S,M,M]
S: [F,K,P,W,K,E,K,W,P,K,F]
O: Saxon victory.
------------------------------
V: [S,S,S,...,S]
S: [P,P,P,...,P]
O: UNDEFINED (since both priests and skalds deal no damage, you can output anything here.)
------------------------------

There are some historical inaccuracies. Feel free to point them out and I'll do my best to fix them.

\$\endgroup\$
  • \$\begingroup\$ Link to the Sandbox \$\endgroup\$ – J. Sallé Nov 21 '17 at 15:54
  • \$\begingroup\$ Can we define other symbols instead of the first letters of the names, for example numbers 0-9? \$\endgroup\$ – NieDzejkob Nov 21 '17 at 16:19
  • \$\begingroup\$ @NieDzejkob sure thing. Just make sure you specify in your answer which symbols were used for which warrior. \$\endgroup\$ – J. Sallé Nov 21 '17 at 16:21
  • 3
    \$\begingroup\$ Would it be considered cheating to take input as their properties rather than letters? (example as (health, damage, damagebonus, protbonus)) \$\endgroup\$ – HyperNeutrino Nov 21 '17 at 17:02
  • \$\begingroup\$ @HyperNeutrino I'm not exactly sure, but I think it'd be okay? I don't see how that could give you a major advantage. As I told NieDzejkob, as long as you specify in your answer what's representing each warrior, go for it. \$\endgroup\$ – J. Sallé Nov 21 '17 at 17:41
3
\$\begingroup\$

Python 2, 576 573 565 554 540 549 bytes

O=[(0,0)]
g=lambda D,W,i:D[i-1]*(W[i-1]<1)+D[i]+D[i+1]*(W[i+1]<1)
h=lambda*V:[v for v in zip(*V)if v[1]>0]
def f(v,s):
 l,L=len(v),len(s);m=max(l,L);a,b=(L-l)/2,(l-L)/2;V,U=zip(*O+O*a+v+O*a+O+O);S,T=zip(*O+O*b+s+O*b+O+O);z=[0]*(m+2);w=z[:];r=range(1,m+1);U=list(U);T=list(T)
 for i in r:w[i]=[0,2,3,2,1,0][V[i]]+(5in V[i-1:i+2:2])*(V[i]<5);z[i]=[0,1,2,2+({1,2}&set(S[i-1:i+2:2])>set()),1,0][S[i]]
 for i in r:U[i]-=g(z,V,i);d=g(w,S,i);T[i]-=d-(d>0)*(5in S[i-1:i+2:2])
 V=h(V,U);S=h(S,T)
 if([],[])<(V,S)!=(v,s):return(f(V,S)if S else'V')if V else'S'

Try it online!

\$\endgroup\$
  • \$\begingroup\$ If I understand correctly, this bit: (5in V[i-1:i+2:2]) implies that adjacent skalds can inflict damage. You may need a ...*(V[i]!=5) there. Test: print f([S,S],[P]) # says V but should be a Draw \$\endgroup\$ – ngn Nov 25 '17 at 15:19
  • \$\begingroup\$ @ngn Thanks for that :) \$\endgroup\$ – TFeld Nov 26 '17 at 12:54
2
\$\begingroup\$

APL (Dyalog Classic), 128 bytes

{t l d b p←(-⌊2÷⍨+/0=⊃⍵)∘⌽¨⍵⋄l+←e+3+/0,0,⍨(0=t)×e←(×≢¨p∩¨h)-⊖d+×≢¨b∩¨h←3,/0,t,0⋄⍵≡a←↑¨(⊂↓l>0)/¨¨↓¨t l d b p:0⋄0∊s←+/l>0:×-/s⋄∇a}

Try it online!

There are two functions in the TIO link: g is the golfed function above and f is an ungolfed function that accepts a pair of strings, converts them to a suitable representation and calls the golfed function.

The input is five matrices: t warrior types as ints; l life; d damage; b what warrior types give bonus when adjacent; p same for protection. The matrices consist of two rows - Vikings and Saxons. If their warriors are not the same number, the matrices must be 0-padded, though not necessarily centred. The result is 1/¯1 for Viking/Saxon victory or 0 for a draw.

{
  t l d b p←(-⌊2÷⍨+/0=⊃⍵)∘⌽¨⍵ ⍝ centre the matrices
  ⍝ (-⌊2÷⍨+/0=⊃⍵) is a pair of numbers - by how much we should rotate (⌽) the rows
  ⍝       +/0=⊃⍵  how many dead? (⊃⍵ is the types, dead warriors have type 0)
  ⍝  -⌊2÷⍨        negated floor of half

  l+←e+3+/0,0,⍨(0=t)×e←(×≢¨p∩¨h)-⊖d+×≢¨b∩¨h←3,/0,t,0 ⍝ compute and apply effective damage
  ⍝ h←3,/0,t,0  are triples of types - self and the two neighbours
  ⍝ b∩¨h        for each warrior intersect (∩) h with his bonus-giving set b
  ⍝ ×≢¨         non-empty? 0 or 1
  ⍝ d+          add to the damage normally inflicted
  ⍝ ⊖           reverse vertically (harm the enemy, not self)
  ⍝ (×≢¨p∩¨h)   same technique for protections (neighbouring priests)
  ⍝ e←          remember as "e" for "effective damage"; we still need to do the diagonal attacks
  ⍝ (0=t)×      zero out the attacks on living warriors
  ⍝ 3+/0,0,⍨    sum triples - each warrior suffers the damage intended for his dead neigbours
  ⍝ e+          add that to the effective damage
  ⍝ l+←         decrease life ("e" is actually negative)

  ⍵≡a←↑¨(⊂↓l>0)/¨¨↓¨t l d b p:0 ⍝ remove dead; if no data changed, it's a draw
  ⍝ ↓¨          split each matrix into two row-vectors
  ⍝ (⊂↓l>0)     boolean mask of warrios with any life left, split in two and enclosed
  ⍝ /¨¨         keep only the survivors
  ⍝ ↑¨          mix the pairs of rows into matrices again, implicitly padding with 0-s
  ⍝ a←          call that "a" - our new arguments
  ⍝ ⍵≡a ... :0  is "a" the same as our original arguments? - nothing's changed, it's a draw

  0∊s←+/l>0:×-/s ⍝ if one team has no members left, they lost
  ⍝ l>0         bitmask of survivors
  ⍝ s←+/l>0     how many in each camp
  ⍝ 0∊          has any of the two armies been annihilated?
  ⍝ :×-/s       if yes, which one? return sign of the difference: ¯1 or 1, or maybe 0

  ∇a ⍝ repeat
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.