self.skill = None # levels: none, novice, fair, good,
# expert, emeritus
# Integer nembers sart here
- self.inkling = None # initial number of klingons
+x self.inkling = None # initial number of klingons
self.inbase = None # initial number of bases
self.incom = None # initial number of commanders
self.inscom = None # initial number of commanders
self.probeiny = None #
self.height = None # height of orbit around planet
-def communicating():
- "Are we in communication with Starfleet Command?"
- return (not damaged("DRADIO")) or game.condition == "docked"
-
-# Code corresponding to ai.c begins here
-
-def tryexit(look, ship, irun):
- # a bad guy attempts to bug out of the quadrant
- iq = coord()
- iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
- iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
- if not valid_quadrant(iq) or \
- game.state.galaxy[iq].supernova or \
- game.state.galaxy[iq].klingons > MAXKLQUAD-1:
- return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
- if ship.type == "Romulan":
- return False # Romulans cannot escape
- if not irun:
- # avoid intruding on another commander's territory
- if ship.type == "Commander":
- if iq in gamestate.kcmdr:
- return False
- # refuse to leave if currently attacking starbase:
- if game.battle == game.quadrant:
- return False;
- # don't leave if over 1000 units of energy
- if ship.power > 1000.0:
- return false;
- # Print escape message and move out of quadrant.
- # We know this if either short or long range sensors are working
- if not damaged("DSRSENS") or not damaged("DLRSENS") or game.condition=="docked":
- crmena(True, "sector", ship)
- prout(" escapes to quadrant %s (and regains strength)." % iq)
- # handle local matters related to escape
- game.quad[ship.location] = None;
- if game.condition != "docked":
- newcnd()
- # Handle global matters related to escape
- game.state.galaxy[game.quadrant].klingons -= 1
- game.state.galaxy[iq].klingons += 1
- if ship.type == "Super-Commander":
- game.ishere = False
- game.iscate = False
- game.ientesc = False
- game.isatb = 0
- schedule("FSCMOVE", 0.2777)
- unschedule("FSCDBAS")
- game.state.kscmdr = iq
- else:
- for (n, cmdr) in enumerate(game.state.kcmdr):
- if cmdr == game.quadrant:
- game.state.kcmdr[n] = iq
- break
- game.comhere = False
- return True # successful exit
-
-def sgn(n): n / abs(n)
-
-'''
-Algorithm for moving bad guys:
-
- * Enterprise has "force" based on condition of phaser and photon torpedoes.
- If both are operating full strength, force is 1000. If both are damaged,
- force is -1000. Having shields down subtracts an additional 1000.
-
- * Enemy has forces equal to the energy of the attacker plus
- 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
- 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
-
- Attacker Initial energy levels (nominal):
- Klingon Romulan Commander Super-Commander
- Novice 400 700 1200
- Fair 425 750 1250
- Good 450 800 1300 1750
- Expert 475 850 1350 1875
- Emeritus 500 900 1400 2000
- VARIANCE 75 200 200 200
-
- Enemy vessels only move prior to their attack. In Novice - Good games
- only commanders move. In Expert games, all enemy vessels move if there
- is a commander present. In Emeritus games all enemy vessels move.
-
- * If Enterprise is not docked, an agressive action is taken if enemy
- forces are 1000 greater than Enterprise.
-
- Agressive action on average cuts the distance between the ship and
- the enemy to 1/4 the original.
-
- * At lower energy advantage, movement units are proportional to the
- advantage with a 650 advantage being to hold ground, 800 to move forward
- 1, 950 for two, 150 for back 4, etc. Variance of 100.
-
- If docked, is reduced by roughly 1.75*game.skill, generally forcing a
- retreat, especially at high skill levels.
-
- * Motion is limited to skill level, except for SC hi-tailing it out.
-'''
-
-def movebaddy(ship):
- # tactical movement for the bad guys
- bugout = False
- # This should probably be just game.comhere + game.ishere
- if game.skill >= SKILL_EXPERT:
- nbaddys = int((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
- else:
- nbaddys = game.comhere + game.ishere
- dist1 = ship.distance()
- mdist = round(dist1 + 0.5) # Nearest integer distance
- # If SC, check with spy to see if should high-tail it
- if ship.type == "Super-Commander" and \
- (ship.power <= 500.0 or (game.condition==docked and not damaged("DPHOTON"))):
- bugout = True;
- motion = -QUADSIZE;
- else:
- # decide whether to advance, retreat, or hold position
- forces = ship.power + 100.0*len(game.quad.enemies()) + 400*(nbaddys-1)
- if not game.shldup:
- forces += 1000.0 # Good for enemy if shield is down!
- if not damaged("DPHASER") or not damaged("DPHOTON"):
- if damaged(DPHASER):
- forces += 300.0
- else:
- forces -= 0.2*(game.energy - 2500.0);
- if damaged("DPHOTON"):
- forces += 300.0
- else:
- forces -= 50.0*game.torps
- else:
- # phasers and photon tubes both out!
- forces += 1000.0
- motion = 0;
- if forces <= 1000.0 and game.condition != "docked": # Typical case
- motion = ((forces+200.0*Rand())/150.0) - 5.0
- else:
- if forces > 1000.0: # Very strong -- move in for kill
- motion = (1.0-square(Rand()))*dist1 + 1.0
- if game.condition == "docked" and "base" in game.options:
- # protected by base -- back off !
- motion -= game.skill * (2.0-Rand()**2)
- if idebug:
- proutn("=== MOTION = %1.2f, FORCES = %1.2f, ", motion, forces)
- # don't move if no motion
- if motion == 0:
- return
- # Limit motion according to skill
- if abs(motion) > game.skill:
- if motion < 0:
- motion = -game.kill
- else:
- motion = game.skill
- # calculate preferred number of steps
- nsteps = abs(motion)
- if motion > 0 and nsteps > mdist: # don't overshoot
- nsteps = mdist
- if nsteps > QUADSIZE: # This shouldn't be necessary
- nsteps = QUADSIZE
- if nsteps < 1: # This shouldn't be necessary
- nsteps = 1
- if idebug:
- proutn("NSTEPS = %d:", nsteps)
- # Compute preferred values of delta X and Y
- me = game.sector - com;
- if 2.0 * abs(me.x) < abs(me.y):
- me.x = 0;
- if 2.0 * abs(me.y) < abs(game.sector.x-com.x):
- me.y = 0;
- if me.x != 0: me.x = sgn(me.x*motion)
- if me.y != 0: me.y = sgn(me.y*motion)
- next = com;
- # main move loop
- for ll in range(nsteps):
- if idebug:
- proutn(" %d", ll+1)
- # Check if preferred position available
- look = next + me
- krawl = me.sgn()
- success = False
- attempts = 0 # Settle meysterious hang problem
- while attempts < 20 and not success:
- attempts += 1
- if look.x < 1 or look.x > QUADSIZE:
- if motion < 0 and tryexit(look, ship, bugout):
- return
- if krawl.x == me.x or me.y == 0:
- break
- look.x = next.x + krawl.x
- krawl.x = -krawl.x
- elif look.y < 1 or look.y > QUADSIZE:
- if motion < 0 and tryexit(look, ship, bugout):
- return
- if krawl.y == me.y or me.x == 0:
- break
- look.y = next.y + krawl.y
- krawl.y = -krawl.y
- elif "ramming" in game.options and game.quad[look] != IHDOT:
- # See if we should ram ship
- if game.quad[look] == game.ship and ienm in (IHC, IHS):
- ram(true, ienm, com)
- return
- if krawl.x != me.x and me.y != 0:
- look.x = next.x + krawlx
- krawl.x = -krawl.x
- elif krawly != me.y and me.x != 0:
- look.y = next.y + krawly
- krawl.y = -krawl.y
- else:
- break # we have failed
- else:
- success = True
- if success:
- next = look
- if idebug:
- proutn(str(next))
- else:
- break # done early
- if idebug:
- prout("")
- # Put ship in place within same quadrant
- if next != ship.location:
- # it moved
- if not damaged("DSRSENS") or game.condition == "docked":
- proutn("*** %s from sector %s" % (ship, ship.location))
- if ship.distance() < dist1:
- prout(" advances to sector %s" % ship.location)
- else:
- prout(" retreats to sector %s" % ship.location)
- ship.sectormove(next)
-
-def moveklings():
- "Allow enemies to move."
- for enemy in self.quad.enemies():
- if enemy.type == "Commander":
- movebaddy(enemy)
- break
- for enemy in self.quad.enemies():
- if enemy.type == "Super-Commander":
- movebaddy(enemy)
- break
- # Ff skill level is high, move other Klingons and Romulans too!
- # Move these last so they can base their actions on what the
- # commander(s) do.
- if game.skill >= SKILL_EXPERT and "movebaddy" in game.options:
- for enemy in self.quad.enemies():
- if enemy.type in ("Klingon", "Romulan"):
- movebaddy(enemy)
- break
-
-def movescom(ship, avoid):
- # commander movement helper
- if game.state.kscmdr == game.quadrant or \
- game.state.galaxy[iq].supernova or \
- game.state.galaxy[iq].klingons > MAXKLQUAD-1:
- return True
- if avoid:
- # Avoid quadrants with bases if we want to avoid Enterprise
- for base in game.state.starbases:
- if base.location == ship.location:
- return True
- if game.justin and not game.iscate:
- return True
- # Super-Commander has scooted, Remove him from current quadrant.
- if game.state.kscmdr == game.quadrant:
- game.iscate = False
- game.isatb = 0
- game.ientesc = False
- unschedule("FSCDBAS")
- if game.condition != "docked":
- newcnd()
- ship.sectormove(None)
- # do the actual move
- game.state.galaxy[game.state.kscmdr].klingons -= 1
- game.state.kscmdr = iq
- game.state.galaxy[game.state.kscmdr].klingons += 1
- # check for a helpful planet in the destination quadrant
- for planet in game.state.planets:
- if planet.location == game.state.kscmdr and planet.crystals=="present":
- # destroy the planet
- del planet
- if communicating():
- pause_game(True)
- prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports")
- proutn(_(" a planet in "))
- proutn(cramlc(quadrant, game.state.kscmdr))
- prout(" has been destroyed")
- prout(" by the Super-commander.\"")
- break
- return False # looks good!
-
-def scom():
- # move the Super Commander
- if (idebug):
- prout("== SCOM")
-
- # Decide on being active or passive
- passive = ((NKILLC+NKILLK)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) \
- or (game.state.date-game.indate) < 3.0)
- if not game.iscate and passive:
- # coxmpute move away from Enterprise
- delta = game.state.kscmdr - game.quadrant
- if distance(game.state.kscmdr) > 2.0:
- # circulate in space
- delta.x = game.state.kscmdr.y-game.quadrant.y
- delta.y = game.quadrant.x-game.state.kscmdr.x
- else:
- if len(game.state.bases):
- unschedule("FSCMOVE")
- return
- sc = game.state.kscmdr
- # compute distances to starbases
- game.starbases.sort(lambda x, y: cmp(distance(x, game.quadrant), distance(y, game.quadrant)))
- # look for nearest base without a commander, no Enterprise, and
- # without too many Klingons, and not already under attack.
- nearest = filter(game.starbases,
- lambda x: game.state.galaxy[x].supernova \
- and game.state.galaxy[x].klingons <= MAXKLQUAD-1)
- if game.quadrant in nearest:
- nearest.remove(game.quadrant)
- if game.battle in nearest:
- nearest.remove(game.battle)
- # if there is a commander, and no other base is appropriate,
- # we will take the one with the commander
- nocmd = filter(lambda x: x.location not in game.state.kcmdr, nearest)
- if len(nocmd):
- nearest = nocmd
- ibq = nearest[0]
- if len(nearest) == 0:
- return # Nothing suitable -- wait until next time
- # decide how to move toward base
- delta = ibq - game.state.kscmdr
- # maximum movement is 1 quadrant in either or both axis
- delta = delta.sgn()
- # try moving in both x and y directions
- iq = game.state.kscmdr + delta
- if movescom(iq, passive):
- # failed -- try some other maneuvers
- if delta.x==0 or delta.y==0:
- # attempt angle move
- if delta.x != 0:
- iq.y = game.state.kscmdr.y + 1
- if movescom(iq, passive):
- iq.y = game.state.kscmdr.y - 1
- movescom(iq, passive)
- else:
- iq.x = game.state.kscmdr.x + 1
- if movescom(iq, passive):
- iq.x = game.state.kscmdr.x - 1
- movescom(iq, passive)
- else:
- # try moving just in x or y
- iq.y = game.state.kscmdr.y
- if movescom(iq, passive):
- iq.y = game.state.kscmdr.y + delta.y
- iq.x = game.state.kscmdr.x
- movescom(iq, passive)
- # check for a base
- if len(game.state.bases) == 0:
- unschedule("FSCMOVE")
- else:
- for ibq in game.bases:
- if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
- # attack the base
- if passive:
- return # no, don't attack base!
- game.iseenit = false
- game.isatb = 1
- schedule("FSCDBAS", 1.0 +2.0*Rand())
- if is_scheduled("FCDBAS"):
- postpone("FSCDBAS", scheduled("FCDBAS")-game.state.date)
- if not communicating():
- return # no warning
- game.iseenit = True
- pause_game(true)
- proutn(_("Lt. Uhura- \"Captain, the starbase in "))
- proutn(cramlc(quadrant, game.state.kscmdr))
- skip(1)
- prout(" reports that it is under attack from the Klingon Super-commander.")
- proutn(" It can survive until stardate %d.\"",
- int(scheduled(FSCDBAS)))
- if not game.resting:
- return
- prout("Mr. Spock- \"Captain, shall we cancel the rest period?\"")
- if ja() == false:
- return
- game.resting = False
- game.optime = 0.0 # actually finished
- return
- # Check for intelligence report
- if (Rand() > 0.2 or not communicating() or
- not game.state.galaxy[game.state.kscmdr].charted):
- return
- pause_game(true)
- prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
- proutn(_(" the Super-commander is in "))
- proutn(cramlc(quadrant, game.state.kscmdr))
- prout(".\"")
- return
-
-def movetho(void):
- "Move the Tholian (an instance of ship type pointed at by game.tholian)."
- if not game.tholian or game.justin:
- return
- next = coord()
- if game.tholian.location.x == 1 and game.tholian.location.y == 1:
- next.x = 1
- next.y = QUADSIZE
- elif game.tholian.location.x == 1 and game.tholian.location.y == QUADSIZE:
- next.x = next.y = QUADSIZE
- elif game.tholian.location.x == QUADSIZE and game.tholian.location.y == QUADSIZE:
- next.x = QUADSIZE
- next.y = 1
- elif game.tholian.location.x == QUADSIZE and game.tholian.location.y == 1:
- next.x = next.y = 1
- else:
- # something is wrong!
- game.tholian = None
- return
- # Do nothing if we are blocked
- if not (isinstance(game.quad[next], space) or isinstance(game.quad[next], web)):
- return
- # Now place some web
- im = (next - game.tholian.location).sgn()
- if game.tholian.x != next.x:
- # move in x axis
- while game.tholian.location.x != next.x:
- game.tholian.location.x += im.x
- if isinstance(game.quad[game.tholian.location], space):
- game.quad[game.tholian.location] = web()
- elif game.tholian.y != next.y:
- # move in y axis
- while game.tholian.y != next.y:
- game.tholian.y += im.y
- if isinstance(game.quad[game.tholian.location], space):
- game.quad[game.tholian.location] = web()
- # web is done, move ship
- game.tholian.movesector(next)
- # check to see if all holes plugged
- for i in range(1, QUADSIZE+1):
- if (not isinstance(game.quad[(1,i)],web)) and game.quad[(1,i)]!=game.tholian:
- return
- if (not isinstance(game.quad[(QUADSIZE,i)],web)) and game.quad[(QUADSIZE,i)]!=game.tholian:
- return
- if (not isinstance(game.quad[(i,1)],web)) and game.quad[(i,1)]!=game.tholian:
- return
- if (not isinstance(game.quad[(i.QUADSIZE)],web)) and game.quad[(i,QUADSIZE)]!=game.tholian:
- return
- # All plugged up -- Tholian splits
- game.quad[game.tholian] = web()
- ship.movesector(None)
- crmena(True, IHT, sector, game.tholian)
- prout(" completes web.")
- game.tholian = None
- return