This is the mail archive of the xconq7@sources.redhat.com mailing list for the Xconq project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Bug in side_controls_unit


Attached to the bottom of this message is necromancer.g, the game module
I wrote to test the unit control code.  While testing it, I have
experienced crashes which I have traced back to the side_controls_unit
function, and I have experienced non-fatal logic errors in which units
become uncontrolled after moving, even if they're still well within
control-range of a unit that can control them (and that is itself
controlled).  These logic errors are usually followed very soon by a
segfault.

---
Lincoln Peters
<sampln@sbcglobal.net>

The Killer Ducks are coming!!!


(game-module "necromancer"
  (title "Necromancers")
  (blurb "Necromancers raise the dead and fight each other to the
death!")
  (instructions "You should start by raising an army of as many undead
as possible.  Then lead your army against other players and crush
them!")

  (notes (
 "This is a fairly simple game that tests the ability of one unit to
control another, something that no other game uses.
""When fighting your enemies, blitzkreig is effective if your enemy is
disorganized.  However, that is only a common scenario if your opponent
is an AI mplayer, as the rule make it unlikely that a self-unit (the
necromancer) would go anywhere without a company of undead defenders. 
It is more often a war of attrition (for if you can take away your
opponent's supply of flesh, you should prevail easily).
""Undead units are powerful, and can easily slay most mortals, but they
are completely helpless if they are so far from their master that they
cannot be controlled.  Therefore, you must ensure that all undead units
remain within the control range of your necromancer at all times. 
Furthermore, occasionally a powerful mortal knight arises who can slay
undead with ease.  When you encounter such a knight, you must be use a
lot of strategy and skill to overcome his righteous fury!
""Guard the necromancer above all else!  If your necromancer dies, you
lose the game immediately and all of your undead units self-destruct!"
  ))

  (variants
    (world-seen)
    (see-all)
    (sequential true)
    (world-size)
    ;; Should have "stubborn sides" variant so that intelligent undead
can take command if the necromancer dies?
    ("Mostly land" mostly-land
     "Generate a world that is mostly (80%) land."
     (true
       ;; Almost all units are walkers, so there should be little water.
       ;; Adjust so that sea is 20% instead of 70% of the world.
       (add sea alt-percentile-max 20)
       (add shallows alt-percentile-min 20)
       (add shallows alt-percentile-max 21)
       (add swamp alt-percentile-min 21)
       (add swamp alt-percentile-max 23)
       (add (desert plains forest) alt-percentile-min 21)
       (add boat start-with 0)
    ))
    ("Disable control" disable-control
     "Allow all units to be controlled directly."
     (true
       (add u* direct-control true)
       ;; I don't *think* anything else must be explicitly turned off.
    ))
  )

)

(scorekeeper (do last-side-wins))

(include "stdterr")
(include "ng-weird")
(include "ng-features")


;;; UNIT TYPES

;; Places

(unit-type village (image-name "ancient-city")
  (hp-max 100) (acp-per-turn 1) (hp-recovery 1.00)
  (can-be-self true)
  (help "Small, usually defenseless village")
  (notes "A defenseless village is the first place that a ruthless evil
necromancer goes when searching for human flesh to fuel his magic.  It
is rarely too difficult for a wizard of respectable power to lay waste
to a village, turning it into a graveyard.")
)

(unit-type graveyard (image-name "ancient-ruins")
  (hp-max 100) (acp-per-turn 0) (hp-recovery 1.00)
  (help "A place where dead bodies are stored")
  (notes "A graveyard is a veritable gold mine for necromancers, for it
holds the dead bodies necessary to create any kind of undead creature.")
)

(unit-type tower (image-name "ancient-tower")
  (hp-max 1000) (acp-per-turn 1) (cp 50) (hp-recovery 3.00)
  (help "The stronghold of an evil wizard")
  (notes "A tower is loaded with powerful magics that allow it to
collect dead bodies from remote graveyards, supplement a necromancer's
magical energy, and protect itself from virtually anything that might
threaten it.")
)

(unit-type castle (image-name "ancient-yellow-castle")
  (hp-max 1000) (acp-per-turn 1) (cp 50) (hp-recovery 3.00)
  (can-be-self true)
  (help "A stronghold for non-magical heroes")
  (notes "A castle often houses knights who would end the career of an
evil necromancer if they have the power to do so.  They are difficult to
destroy, and occasionally one or more powerful knights emerge and fight
a necromancer and/or his minions to the death. ")
)

;; Living units

(unit-type necromancer (image-name "monsters-dark-lord")
  (hp-max 200) (acp-per-turn 4) (acp-min -3) (cp 50) (hp-recovery 6.00)
  (tech-to-build 120) (tech-max 120)
  (can-be-self true)
  (help "The unchallenged commander of undead armies")
  (notes "The necromancer can raise the dead and bind them to his
service.  He also has arcane powers that are devastating to his enemies,
both those living and dead.")
)

(unit-type knight (image-name "adventurer")
  (hp-max 100) (acp-per-turn 4) (acp-min -3) (cp 40) (hp-recovery 0.50)
  (help "Champion against evil magic")
  (notes "This champion is an expert at combat and the bane of virtually
all evildoers.  It takes a lot of powerful magic to take this guy
down.")
)

(unit-type commoner (image-name "heroes-man1")
  (hp-max 5) (acp-per-turn 4) (acp-min -3) (cp 3)
  (help "Defenseless bystander")
  (notes "To a necromancer, a commoner such as this is nothing more than
a source of raw materials and energy to power his magic.  He can be
transformed into any form of undead creature that the necromancer knows
how to create.  Of course, others look upon this as the height of
evil.")
)

;; Dead units

(unit-type skeleton (image-name "skeleton")
  (hp-max 10) (acp-per-turn 4) (acp-min -3) (cp 4)
  ;; (tech-to-build 6) (tech-max 6)
  (help "Animated bones")
)

(unit-type zombie (image-name "monsters-undead")
  (hp-max 20) (acp-per-turn 2) (acp-min -1) (cp 8)
  (tech-to-build 6) (tech-max 6)
  (help "The simplest form of animated corpse")
)

(unit-type ghoul (image-name "orc")
  (hp-max 30) (acp-per-turn 4) (acp-min -3) (cp 12)
  (tech-to-build 12) (tech-max 12)
  (help "Slightly more intelligent than a zombie")
)

(unit-type wight (image-name "monsters-gollum")
  (hp-max 40) (acp-per-turn 5) (acp-min -4) (cp 16)
  (tech-to-build 18) (tech-max 18)
  (help "Horrid creation that hates all life")
)

(unit-type wraith (image-name "monsters-undead")
  (hp-max 50) (acp-per-turn 6) (acp-min -5) (cp 20) (hp-recovery 1.00)
  (tech-to-build 24) (tech-max 24)
  (help "Incorporeal undead spirit")
)

(unit-type spectre (image-name "monsters-wormtongue")
  (hp-max 60) (acp-per-turn 8) (acp-min -7) (cp 24) (hp-recovery 1.00)
  (tech-to-build 30) (tech-max 30)
  (help "More powerful undead spirit")
)

(unit-type vampire (image-name "vampire")
  (hp-max 70) (acp-per-turn 4) (acp-min -3) (cp 28) (hp-recovery 2.00)
  (tech-to-build 36) (tech-max 36)
  (help "Very dangerous; can control lesser undead")
)

(unit-type lich (image-name "monsters-blue-king")
  (hp-max 80) (acp-per-turn 4) (acp-min -3) (cp 32) (hp-recovery 2.00)
  (tech-to-build 42) (tech-max 42)
  (help "The most powerful undead; can control any other undead")
)

;; Miscellaneous units

(unit-type corpse (image-name "carcass")
  (hp-max 15) (acp-per-turn 0)
  (help "A piece of raw, bloody meat")
  (notes "This is the remains of a recently-killed human.  A necromancer
can transform it into any kind of undead creature that he knows how to
create.")
)

(unit-type boat (image-name "ancient-dromund")
  (hp-max 6) (acp-per-turn 4) (cp 10)
  (help "Carries land units across water")
  (notes "The boat is the only to move an army across water.  It can be
constructed with relative speed by any intelligent units.  However, it
is quite vulnerable to ranged attacks.")
)

;;; MATERIAL TYPES

(material-type flesh (image-name "red")
  (help "Dead stuff")
  (notes "When a necromancer raises the dead, he shapes this stuff into
undead creatures and gives them an artificial life force.  One unit of
flesh is roughly equal to one dead body.")
)

(material-type mana (image-name "blue")
  (help "Magical energy")
  (notes "All magical actions use up mana, and so, even with an
unlimited supply of flesh, no necromancer can cast spells without
eventually having to stop and rest.  Additionally, undead units are
powered by mana and are rendered helpless without it.")
)

;;; BASIC DEFINITIONS

(define places (village graveyard tower castle))
(define living (necromancer knight commoner))
(define dead (skeleton zombie ghoul wight wraith spectre vampire lich))
(define unintelligent-dead (skeleton zombie ghoul wight))
(define intelligent-dead (wraith spectre vampire lich))

(define movers (necromancer knight commoner skeleton zombie ghoul wight
wraith spectre vampire lich))

(add commoner wrecked-type corpse)
(add knight wrecked-type corpse)
(add village wrecked-type graveyard)
(add castle wrecked-type graveyard)

(set self-required true)

(add necromancer start-with 1)
(add tower start-with 1)
(add boat start-with 1)

(add graveyard independent-near-start 1)

(table favored-terrain
  (u* t* 0)		;; Be very strict about starting terrain.
  (u* plains 100)	;; Start everyone in plains.
  (boat plains 0)	;; Except boats...
  (boat shallows 100)	;; ...start in shallow water.
)

(add t* capacity 4)

(table unit-size-in-terrain
  (u* t* 1)
  (places t* 3)
  (corpse t* 0)
)

(set country-radius-min 3)

(table independent-density
  (village plains 100)
  (graveyard plains 75)
  (commoner plains 150)

  (castle plains 25)
  ;; No knights initially; they make it too hard for beginning players
to survive!
)

(set country-separation-min 50)			;; Might also need adjustment
;; (set country-separation-max 9999)		;; This shouldn't be necessary,
but country-separation-min doesn't seem to work without it.


;;; MATERIAL HANDLING

(table unit-storage-x
  ;; Units store materials as needed or as might be logistically useful.
  ;; Some fudging of the laws of physics is done here.
  (tower flesh 1000)
  (necromancer flesh 100)
  (dead flesh 10)
  (vampire flesh 30)
  (lich flesh 50)

  (tower mana 5000)
  (necromancer mana 1000)
  (dead mana 100)
  (vampire mana 250)
  (lich mana 500)

  (graveyard flesh 200)	;; Graveyards are made to store lots of dead
bodies.
  (corpse flesh 4)	;; A fresh dead body stores a lot of usable flesh.
)

(table unit-initial-supply
  ;; All sides start with a full supply of mana but no flesh.
  (u* flesh 0)
  (u* mana 9999)
)

(table base-production
  ;; Flesh is only "produced" by graveyards.
  (graveyard flesh 2)

  ;; Although many units depend on mana, few can produce it.
  (tower mana 20)	;; Towers are supply bases for mana.
  (necromancer mana 4)	;; Not quite enough to support continuous
spellcasting.
  (vampire mana 2)	;; Vampires are self-sufficient (although they're
still helpless if depleted)
  (lich mana 2)		;; As are liches.
)

(table base-consumption
  ;; Undead always consume some mana, even when not acting.
  (dead mana 1)
)

(table unit-initial-supply
  ;; All units capable of storing mana start loaded with it.
  (u* mana 9999)

  ;; All graveyards start full.
  (graveyard flesh 9999)
)

(table supply-on-completion
  ;; Graveyards and corpses, once brought into existence, always have at
least some flesh.
  (graveyard flesh 100)
  (corpse flesh 4)

  ;; Give undead an initial supply of mana, so that they can at least
resupply.
  (dead mana 8)
)

(table material-to-act
  ;; Undead units are powerless without mana.
  (dead mana 1)
)

;;; UNIT SIZE AND TRANSPORT/OCCUPANT RELATIONS

(add village capacity 4)
(add tower capacity 16)
(add castle capacity 16)
(add boat capacity 4)

(table unit-size-as-occupant
  (u* u* 1)		;; By default.
  (boat u* 2)		;; Boats are big.
  (places u* 99)	;; Places do not fit in anything else.
)

#| This doesn't work as well as I had hoped...

(table acp-to-load
  ;; Any unit with the necessary capacity can pick up materials.
  (u* m* 1)
)

(table acp-to-unload
  ;; Any unit can transfer materials to another.
  (u* m* 1)
)

(table acp-to-extract
  ;; Most units can extract flesh from graveyards and corpses.
  (necromancer flesh 1)
  (dead flesh 1)
)

|#

;;; MOVEMENT

(add places speed 0)

(table mp-to-enter-terrain
  ;; Since nearly all movers walk, this is pretty straightforward.
  (u* plains 1)
  (u* desert 1)
  (u* forest 2)
  (u* swamp 2)
  (u* mountains 3)
  (u* ice 99)
  (u* shallows 99)
  (u* sea 9)

  ;; The boat is slightly different...
  (boat t* 99)
  (boat sea 1)
  (boat shallows 1)
)

(table mp-to-traverse
  (u* road 1)
)

(table vanishes-on
  ;; Normally mp-to-enter-terrain would negate any need to use this
table, but it is necessary to prevent necromancers from raising the dead
on water.
  (u* t* false)		;; By default.
  (u* sea true)
  (u* shallows true)
  (boat t* true)
  (boat sea false)
  (boat shallows false)
)

(table material-to-move
  ;; Undead are immobilized without mana.
  (dead mana 1)
)

(table consumption-per-move
  ;; Undead require mana to move around.
  (dead mana 1)
)

;;; CONSTRUCTION

(table acp-to-create
  ;; Start with a backdrop
  (commoner village 1)
  (knight castle 1)
  (necromancer tower 4)
  (lich tower 4)

  (village commoner 1)
  (castle knight 1)
  (tower dead 1)
  (tower necromancer 1)

  (living boat 1)
  (intelligent-dead boat 1)
  (places boat 1)

  ;; And now, the sinister stuff...
  (necromancer dead 4)			;; All necromantic creations require 4 ACP per
create/build action (although they require different CP's).
  (necromancer necromancer 4)		;; But he has to be *really* powerful to
clone himself!

  (vampire unintelligent-dead 4)	;; Vampires can create unintelligent
undead minions for themselves.
  (lich dead 4)				;; A lich can create any kind of undead...
  (lich lich 0)				;; ...except itself.
)

(table acp-to-build
  ;; Start with a backdrop
  (commoner village 1)
  (knight castle 1)
  (necromancer tower 4)
  (lich tower 4)

  (village commoner 1)
  (castle knight 1)
  (tower dead 1)
  (tower necromancer 1)

  (living boat 1)
  (intelligent-dead boat 1)
  (places boat 1)

  ;; And now, the sinister stuff...
  (necromancer dead 4)		;; All necromantic creations require 4 ACP per
create/build action (although they require different CP's).
  (necromancer necromancer 4)		;; But he has to be *really* powerful to
clone himself!

  (vampire unintelligent-dead 4)	;; Vampires can create unintelligent
undead minions for themselves.
  (lich dead 4)			;; A lich can create any kind of undead...
  (lich lich 0)				;; ...except itself.
)

(table create-range
  (u* u* 2)		;; By default
  (tower u* 0)
  (castle u* 0)
)

(table build-range
  (u* u* 2)		;; By default
  (tower u* 0)
  (castle u* 0)
)

(table material-to-create
  ;; The only thing that must be considered for this game is flesh and
mana.
  (dead flesh 1)	;; Fairly straightforward.
  (dead mana 8)	;; Mana can easily be consumed faster than it is
produced.
  (necromancer mana 32)	;; It takes even more for a necromancer to clone
himself!
)

(table consumption-per-build
  ;; The only thing that must be considered for this game is flesh and
mana.
  (dead flesh 1)	;; Fairly straightforward.
  ;; (dead mana 8)		;; Mana can easily be consumed faster than it is
produced. (should it be?)
  (necromancer mana 32)	;; It takes even more for a necromancer to clone
himself!
)

(table acp-to-develop
  ;; Only the necromancer himself can research new undead units.
  (necromancer dead 4)
)

(table tech-per-develop
  (necromancer dead 1.00)
)

;;; CONTROL
;; (this is what makes this game especially interesting!)

(add u* direct-control false)		;; By default, no unit is directly
controlled by a side.
(add necromancer direct-control true)	;; But the necromancer *is* the
side.
(add knight direct-control true)	;; And the knight *is* the independent
side.
(add places direct-control true)	;; Otherwise the game can become
unplayable!

(table unit-control-chance
  (u* u* 0)				;; Most units are unable to control other units.
  (places u* 100)			;; Places can control nearby units.
  (necromancer u* 100)			;; Necromancers can control *all* of their
minions.
  (vampire unintelligent-dead 100)	;; Vampires can control unintelligent
undead.
  (lich dead 100)			;; The lich can control any undead.
)

(table unit-control-range
  (u* u* 0)
  (knight commoner 4)			;; Knights can (try to) aid lost villagers.
  (necromancer dead 16)			;; The necromancer can telepathically control
undead within twice his vision-range.
  (necromancer vampire 32)		;; But he can control vampires at a much
greater range.
  (necromancer lich 64)			;; And he ccan control liches at even greater
range!
  (tower dead 16)			;; The tower can control undead at the same range as
the necromancer.
  (lich lich 32)			;; Liches can relay commands at comparable range.
  (u* boat 4)				;; Boats are easy to control.
)

;;; COMBAT

;; I wanted to use the extraction mechanism to move flesh from corpses
and graveyards to necromancers and towers.
;; But that doesn't seem to work, so I'm using a capture mechanism.

(table acp-to-capture
  (necromancer graveyard 1)
  (intelligent-dead graveyard 1)
)

(table capture-chance
  (necromancer graveyard 100)
  (dead graveyard 100)

  (necromancer corpse 100)
  (dead corpse 100)
)

(table out-length
  (graveyard flesh 20)
  (corpse flesh 20)

  (necromancer mana 6)
  (lich mana 4)
  (vampire mana 2)
  (tower mana 40)
)

(table in-length
  (u* flesh 20)
  (u* mana 6)
)

(table acp-to-attack
  (u* u* 2)		;; By default, any unit can attack any adjacent unit.
  (necromancer graveyard 0)
  (places u* 0)		;; Places cannot initiate attacks.
)

;; This may be causing more problems than it solves...
(add necromancer acp-to-fire 2)		;; Necromancers can fire destructive
spells at opponents.
(add necromancer range 6)		;; They may extend as far as he can see.
(add necromancer range-min 2)		;; At shorter range, he's inviting
someone to chop him up!
;; (should define fire-angle-max?)


(table hit-chance
  (u* u* 50)		;; By default.
  (u* places 75)	;; Non-moving targets are easier to hit.
)

(table damage
  (u* u* 1d6)		;; By default.
  (knight u* 2d4)	;; The knight has had rigorous combat training.
  (necromancer u* 1d4)	;; The necromancer has had hardly any combat
training.
  (commoner u* 1d4)	;; The commoner has just as little combat training.
)


(table fire-damage
  (necromancer u* 2d6)		;; Combat spells hurt.
  (necromancer places 4d6)	;; And they're especially deadly against
non-moving targets.
)


(table protection
  ;; If a unit is hiding in a tower or castle, it is impervious to
outside attacks.
  ;; Of course, the unit is in trouble if the tower or castle is
destroyed.
  (tower u* 0.00)
  (castle u* 0.00)
)

;; capture-chance is not defined because the goal of all sides is to
completely destroy the other!

(table occupant-escape-chance
  (u* u* 50)			;; Most units are smart enough to escape a building that
is collapsing.
  (unintelligent-dead u* 25)	;; But unintelligent undead are not.
  (necromancer u* 100)		;; The necromancer can escape from anything!
)

;;; REPAIR

(table auto-repair
  ;; Towers can heal undead creatures and necromancers.
  (tower necromancer 1.00)
  (tower dead 1.00)

  ;; Castles can heal knights.
  (castle knight 2.00)
)

(table acp-to-repair
  ;; Necromancers can heal undead and repair their towers.
  (necromancer tower 4)
  (necromancer dead 4)

  ;; Towers can concentrate on healing their master and his minions.
  (tower necromancer 1)
  (tower dead 1)

  ;; Knights can heal themselves, repair their castles, and rebuild
villages.
  (knight knight 4)
  (knight castle 4)
  (knight village 4)

  ;; Castles can heal knights.
  (castle knight 4)
)

(table hp-per-repair
  (necromancer tower 10)
  (necromancer dead 8)

  (tower necromancer 8)
  (tower dead 8)

  (knight knight 4)
  (knight castle 10)
  (knight village 12)

  (castle knight 8)
)

;;; VISION

(add places vision-range 8)
(add living vision-range 6)
(add dead vision-range 4)

(add u* vision-bend 0)		;; Do the line-of-sight thing.

(table visibility
  ;; Most units are harder to see in rough terrain.
  (u* forest 0.50)
  (u* mountains 0.50)
)

(table see-chance
  ;; As per "visibility" table, but nothing obscures a place.
  (u* places 200)
)

(table see-chance-adjacent
  ;; Nothing can hide from an adjacent unit.
  (u* u* 200)
)

;;; BACKDROP

;; In case land masses are separated by water, allow intelligent units
to build bridges.
(table acp-to-add-terrain
  (living road 1)
  (intelligent-dead road 1)
)

(table acp-to-remove-terrain
  (living road 1)
  (intelligent-dead road 1)
)

;; Use attrition to cause corpses to eventually vanish.
(table attrition
  (corpse t* 0.50)
)

;; Give weird names to all units.
(add u* namer "generic-names")

;; This code for generating feature names was copied nearly verbatim
from the Standard game.
(set feature-types '(peaks islands lakes bays seas continents 
			    (desert 10)(forest 10)(mountains 5)))

(set feature-namers
  '((islands generic-island-names) (lakes generic-lake-names) (bays
generic-bay-names)
  	(seas generic-sea-names) (continents generic-continent-names)
  	(desert generic-desert-names) (forest generic-forest-names)
  	(mountains generic-mountain-names)))

(add u* lost-vanish-chance 0)
(add u* lost-wreck-chance 10000)
(add necromancer lost-wreck-chance 0)
(add necromancer lost-revolt-chance 10000)



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]