(game-module "panzer"
  (title "Panzer")
  (version "1.0")
  (blurb "base module for tactical-level WWII, Eastern Front")
  (variants
   (world-seen true)
   (see-all false)
   (world-size (80 40 25000))
   (real-time (0 0 0))
   ("Capture the Town" capture-the-town
    "Each side's goal is to capture the other side's town."
    (true
      (add town start-with 1)
      (add u* point-value 0)
      (add town point-value 1)
      ))
   ("Minefields" minefields
    "Minefields are present."
    (true
      ;; if this is enabled, the AI gets confused...
	  (table independent-density
	    (minefield clear 500)
	    (minefield woods 100)
	    )
      ))
   ("Rougher" rougher
    "Terrain is more hilly, harder to get a clear line of sight."
    (true
	  (add t* elevation-max 1000)
      ))
   ("Night" night
    "Everything is dark, visibility is reduced, etc."
    (true
	  (world (day-length 144))
      (set initial-day-part 72) ; midnight
      ))
   )
)

(terrain-type water (image-name "water") (char ".")
  (help "open water"))
(terrain-type swamp (char "=")
  (help "water, mud and thick vegetation - nearly impassable"))
(terrain-type gully (char "&")
  (help ""))
(terrain-type woods (image-name "forest") (char "%")
  (help "hinders visibility and combat"))
(terrain-type slope (image-name "goldenrod") (char "/")
  (help ""))
(terrain-type clear (image-name "khaki") (char "+")
  (help "open flat ground"))
(terrain-type thick-forest (image-name "forest")
  (subtype border)
  (help "impassable to both wheeled and tracked vehicles"))
(terrain-type stream (image-name "river-conn")
  (subtype connection) (subtype-x river-x)
  (help ""))
(terrain-type road
  (subtype connection) (subtype-x road-x)
  (help "faster travel for vehicles"))

(add (water swamp) liquid true)

(define cell-t* (water swamp gully woods slope clear))

;;; Ground is what doesn't require swimming.

(define ground (swamp gully clear woods slope))

;;; Vehicles require solid ground.

(define solid (gully clear woods slope))

;;; Wheeled vehicles can't deal with woods.

(define drivable (gully clear slope))

;; Distances are in meters.

(add t* elevation-min 100)
(add t* elevation-max 300)

(area (cell-width 400))

(add clear river-chance 5.00)

(table drawable-terrain
  (t* t* true)
  (stream (water swamp) false)
)

(set no-indepside-ingame true)

;;; Definitions of all the unit types.

;;; Random gen should do these in clumps?
(unit-type town (image-name "town20"))
(unit-type block)
(unit-type minefield)
(unit-type cmdpost (name "command post") (image-name "cmd-post")
  (acp-per-turn 1))

(add (town block minefield) speed 0)

;;; Russian unit types.

(unit-type rmg (name "MG") (image-name "pz-flak")
  (help "Russian 12.7mm machine gun"))
(unit-type r45 (name "45mm AT") (image-name "pz-at")
  (help "Russian 45mm anti-tank"))
(unit-type r57 (name "57mm AT") (image-name "pz-at")
  (help "Russian 57mm anti-tank"))
(unit-type r76at (name "76mm AT") (image-name "pz-at")
  (help "Russian 76mm anti-tank"))
(unit-type r122 (name "122mm AT") (image-name "pz-at")
  (help "Russian 122mm anti-tank - has a long reach"))
(unit-type r76h (name "76mm H") (image-name "pz-how")
  (help "Russian 76mm howitzer"))
(unit-type r82m (name "82mm M (Mot)") (image-name "pz-mortar")
  (help "Russian motorized 82mm mortar"))
(unit-type r82 (name "82mm M") (image-name "pz-mortar")
  (help "Russian 82mm mortar"))
(unit-type r120 (name "120mm M(r)") (image-name "pz-mortar")
  (help "Russian 120mm mortar - a powerful long-range hitter"))

(define r-arty (rmg r45 r57 r76at r76h r122 r82m r82 r120))

(add r-arty generic-name "arty")

(add r-arty acp-per-turn 1)
(add r-arty speed 0)
(add (r82m r82) speed 2.00)

(add r-arty acp-to-fire 1)

(add r-arty range ( 6  3  4  5 10 20 12 12 20))

(unit-type rengrs (name "engineer platoon(r)") (image-name "engr"))
(unit-type rrecon (name "recon platoon") (image-name "inf-plt"))
(unit-type rrifle (name "rifle platoon(r)") (image-name "inf-plt"))
(unit-type rguard (name "guards platoon") (image-name "inf-plt"))
(unit-type rsmg (name "SMG platoon(r)") (image-name "inf-plt"))

(define r-inf (rengrs rrecon rrifle rguard rsmg))

(add r-inf generic-name "inf")

(add r-inf acp-per-turn 2)

(unit-type rcav (name "cavalry") (image-name "cavalry")
  (acp-per-turn 6))

(unit-type rwag (name "wagon(r)") (generic-name "wagon") (image-name "wagon"))
(unit-type rtruck (name "truck(r)") (generic-name "truck") (image-name "truck"))
(unit-type rhalf (name "halftrack(r)") (generic-name "halftrack") (image-name "halftrack"))

(define r-transport (rwag rtruck rhalf))

(add r-transport acp-per-turn (6 24 20))

(unit-type su-152 (name "SU-152") (image-name "su-152"))
(unit-type su-76 (name "SU-76") (image-name "su-76"))
(unit-type su-85 (name "SU-85") (image-name "su-85"))
(unit-type su-100 (name "SU-100") (image-name "su-100"))
(unit-type jsu-122 (name "JSU-122") (image-name "jsu-122"))

(define r-td (su-152 su-76 su-85 su-100 jsu-122))

(add r-td generic-name "TD")

(add r-td acp-per-turn (14 18 22 16 14))
(add r-td acp-min (-14 -18 -22 -16 -14))

(add r-td acp-to-fire  (14 18 22 16 14))
(add r-td range        (10  5  8  8 10))

(unit-type kv85 (name "KV85") (image-name "kv85")
  (help "Early heavy tank"))
(unit-type t34 (name "T-34c") (image-name "t-34c")
  (help "The most common type of Russian tank"))
(unit-type t34/85 (name "T-34/85") (image-name "t-34-85")
  (help "A better T-34"))
(unit-type js2 (name "JS II") (image-name "js-2")
  (help "Heaviest Russian tank, but slow"))

(define r-tank (kv85 t34 t34/85 js2))

(add r-tank generic-name "tank")

(add r-tank acp-per-turn (20 22 22 16))
(add r-tank acp-min (-20 -22 -22 -16))

(add r-tank acp-to-fire  (20 22 22 16))
(add r-tank range        ( 8  6  8  8))

(define r-wheeled (rwag rtruck))

(define r-tracked (append rhalf r-td r-tank))

(define r-vehicle (append r-wheeled r-tracked))

(define r-armored (append rhalf r-td r-tank))

(define russian (append r-arty r-inf rcav r-transport r-td r-tank))

(add russian possible-sides "russian")

;;; German unit types.

(unit-type g50 (name "50mm AT") (image-name "pz-at")
  (help "German 50mm anti-tank"))
(unit-type g75 (name "75mm AT") (image-name "pz-at")
  (help "German 75mm anti-tank"))
(unit-type g88 (name "88mm AT") (image-name "pz-at")
  (help "German 88mm anti-tank"))
(unit-type g20 (name "20mm F") (image-name "pz-flak")
  (help "German 20mm flak"))
(unit-type g20q (name "20mmQUAD F") (image-name "pz-flak")
  (help "German 20mm quad flak"))
(unit-type g75h (name "75mm H") (image-name "pz-how")
  (help "German 75mm howitzer"))
(unit-type g150 (name "150mm H") (image-name "pz-how")
  (help "German 150mm howitzer - hard-hitting but shortish range"))
(unit-type g81 (name "81mm M") (image-name "pz-mortar")
  (help "German 81mm mortar"))
(unit-type g120 (name "120mm M(g)") (image-name "pz-mortar")
  (help "German 120mm mortar"))

(define g-arty (g50 g75 g88 g20 g20q g75h g150 g81 g120))

(add g-arty generic-name "arty")

(add g-arty acp-per-turn 1)
(add g-arty speed 0)

(add g-arty acp-to-fire 1)
(add g-arty range ( 5  6 20 10 10 12 12 12 20))

(unit-type gengrs (name "engineer platoon(g)") (image-name "engr")
  (help "German engineer platoon"))
(unit-type gsec (name "security platoon") (image-name "inf-plt")
  (help "German security platoon"))
(unit-type grifle (name "rifle platoon(g)") (image-name "inf-plt")
  (help "German rifle platoon"))
(unit-type gsmg (name "SMG platoon(g)") (image-name "inf-plt"))

(define g-inf (gengrs gsec grifle gsmg))

(add g-inf generic-name "inf")

(add g-inf acp-per-turn 2)

(unit-type gwag (name "wagon(g)") (generic-name "wagon") (image-name "wagon"))
(unit-type gtruck (name "truck(g)") (generic-name "truck") (image-name "truck"))
(unit-type ghalf (name "halftrack(g)") (generic-name "halftrack") (image-name "halftrack"))

(define g-transport (gwag gtruck ghalf))

(add g-transport acp-per-turn (6 24 20))

(unit-type sdkfz/1 (name "SdKfz 234/1") (image-name "sdkfz-234-1")
  (help "Weak, but fastest unit in the game"))
(unit-type puma (name "Puma"))
(unit-type sdkfz/4 (name "SdKfz 234/4") (image-name "sdkfz-234-4"))

(define g-car (sdkfz/1 puma sdkfz/4))

(add g-car generic-name "car")

(add g-car acp-per-turn (32 28 28))
(add g-car acp-min (-32 -28 -28))

(add g-car acp-to-fire  (32 28 28))
(add g-car range        ( 2  6 13))

(unit-type maultier (name "Maultier")
  (help "Second-deadliest in the game, but very vulnerable"))
(unit-type wespe (name "Wespe")
  (help "Longest range in the game, but vulnerable"))
(unit-type hummel (name "Hummel")
  (help "Deadliest unit in the game, but vulnerable"))

(define g-spa (maultier wespe hummel))

(add g-spa generic-name "SPA")

(add g-spa acp-per-turn (20 16 16))
(add g-spa acp-min (-20 -16 -16))

(add g-spa acp-to-fire  (20 16 16))
(add g-spa range        (12 32 24))

(unit-type gw38 (name "Gw 38"))
(unit-type wirbelwind (name "Wirbelwind"))
(unit-type stuh42 (name "Stu H 42"))
(unit-type marder3 (name "Marder III"))
(unit-type stug3 (name "StuG III"))
(unit-type hetzer (name "Hetzer"))
(unit-type nashorn (name "Nashorn")
  (help "Longer-range TD"))
(unit-type jgdpz4 (name "Jgd Pz IV"))
(unit-type jgdpz5 (name "Jgd Pz V"))
(unit-type jgdpz6 (name "Jgd Pz VI"))

(define ww wirbelwind)

(define g-td (gw38 ww stuh42 marder3 stug3 hetzer nashorn jgdpz4 jgdpz5 jgdpz6))

(add g-td generic-name "TD")

(add g-td acp-per-turn (12 16 16 16 16 12 16 16 18 10))
(add g-td acp-min (-12 -16 -16 -16 -16 -12 -16 -16 -18 -10))

(add g-td acp-to-fire  (12 16 16 16 16 12 16 16 18 10))
(add g-td range        (12 10 12  8  8  8 20 12 12 12))

(unit-type lynx (name "Lynx")
  (help "Weak but speedy"))
(unit-type pz4 (name "PzKpfw IV") (image-name "pz-4")
  (help "Most common type of Panzer"))
(unit-type panther (name "Panther")
  (help "All-around best tank"))
(unit-type tiger1 (name "Tiger I") (image-name "tiger-1")
  (help "Powerful but slow tank"))
(unit-type tiger2 (name "Tiger II") (image-name "tiger-2"))

(define g-tank (lynx pz4 panther tiger1 tiger2))

(add g-tank generic-name "tank")

(add g-tank acp-per-turn (20 16 20 16 12))
(add g-tank acp-min (-20 -16 -20 -16 -12))

(add g-tank acp-to-fire  (20 16 20 16 12))
(add g-tank range        ( 4  8 12 10 12))

(define g-wheeled (append gwag gtruck g-car))

(define g-tracked (append ghalf g-spa g-td g-tank))

(define g-vehicle (append g-wheeled g-tracked))

(define g-armored (append ghalf g-car g-spa g-td g-tank))

(define german (append g-arty g-inf g-transport g-car g-spa g-td g-tank))

(add german possible-sides "german")

;;; Non-side-specific type lists.

(define arty (append r-arty g-arty))

(define inf (append r-inf g-inf))

(define engrs (rengrs gengrs))

(define transport (append r-transport g-transport))

(define wheeled (append r-wheeled g-wheeled))

(define tracked (append r-tracked g-tracked))

(define vehicle (append r-vehicle g-vehicle))

(define armored (append r-armored g-armored))

;;; What happens to tanks that get wrecked.

(unit-type wreck (image-name "tank-wrecked") (acp-per-turn 0))

;;; Wrecks don't belong to either side.

(add wreck possible-sides "independent")

(add wreck assign-number false)

;; This should be the end of type definitions.

;;; Static relationships.

(table vanishes-on
  (u* water true)
  (vehicle swamp true)
  )

;; Normal stacking is 4 in a hex.

(add ground capacity 4)

(table unit-size-in-terrain
  (u* solid 1)
  ((block town) ground 4)  ; towns and blocks fill entire hex
  )

;; Towns can have a higher concentration of units.

(add town capacity 8)

;; Trucks, tanks, etc can carry one infantry or artillery unit.

(add vehicle capacity 1)

(table unit-size-as-occupant
  (u* u* 99)  ; can't be occupants usually
  (r-arty r-vehicle 1)
  (r-inf r-vehicle 1)
  (g-arty g-vehicle 1)
  (g-inf g-vehicle 1)
  (arty town 1)
  (inf town 1)
  (vehicle town 1)
)

;;; Vision.

;; No secret towns, although ownership might be unknown.

(add town already-seen 100)

;; Everybody sees everything up to about 2 km or so.
;; (Every unit has *somebody* with binoculars!)

(add u* vision-range 8)
;; No binoculars (or even eyes) for these types though.
(add (block minefield wreck) vision-range -1)

(table see-chance-adjacent
  (u* minefield 50)
  ;; Engineers live to deal with minefields.
  (engrs minefield 100)
  )

(table see-chance
  ;; Can't see minefields from a distance.
  (u* minefield 0)
  )

(table vision-night-effect
  ;; No time to study vague shapes in the dark, so night vision
  ;; greatly curtailed.
  (u* t* 25)
  ;; (should have some types, like CPs, less affected?)
  )

;; Everybody is line-of-sight.

(add u* vision-bend 0)

(table eye-height
  ;; Everybody can at least stand up to look around.
  (u* t* 2)
  ;; One can stand on top of a vehicle to see further.
  (vehicle t* 4)
  )

;; Trees go up to about 20m in height.

(add (woods thick-forest) thickness 20)

;; Unit types are not always easy to distinguish.

(table see-mistake-chance
  (u* r-tank 50.00)
  (u* g-td 50.00)
  (u* g-spa 50.00)
  (u* g-tank 50.00)
  )

(table looks-like
  ;; Types are most likely to look like types in the same class.
  (r-tank r-tank 20)
  (g-spa g-spa 20)
  (g-td g-td 20)
  (g-tank g-tank 20)
  ;; Tracked types are less likely, but still possible.
  (r-tracked r-tracked 10)
  (rhalf u* 0)
  (g-tracked g-tracked 10)
  (ghalf u* 0)
  )

;;; Actions.

(table acp-night-effect
  (vehicle t* 50)
  (vehicle road 75)
  )

;;; Movement parameters.

(table mp-to-enter-terrain
  (u* t* 1)
  (u* slope 2)
  ;; While it's more realistic to make inf go slower on slopes too, they
  ;; only have 2 acp to begin with and it's otherwise hard to make the
  ;; numbers work right.  Inf speed doesn't matter much anyway, the battle
  ;; usually moves faster than anybody on foot.
  (inf slope 1)
  (u* road 0)
  (u* water 99)
  (vehicle swamp 99)
  )

(table mp-to-leave-terrain
  (u* t* 1)
  (wheeled gully 20)
  (tracked gully 3)
  (u* road 0)
  )

(table mp-to-traverse
  ;; Roads are the fastest way to get around.
  (u* road 1)
  )

(table mp-to-enter-own
  (u* u* -1)
  (u* wreck 10)
  (u* minefield 20)
  )

(table mp-to-enter-zoc
  (u* u* -1)
  (u* wreck 10)
  (u* minefield 20)
  )

;; Need high cost of entry, takes entire turn, including transport's acp.

(table ferry-on-entry
  ;; Artillery can be loaded/towed by vehicles even though they can't
  ;; move normally.
  (r-vehicle r-arty over-all)
  (g-vehicle g-arty over-all)
  )

;;; Combat parameters.

(table acp-to-attack
  (u* u* 2) ; for now
  ;; Nobody can attack a block or wreck...
  (u* (block wreck) 0)
  ;; ...except for engrs trying to remove one.
  (engrs (block wreck) 1)
  )

(table acp-to-defend
  (u* u* 2) ; for now
  )

;; In general, hp of 2 is healthy, 1 is crippled, 0 is dead or disappeared.

(add u* hp-max 2)
;; Towns are not indestructible, but you'd have to work at it.
(add town hp-max 500)
(add minefield hp-max 1)
;; Trucks and wagons pretty much evaporate in this sort
;; of combat.
(add transport hp-max 1)
;; However, armored equipment can absorb more punishment.
(add armored hp-max 4)
;; ...but not halftracks.
(add (rhalf ghalf) hp-max 2)

(table hit-chance
  ;; By default, don't allow combat.
  (u* u* 0)
  ;; Minefields almost always hit.
  (minefield u* 90)
  ;; But they're unlikely to catch engineers by surprise.
  (minefield engrs 20)
  (r-arty u* 100)
  (r-arty g-inf 50)
  (r-inf  u* 100)
  (r-inf  g-armored 50)
  (r-td   u* 100)
  (r-td   g-inf 50)
  (r-tank u* 100)
  (r-tank g-inf (50 40 50 60))
  (g-arty u* 100)
  (g-inf  u* 100)
  (g-inf  r-tank 10)
  (g-car  u*  70)
  (g-car  r-inf  30)
  (g-spa  u* 100)
  (g-spa  r-inf 50)
  (g-td   u* 100)
  (g-td r-inf 40)
  (g-tank u* 100)
  (g-tank r-inf 40)
  ;; Nobody can do anything to a burning wreck.
  (u* wreck 0)
  ;; Only engineers can clear minefields.
  (u* minefield 0)
  (engrs minefield 20)
  )

(table damage
  (u* u* 0)
  (minefield u* 1)
  (r-arty u* 1)
  (r-inf  u* 1)
  ((rcav rhalf) u* 1)
  (r-td   u* 2)
  (su-152 u* 2)
  (r-tank u* 1)
  (g-arty u* 1)
  (g-inf  u* 1)
  (g-car  u* 1)
  (g-spa  u* 1)
  (g-spa  r-inf 1d2+1)
  (wespe  u* 1d2+2)
  (hummel u* 2d2+2)
  (g-td   u* 1)
  (g-tank u* 1)
  ;; Heavy tanks are more deadly when they connect
  ((js2 tiger1 tiger2) u* 2)
  ;; Nobody can do anything to a burning wreck.
  (u* wreck 0)
  ;; Only engineers can clear minefields.
  (u* minefield 0)
  (engrs minefield 1)
  )

(table occupant-combat
  ;; Artillery can't be used from inside trucks etc.
  (arty vehicle 0)
  ;; (perhaps allow MGs and mortars to fire from halftracks?)
  )

(add arty fire-angle-max 100)
(add g-spa fire-angle-max 75)
(add g-td fire-angle-max 25)
(add g-tank fire-angle-max 25)
(add r-tank fire-angle-max 25)

(table weapon-height
  (u* t* 0)
  (vehicle t* 2)
  )

(table body-height
  (u* t* 2)
  ;; Infantry eats dirt. :-)
  (inf t* 0)
  )

;;; Units eventually bounce back.

(add u* hp-recovery 0.50)

;;; Wrecked armored vehicles continue to be exist.

(add armored wrecked-type wreck)

;;; Towns are easy to capture, that's why they should be protected.

(table capture-chance
  (u* town 100)
  )

;; Minefields clobber any unit trying to pass over them.

(table detonate-on-hit
  ;; One way to get through a minefield is to sacrifice your
  ;; own guys.
  (minefield u* 80)
  )

(table detonate-on-approach-range
  (minefield u* 0)
  )

(add minefield acp-to-detonate 1)

(add minefield hp-per-detonation 0)

(table detonation-damage-at (minefield u* 1d3))

;; All games will have exactly one Russian and one German side.

(set side-library '(
  ((name "Russia") (noun "Russian") (adjective "Russian") (class "russian")
   (color "black,red") (emblem-name "soviet-star") (names-locked true))
  ((name "Germany") (noun "German") (adjective "German") (class "german")
   (color "gray,black") (emblem-name "german-cross") (names-locked true))
  ))

(set sides-min 2)
(set sides-max 2)

;;; The following sets up a simple game, for testing;
;;; usually this module should be used in a more-or-less
;;; preset scenario.

(set alt-blob-height 1000)
(set alt-blob-size 100)
(set alt-smoothing 10)

(add cell-t* alt-percentile-min (  0   5  10   5  90   5))
(add cell-t* alt-percentile-max (  5  10  15  95  95 100))
(add cell-t* wet-percentile-min (  0  50   0  90   0   0))
(add cell-t* wet-percentile-max (100 100  50 100 100 100))

(set edge-terrain clear)

(set country-radius-min 5)

(set country-separation-min 25)
(set country-separation-max 30)

;; An approximation to a Russian tank corps.

(add (r45 r76at) start-with 2)
(add (rrecon rsmg) start-with (2 4))
(add (rtruck rhalf) start-with (6 2))
(add (t34 su-85 su-152) start-with (10 2 2))

;; An approximation to a German battle group.

(add (g75 g88 g20q g120) start-with (2 1 1 1))
(add grifle start-with 3)
(add ghalf start-with 7)
(add (pz4 panther wespe hummel jgdpz4) start-with (3 1 1 1 1))

(table favored-terrain
  ;; Make the less-mobile units start out in transports.
  (arty t* 0)
  (inf t* 0)
  (engrs t* 0)
  )

(table road-chance
  (town town 100)
  )

(table road-into-chance
  (t* t* 100)
  (t* gully 20)
  (gully t* 20)
  (t* water 10)
  (water water 0)
  )

(add town road-to-edge-chance 100)

(set edge-road-density 400)

(add town spur-chance 100)
(add town spur-range 8)

(add u* point-value 1)

(set advantage-max 3)

(scorekeeper (do last-side-wins))

(game-module (instructions "Move fast or die!"))

(game-module (design-notes (
  "Turns represent about 10 minutes each, cells are about 250m across."
  ""
  "make shooting be LOS for armor, specify alts for artillery."
  ""
  )))

