• Welcome to the new COTI server. We've moved the Citizens to a new server. Please let us know in the COTI Website issue forum if you find any problems.

[HG] Slugfest with the 154th

Hi

I'm taking a break from a nasty code problem, so I'll offer a design for your auto-system. Warning that I have not played TCS / HG in a LONG time, so I can't remember some of the mechanic specifics. If these will significantly change how the algorithm must work, they have been noted.

An "automated" system for HG combat could be as simple as something like an auto-roller. This would save you lots of time just by eliminating the rolling of dice and looking up of tables. and automatically applying damage to systems.

If you want a fully automated tester, you need the auto-roller anyway, but you also need five other modules for decisions, and all of these can be done with a person choosing an option manually. I will argue later which of these can be trivially done with automation, and which would be best done with a human at first.

1) Main or Reserve?
If a ship can inflict damage on its opponents, put it in "main" if it can't put it in reserve.

You may want to program something that puts ships into reserve if they double their base vulnerability to enemy fire (base "to hit" goes from "9" to "7" for the main weapons of the opponent: go repair the computer or drives) or they lose 50% of their chance to hit the enemy (base "to hit" changes from a "7" to a "9", go repair weapon batteries or computer)

2) Target Selection.
"Blue" ship 1 should fire at "Red" ship 1,
"Blue" ship 2 should fire at "Red" ship 1,
"Blue" ship 3 should fire at "Red" ship 2,
"Blue" ship 4 should fire at "Red" ship 2
(Wash, rinse repeat. NB that this may have each ship firing at multiple targets)

3) Choice of weapon roles
No-Brainers:
PAWs, Missiles Meson Guns: shoot bad guys
Repulsors: Missile Defence only
Energy weapons: Missile Defence at long range

Role choices to be made:
Lasers: Offence or Missile Defence
Energy weapons: same choices as lasers *at short range only*
Sand: Missile Defence OR Beam Defence. Since you get to choose after fire is resolved, this is trivial: stop the missiles first, then the beams (assumes that nukes are in use)

All of the role choices revert to "trivial" if your opponent has no missiles

4) Choice of what to intercept with active defences. Against Cap Ships, algorithmically I'd start by stopping the "easiest" attack with the "weakest" defence and working my way up, since all "hits" are the same. I'd probably also stop all nuke missile hits before starting on beam hits.

5) What to repair if your ship is in the reserve. Reviving the frozen watch (if needed) is a no-brainer, the rest needs to be based on why you pulled the ship into the reserve in the first place...

_________________________________________
Simple Decisions: (AKA cheatng to make the tester easier)

1) Leave all ships in the line until they blow up. Yes, it's unrealistic, but damage control should favor both sides equally: running a few tens or hundreds of the same scenario should give roughly the same results

2) Target Selection: Use a player to set up taregets the first time you do this. How long will it take for a person to point batteries with a decent interface? even running massive multiples of battles, it's probably easier for a person to do this than to code, and once they have the "hang" of optimal target selection, they can probably give you a good idea what the allocation algorithm looks like. This will also interact strongly with "weapon roles" below, so one target selection option should *always* be "All blue ships shoot at red ship #1, all red ships shoot at blue ship #1"

3) Weapon Roles: Run 4 sets of scenarios, with the sides alternating "Max Offense" and "Max Defence" (offense vs offensie, offence vs defence, defence vs offense, defence vs defence) this should give you an idea how the ships stack up against each other.

4) I believe that I already have the suggested algorithm. I can't remember if you allocate all active defences and then roll them, or if this is sequential (I missed with sand battery #1, so now I'll try sand battery #2) If it is sequential, then this is easy to automate, if not then it gets a bit trickier.
Remember to never allocate active defence on targets that are guarenteed intercepted with passive defences (Nuke dampers)

5) What to repair in the reserve: Dealt with in point 1) fight to destruction. The only exception that springs to mind is if you aren't allowed to revive the frozen watch unless you are in the reserve

Scott Martin

HG abuse testers are a lot easier than figuring out UI's for graph theory applications...
 
Fire should not be ship to ship, but rather allocated on how much firepower is expected to be needed to defeat the target.

For spinal meson guns in straight HG combat this requires at least two factor-E+ meson guns per target, no matter the size of the target.

Spinal PAWs should be used on lightly armored vessels or smaller ships of high target value; they should =not= be allocated to large, heavily armored targets (basically subtact 1/2 the target's armor from the size code of the PAW, if the result is greater than the size code of the target, FIRE!)

Missiles should be allocated at least two batteries per 1000 dtons of target and work best against:
</font>
  • Lightly armored targets without nuke dampers (use nuke missiles)</font>
  • Ships without nuke dampers (use nuke missiles)</font>
  • Lightly armored ships with nuke dampers (use HE missiles)</font>
  • Armored ships with nuke dampers (use nuke missiles, allocate six times as many)</font>
Minor offensive weapons should be allocated to enemy escorts (ships less than 10,000 dtons). Big ships should save light weapons for anti-missile work. For anti-ship work light weapons should be allocated at the same rate as missiles (two per 1000 dtons of target, minimum).

Allocation of firepower should be doubled for each TL the target is higher than the firing ship. So a TL13 ship firing at a TL15 ship should allocate four times the firepower recommended above.

Target selection should be based on the value of the target, and =that= should be based on factors like:
</font>
  • How much damage the target can do (enemy meson guns first!)</font>
  • Any with carried craft still aboard (rider tenders, carriers)</font>
  • Any special vessels needed for the enemy's mission (assault ships, tankers, etc)</font>
  • Any especially vulnerable ships</font>
 
Originally posted by robject:
[/CODE]Kokirrak Battle Squadron
</font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;"> Kokirrak_BatRon Battle Squadron
1200000 tons, MCr 810612

6 x Kokirrak Dreadnaught
200000 tons, MCr 135102

(and what else?)</pre>
Plankwell Battle Squadron
</font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;"> Plankwell_BatRon Battle Squadron
1200000 tons, MCr 722964

6 x Plankwell Dreadnaught
200000 tons, MCr 120494

(and what else?)</pre>[/QUOTE]Tigress Battle Squadron
</font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;"> Tigress_BatRon Battle Squadron
3000000 tons, MCr 2176326

6 x Tigress Dreadnaught
500000 tons, MCr 362721

(and what else?)</pre>[/QUOTE]
[/quote]Hmm. I see that you've already reduced the battleship squadrons by 25%. A Tigress is eight Tigresses (plus an unspecified number of auxiliaries). I don't have FS here, so I won't swear to it, but I think it is explicitly stated that Kokirrak and Plankwell squadrons likewise have 8 battleships. Or maybe it's just implied somewhere. Or maybe I'm just channeling my own ideas. But the Tigresses I'm sure about.

How about compromising on seven battleships for each squadron? Maybe one is getting its annual maintenance ;) .


Hans
 
A BatRon of riders is 6 to 8 riders carried by a tender, page 9 of Supplement 9.
A BatRon of Tigresses is 8 BBs, a BatRon of Kokirraks is also 8 BBs.
The size of a Plankwell BatRon is not given, unfortunately.
 
OK, moving this thread cautiously forward, here's the data record for the Kinunir.

The paired numbers for the weapons represents batteries, and batteries bearing, respectively. Note that I have split missiles into HE and Nukes -- that's data not available in the plain USP.

The list for the drives and computer allows for backup systems to exist.

</font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">---
Units:
unit one:
ship type: BC
tonnage code: A
configuration: 2
j-drives: [4]
m-drives: [4]
p-plants: [7]
computers: [7 fib]
armor: 0
sandcasters: 0
meson screens: 0
nuclear damper: 5
black globe: 1
repulsors: 0
lasers: [5,2]
energy: [0,0]
PA: [2,2]
meson: [0,0]
HE missiles: [0,0]
nukes: [2,2]
fighter squad: 0
volume: 1250
crew: 45
tl: 15
agility: 1
frozen watch: 0
fuel tankage: 588
fuel level: 588
marines: 35</pre>[/QUOTE]
 
Next is a way to represent simple decision rules; that is, whether to fire weapon X at ship Y or not, or when to allocate laser batteries to missile defense.

This means I need a way to represent when an attack is worth the effort. Ultimately this goes back to the tables, I suppose: an attacking battery factor is compared against all defending ships (i.e. active defenses and armor), yielding a set of probabilities to hit. The ship with the largest probability to be hit is chosen.

Beyond the table, though, are a few choices to make, regarding lasers used as defense of offense for instance. Is that simply a comparison of the missile capabilities of the other side, resulting in a "attack | defend" for each laser battery on the attacking side?
 
Okay, here's the combat tables, best I can manage.

</font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">Target Size DM: [ -2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,2 ]

Missile:
Factor: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
To Hit: [ 6, 6, 5, 5, 4, 4, 3, 3, 2 ]
Sand or Beam: [ 4, 3, 2, 1, 0, -1, -2, -3, -4 ]
Repulsor: [ 14, 13, 12, 11, 10, 9, 8, 7, 6 ]
Damper: [ 9, 8, 7, 6, 5, 4, 3, 2, 1 ]

Beam:
Factor: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
To Hit: [ 8, 7, 7, 6, 6, 5, 5, 4, 4 ]
Sand: [ 5, 4, 3, 2, 1, 0, -1, -2, -3 ]

PA:
Factor: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T ]
To Hit: [ 9, 8, 7, 7, 6, 6, 5, 5, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0 ]

Meson:
Factor: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, G, H , J, K, L, M, N, P, Q, R, S, T ]
To Hit: [ 9, 9, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4 , 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ]
Screen:
- [ 16, 15, 15, 14, 14, 13, 13, 12, 12, 9, 9, 8, 8, 7, 7, 6, 6 , 5, 5, 4, 4, 3, 3, 2, 2, 1, 1 ]
- [ 16, 16, 15, 15, 14, 14, 13, 13, 12, 10, 9, 9, 8, 8, 7, 7, 6 , 6, 5, 5, 4, 4, 3, 3, 2, 2, 1 ]
- [ 17, 16, 16, 15, 15, 14, 14, 13, 13, 10, 10, 9, 9, 8, 8, 7, 7 , 6, 6, 5, 5, 4, 4, 3, 3, 2, 2 ]
- [ 17, 17, 16, 16, 15, 15, 14, 14, 13, 11, 10, 10, 9, 9, 8, 8, 7 , 7, 6, 6, 5, 5, 4, 4, 3, 3, 2 ]
- [ 18, 17, 17, 16, 16, 15, 15, 14, 14, 11, 11, 10, 10, 9, 9, 8, 8 , 7, 7, 6, 6, 5, 5, 4, 4, 3, 3 ]
- [ 18, 18, 17, 17, 16, 16, 15, 15, 14, 12, 11, 11, 10, 10, 9, 9, 8 , 8, 7, 7, 6, 6, 5, 5, 4, 4, 3 ]
- [ 19, 18, 18, 17, 17, 16, 16, 15, 15, 12, 12, 11, 11, 10, 10, 9, 9 , 8, 8, 7, 7, 6, 6, 5, 5, 4, 4 ]
- [ 19, 19, 18, 18, 17, 17, 16, 16, 15, 13, 12, 12, 11, 11, 10, 10, 9 , 9, 8, 8, 7, 7, 6, 6, 5, 5, 4 ]
- [ 20, 19, 19, 18, 18, 17, 17, 16, 16, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5 ]

Configuration Modifiers:
- [ 12, 12, 12, 11, 11, 11, 10, 10, 10, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3 ]
- [ 11, 11, 10, 10, 10, 9, 9, 9, 8, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1 ]
- [ 10, 9, 9, 9, 8, 8, 8, 7, 7, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0 ]
- [ 7, 7, 6, 6, 6, 5, 5, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- [ 6, 5, 5, 5, 4, 4, 4, 3, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- [ 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0 ]
- [ 15, 15, 14, 14, 14, 13, 13, 13, 12, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5 ]
- [ 4, 4, 4, 3, 3, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- [ 14, 13, 13, 13, 12, 12, 12, 11, 11, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4 ]

Damage tables:
Surface: [ crit, int, int, int, m2, f3, w3, m1, f2, w2, m1, f1, w1, w1, f1, w1, w1, f1, w1, w1 ]
Radiation: [ crit, r1, c4, r1, c3, r1, c2, c2, w4, c2, w3, c1, w2, c1, w2, w1, w1, w1, w1, w1 ]
Interior: [ crit, crit, crit, fx, c2, s3, j2, p2, r1, c1, s2, j1, p1, c1, s1, j1, p1, s1, j1, p1 ]
Critical: [ vap, brx, cx, mx, sx, jx, hx, px, c1, Sx, zx ]</pre>[/QUOTE]
 
SO then, the process seems to be this:

Each time a weapon is considered for attack:

Determine the probability of it to hit each opposing ship, and the general severity of damage it can deliver to each opposing ship. (Not sure how to best do this. Perhaps something simple, like "surface = 1, radiation = 1, internal = 5, crit = 25"?).

Maybe there are shortcuts to this process.


For every weapon on the opposite side, determine:
1. The probability of it to hit each opposing ship, and
2. The general severity of damage it can deliver to each opposing ship.

Maybe there are shortcuts to this process.


Then

For every ship on the opposite side, calculate the sum destructive value of its functioning weaponry.

Once this is done, each side may then prioritize targets, from most destructive to least, and pummel them until satisfactorily beaten down.


When a combat round is complete, the inflicted damages can then be officially applied to the ships, and the process repeats.
 
I have some code that handles rolling the hit and damage procedures.

Here's a contrived 10K ton Battle Rider:

(defparameter ship10k
(make-ship :tons 10000 :m-drive (make-system :factor 6)
:power-plant (make-system :factor 18)
:agility (make-system :factor 5) :armor (make-system :factor 15)
:missile (make-battery :type 'nuclear-missile :factor 7 :count 8)
:meson (make-battery :type 'meson :factor (character-to-factor #\N) :count 1)
:meson-screen (make-system :factor 9)
:nuclear-damper (make-system :factor 9)))


Here it's firing it's spinal at a sister ship, essentially.


[4]> (fire-battery (ship-meson ship10k) 1 ship10k ship10k nil)
#S(FIRE-RESULT :HITS 1 :EXTRA-HITS 13 :CRITICAL-HITS 3)


So, we got 14 (1 + 13) hits.

[5]> (roll-damage (ship-meson ship10k) 14 ship10k)
((#S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 2 :IS-RADIATION T) #S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 3 :IS-RADIATION T)
#S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 2 :IS-RADIATION T) #S(DAMAGE-RESULT :SYSTEM CREW :FACTOR 1 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM CREW :FACTOR 1 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM WEAPON :FACTOR 4 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 2 :IS-RADIATION T) #S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 4 :IS-RADIATION T)
#S(DAMAGE-RESULT :SYSTEM WEAPON :FACTOR 4 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 2 :IS-RADIATION T)
#S(DAMAGE-RESULT :SYSTEM CREW :FACTOR 1 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 2 :IS-RADIATION T)
#S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 4 :IS-RADIATION T) #S(DAMAGE-RESULT :SYSTEM COMPUTER :FACTOR 2 :IS-RADIATION T)
#S(DAMAGE-RESULT :SYSTEM CREW :FACTOR 1 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM POWER-PLANT :FACTOR 2 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM SCREEN-DISABLED :FACTOR 0 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM CREW :FACTOR 1 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM SCREENS :FACTOR 3 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM JUMP :FACTOR 2 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM CREW :FACTOR 1 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM SCREENS :FACTOR 3 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM JUMP :FACTOR 2 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM SCREENS :FACTOR 3 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM JUMP :FACTOR 2 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM CREW :FACTOR 1 :IS-RADIATION NIL)
#S(DAMAGE-RESULT :SYSTEM SCREENS :FACTOR 3 :IS-RADIATION NIL) #S(DAMAGE-RESULT :SYSTEM FUEL-TANKS-SHATTERED :FACTOR 0 :IS-RADIATION NIL))
1)


You'll note the 1 at the end, during the normal damage process, we managed to get 1 critical hit (as evidenced at the end by the Fuel Tanks Shattered result). Both the radiation and interior explosion tables have potential crits on them. In theory, there's another 3 crits pending from the original attack not handled yet.

This is as far I got. Essentially high level primitives to calculate hits, and calculate damage. I lack applying the damage, much less "fighting" a ship. Applying damage is straight forward. Fighting a ship could be, fighting a fleet is a bit more nuanced.

But nobody seemed particularly interested, so I stopped.

Funny, something I hadn't realized until now (been at least 6 months since I've looked at this), TL only affects design, but not combat. I noticed that when I dumped the ship.


[10]> ship10k
#S(SHIP :TL 0 :CONFIGURATION 1 :TONS 10000
:POWER-PLANT #<SYSTEM :FACTOR 18 :ORIG-FACTOR 18>
:M-DRIVE #<SYSTEM :FACTOR 6 :ORIG-FACTOR 6>
:J-DRIVE #<SYSTEM :FACTOR 0 :ORIG-FACTOR 0> :FUEL 0
:ARMOR #<SYSTEM :FACTOR 15 :ORIG-FACTOR 15>
:AGILITY #<SYSTEM :FACTOR 5 :ORIG-FACTOR 5>
:BRIDGE NIL
:CREW #<SYSTEM :FACTOR 0 :ORIG-FACTOR 0>
:COMPUTER #<COMPUTER :FACTOR 0 :ORIG-FACTOR 0 :BIS NIL>
:LASER #<BATTERY :TYPE LASER :FACTOR 0 :ORIG-FACTOR 0 :COUNT 0 :ORIG-COUNT 0 :FIRED 0>
:MISSILE #<BATTERY :TYPE NUCLEAR-MISSILE :FACTOR 7 :ORIG-FACTOR 7 :COUNT 8 :ORIG-COUNT 8 :FIRED 0>
:SAND #<BATTERY :TYPE SAND :FACTOR 0 :ORIG-FACTOR 0 :COUNT 0 :ORIG-COUNT 0 :FIRED 0>
:ENERGY #<BATTERY :TYPE PLASMA :FACTOR 0 :ORIG-FACTOR 0 :COUNT 0 :ORIG-COUNT 0 :FIRED 0>
:MESON #<BATTERY :TYPE MESON :FACTOR 22 :ORIG-FACTOR 22 :COUNT 1 :ORIG-COUNT 1 :FIRED 0>
:PA #<BATTERY :TYPE PA :FACTOR 0 :ORIG-FACTOR 0 :COUNT 0 :ORIG-COUNT 0 :FIRED 0>
:REPULSOR #<BATTERY :TYPE REPULSOR :FACTOR 0 :ORIG-FACTOR 0 :COUNT 0 :ORIG-COUNT 0 :FIRED 0>
:MESON-SCREEN #<SYSTEM :FACTOR 9 :ORIG-FACTOR 9>
:NUCLEAR-DAMPER #<SYSTEM :FACTOR 9 :ORIG-FACTOR 9>
:FLEET-TACTICS 0 :SHIP-TACTICS 0
:PILOT 0)


I noticed the TL was 0. Computers only affect combat in their differential, so I don't have one in this test case (they're both the same, no differential, no DM). The rules for a "valid" ship and those necessary for actual combat vary.

Anyway, if you have some one on one ships you want flung against each other, I can do that readily.
 
TCS

There is software that lets you assemble fleets for these games from a set of existing designs. What I have never had it the software to test the results when those two fleets meets and slug it out. What would I need to run your software?
 
There is software that lets you assemble fleets for these games from a set of existing designs. What I have never had it the software to test the results when those two fleets meets and slug it out. What would I need to run your software?

You need a Common Lisp system to run it on. I use CLISP.

I think I have it to where I can apply damage now, I haven't looked at it in some time. I think last time I looked I was trying to get a full round of combat going where Fleet A and B exchange salvoes and tally up the damage.
 
I'm familiar with it, but hardly fluent.

I find it pretty easy to do "stream of consciousness" style code in it.

All languages have some level of boiler plat, but Common Lisp is actually pretty concise.

I find it really easy to type. id-rather-type-with-hyphens than CamelCasingEverything, or_worse_underscores_everywhere, for example. That lack of a shift key actually adds up. I think the hyphens are easier to read.

Yea, there's a lot of parentheses, but the shift is on one hand, and the keys on another. So, less chording. In theory I can use alternate shift keys, (so C is "right shift, left C", but -- I don't. Left hand is my "modifier" hand [shift, alt, control]).

The REPL, the Read-Eval-Print-Loop, is completely usable in Common Lisp, more so than in most every thing else. So, my code has "no ui", it's just functions. I let the REPL do all the work.

I don't use EMACs as an interface, or anything like that. (EMACs provides a very robust interface to many Lisps). I use EMACs for the editor, as I find it works better than vi for me, but I just ^X^S the buffer, and in Lisp I have a simple defun to reload the file. So, I just type (l) and it reloads. Easy.

I don't do a lot of Lisp, sometimes I like the structure enforced on my by other environments. Structure is nice because it's one less thing I have to worry about, even if I have to comply with it.

But for stuff like this, I could just "read" the HG rules, and "type it in". Most of the time it mostly just works.

The code looks like this (this is a selective excerpt demonstrating missile fire).
Code:
(defun make-hit-table (n)
  "many of the hit tables in high guard follow a simple pattern,
this function generates such tables"
  (let ((row-start n)
        (table (make-array '(9 9))))
    (dotimes (y 9)
      (let ((factor row-start))
        (dotimes (x 9)
          (setf (aref table x y) factor)
          (setf factor (max (- factor 1) 0))))
      (incf row-start))
    table))

(defparameter missile-hit-table #(6 6 5 5 4 4 3 3 2))

(defparameter missile-pen-beam (make-hit-table 5))
(defparameter missile-pen-repulsor (make-hit-table 15))
(defparameter missile-pen-damper (make-hit-table 10))

(defun lookup-pen-table (table attack-factor defense-factor)
  (let ((max-cols (+ (first (array-dimensions table)) 1))
        (max-rows (+ (second (array-dimensions table)) 1)))
    (if (and (< 0 attack-factor max-cols) (< 0 defense-factor max-rows))
        (aref table (- attack-factor 1) (- defense-factor 1))
        99)))

(defun lookup-hit-table (table attack-factor)
  (let ((max (+ (first (array-dimensions table)) 1)))
    (if (< 0 attack-factor max)
        (aref table (- attack-factor 1))
        99)))

(defun lookup-missile-hit (factor)
  (lookup-hit-table missile-hit-table factor))

(defun lookup-missile-pen-beam (missile-factor beam-factor)
  (lookup-pen-table missile-pen-beam missile-factor beam-factor))

(defun lookup-missile-pen-repulsor (missile-factor repulsor-factor)
  (lookup-pen-table missile-pen-repulsor missile-factor repulsor-factor))

(defun lookup-missile-pen-damper (missile-factor damper-factor)
  (lookup-pen-table missile-pen-damper missile-factor damper-factor))

(defun missile-to-hit (from-ship to-ship is-long-range)
  (let ((ship-dm (to-hit-dm from-ship to-ship))
        (range-dm (if is-long-range 0 -1)))
    (- (lookup-missile-hit (battery-factor (ship-missile from-ship)))
       ship-dm range-dm)))

(defun fire-missile (count from-ship to-ship is-nuclear is-long-range)
  (let* ((battery (ship-missile from-ship))
         (to-hit (missile-to-hit from-ship to-ship is-long-range))
         (base-hits (make-rolls count to-hit))
         (to-pen-laser (missile-to-pen-beam-sand from-ship to-ship nil))
         (to-pen-sand (missile-to-pen-beam-sand from-ship to-ship t))
         (to-pen-repulsor (missile-to-pen-repulsor from-ship to-ship))
         (to-pen-damper (missile-to-pen-damper from-ship to-ship)))
    (loop while (and (> base-hits 0) (ship-can-fire-sand to-ship))
       do
         (when (< (roll2d) to-pen-sand)
           (decf base-hits))
         (track-battery-fired (ship-sand to-ship)))
    (loop while (and (> base-hits 0) (ship-can-fire-laser to-ship))
       do
         (when (< (roll2d) to-pen-laser)
           (decf base-hits))
         (track-battery-fired (ship-laser to-ship)))
    (loop while (and (> base-hits 0) (ship-can-fire-repulsor to-ship))
       do
         (when (< (roll2d) to-pen-repulsor)
           (decf base-hits))
         (track-battery-fired (ship-repulsor to-ship)))
    (when (and is-nuclear (ship-has-nuclear-damper to-ship))
      (dotimes (i base-hits)
        (when (< (roll2d) to-pen-damper)
          (decf base-hits))))
    (make-fire-result :hits base-hits
                      :extra-hits (calculate-extra-hits battery base-hits)
                      :critical-hits (calculate-crits-for-hit battery base-hits to-ship))))

That final bit is the missile fire sequence, and right now I implicitly defend against all missiles. So this fires all of the sand, then all of the lasers, then all of the repulsers, then it has to penetrate the dampers. Reading this again, I should probably restructure it to penetrate the dampers first (why fire a weapon at a dead nuke), then the repulsers (can only be used against missiles anyway), then sand (are defensive only), then lasers (save these for last if we can). Obviously there's much work that could be done to better define the "strategy" of how and when to defend against missile fire, but that's a whole 'nother kettle of fish.

There's only a couple of nasty things I have to re-remember when I come back to this every few months. "How did I do that again?!?" Most of the code is pretty clear. I really should formalize damage as a structure, right now I just do list shenanigans with it. Get confused myself as to what's what when.

Heh, I just noticed I need to take into account the fuel status of the ship when calculating agility for DMs. Doesn't matter what the M-Drive is if there's no fuel.

Most folks think Lisp is just parens, CAR, CDR, and recursion. Just not so.

So far, whole thing is about 1300 lines.
 
I see what you mean about the parentheses, but thats only syntax and every language has its quirks. Ta for the perspective, it was useful :)
 
Back
Top