'''''''''''''''''''''''''''''''''
' W O I M A  1.0 (J-J Oikkonen) '
' Freeware                      '
' AI.BAS eli taistelun tekoly  '
'''''''''''''''''''''''''''''''''
'$INCLUDE: 'woima.bi'
DEFINT A-Z
DECLARE FUNCTION Kohteita% (xx%, yy%, hahmo)
DECLARE FUNCTION Vaaroja% (tempX%, tempY%)
DECLARE SUB TarkistaSuunta (tx AS INTEGER, ty AS INTEGER)
DECLARE SUB Delay (Seconds!)
DECLARE FUNCTION HasLine% (tempX AS INTEGER, tempY AS INTEGER, mihinX AS INTEGER, mihinY AS INTEGER, kantama AS INTEGER)
DECLARE FUNCTION LataaTile (tile$, hae$, snum)
DECLARE FUNCTION TileTyyppi (tile AS STRING)
DECLARE FUNCTION KenenSotilas (hahmo$)
DECLARE FUNCTION MikaSotilas$ (liitto, hahmo)
DECLARE FUNCTION SotilaanTyyppi (hahmo$)
DECLARE SUB TarkistaRuutu (kohtaX, kohtaY, tilenum)
DECLARE SUB AktivoiTile (uX, uY)
DECLARE SUB AsetaUkko (kenen, kuka, uX, uY, I)
DECLARE SUB XYmByDir (suunta, xm, ym)
DECLARE SUB GetBlock (xx, yy, tulos)
DECLARE SUB DirByXYm (xx, yy, tulos)
DECLARE FUNCTION max (xx, yy)
DECLARE FUNCTION MikaTile$ (tilenumn)
DECLARE SUB PiirraTile (tilenum, sijaintiX, sijaintiY)
DECLARE SUB PiirraKentta (mode)
DECLARE SUB HiiriStatus (VH, OH, XHiiri, YHiiri, hx, hy)
DECLARE SUB HiiriHide ()
DECLARE SUB HiiriShow ()
DECLARE SUB Font (Fonti$, col, tx, ty, koko, script$)
DECLARE SUB VuoronVaihto ()
DECLARE SUB TeeLoitsu ()
DECLARE SUB LoppuTili ()
DECLARE SUB PikaApu ()
DECLARE SUB NaytaTile (locX, locY)
DECLARE SUB NaytaTulilinja (VH, OH)
DECLARE SUB Turnit ()
DECLARE SUB AsetaTekstit (vasen, keski, oikea)
DECLARE SUB UkkojenAsettelu ()
DECLARE SUB Sovinto ()
DECLARE SUB AImove (kumpi)
DECLARE SUB AktivoiAi (liitto)

DIM SHARED kohde    ''Aktivoitu kohde (spritenum)
DIM SHARED tempX, tempY
DIM SHARED vast AS INTEGER, ParasHahmo AS INTEGER

REM $DYNAMIC
SUB AiAseta (kuka)
DIM xx, yy, xm, ym     '' Muuttujat sijaintia varten
DIM tile1, uusiksi, kohta
DIM rran, rivi, melee, rang, rang2
DIM tmap(19, 11)

'' AI asettaa yhden hahmonsa paikoilleen (kuka = liittouman nmr.)
  IF vuorossa = vastus(1).vastus THEN
        ''haetaan 1 vastustaja (hyokkaaja) hahmojen maara
        melee = vastus(1).miekat
        rang = vastus(1).jouset
        rang2 = vastus(1).heitto
  ELSE  '' muutoin haetaan 2 vastustajan hahmojen maara
        melee = vastus(2).miekat
        rang = vastus(2).jouset
        rang2 = vastus(2).heitto
  END IF

  meleemies$ = MikaSotilas$(vuorossa, 1)
  jousimies$ = MikaSotilas$(vuorossa, 0)
  heittomies$ = MikaSotilas$(vuorossa, 2)
 
  IF RTRIM$(Ukko(1).nimi) = "" THEN '' Tt ennen ei ole aseteltu -> AI asettaa ensimmisen
    '' Ensin asetetaan jouset vhintn 3 askeleen vlimatkoin
    '' Ensimminen randomiin paikkaan
    kohta = kohta + 1   '' tallennetaan hahmo muistipaikkaan X (eli kohta)
    DO
     xx = INT(RND * 19) + 1: yy = INT(RND * 4) + 4
    '' kunnes loytyy tyhja paikka
    LOOP UNTIL map(mapnum, xx, yy) = 0
    IF rang > 0 THEN CALL AsetaUkko(vuorossa, SotilaanTyyppi(jousimies$), xx, yy, kohta): kohta = kohta + 1
    '' Siteen aloitetaan asettamalla jousimiehet
    mies$ = jousimies$
    FOR aa = 2 TO rang
     GOSUB EtsiMel
    NEXT aa
    '' Sitten heittomiehet
    mies$ = heittomies$
    uusiksi = 0
    FOR aa = 1 TO rang2
     GOSUB EtsiMel
    NEXT
    '' Sitten meleehykkjt
    mies$ = meleemies$
    uusiksi = 0
    FOR aa = 1 TO melee
     GOSUB EtsiMel
    NEXT aa

  '' HYKKYS asettelu
  ELSE  '' vastustaja on jo asettanut - Haetaan taktiset paikat
 
  'aktivoidaan oliot
  AktivoiAi 1
  kohta = vastus(2).miekat + vastus(2).jouset + vastus(2).heitto
  
  ''ampujat
  rran = LataaTile(jousimies$, "kanto", 0)
  maxm = rang + vastus(2).miekat + vastus(2).jouset + vastus(2).heitto
  mies$ = jousimies$
  uusiksi = 1
  GOSUB katsopaikat
  GOSUB AsetaUkot
  IF kohta < maxm THEN
   uusiksi = -5
   GOSUB AsetaUkot
  END IF
 
  ''heitto
  rran = LataaTile(heittomies$, "kanto", 0)
  maxm = rang + rang2 + vastus(2).miekat + vastus(2).jouset + vastus(2).heitto
  mies$ = heittomies$
  uusiksi = 1
  GOSUB katsopaikat
  GOSUB AsetaUkot
  IF kohta < maxm THEN
   uusiksi = -5
   GOSUB AsetaUkot
  END IF
 
  ''meleemiehet
  rran = LataaTile(meleemies$, "kanto", 0)
  maxm = melee + rang + rang2 + vastus(2).miekat + vastus(2).jouset + vastus(2).heitto
  mies$ = meleemies$
  uusiksi = 0
  GOSUB katsopaikat
  GOSUB AsetaUkot
  IF kohta < maxm THEN
   uusiksi = -5
   GOSUB AsetaUkot
  END IF
 END IF
EXIT SUB

AsetaUkot:
   FOR y = 1 TO 4
    FOR x = 2 TO 18
      rivi = y
      IF y = 2 THEN rivi = 11
      IF y = 3 THEN rivi = 2
      IF y = 4 THEN rivi = 10
      IF tmap(x, rivi) >= uusiksi AND map(mapnum, x, rivi) = 0 AND kohta < maxm THEN
       TarkistaRuutu x, rivi, tile1
       IF tile1 = 0 THEN kohta = kohta + 1: AsetaUkko vuorossa, SotilaanTyyppi(mies$), x, rivi, kohta
       IF kohta = maxm THEN EXIT FOR
      END IF
    NEXT
    IF kohta = maxm THEN EXIT FOR
   NEXT
RETURN

katsopaikat:
  FOR y = 1 TO 4
   FOR x = 1 TO 19
     rivi = y
     IF y = 3 THEN rivi = 11
     IF y = 4 THEN rivi = 10
     IF map(mapnum, x, rivi) = 0 THEN
       TarkistaRuutu x, rivi, tile1
       IF tile1 = 0 THEN
        pisteet = Kohteita(x, rivi, rran) - Vaaroja(x, rivi)
        tmap(x, rivi) = pisteet
       ELSE
        tmap(x, rivi) = -1
       END IF
     END IF
   NEXT
  NEXT
 RETURN

EtsiMel:
otataasuusi:
      uusiksi = uusiksi + 1
      xx = INT(RND * 19) + 1: yy = INT(RND * 6) + 4
      TarkistaRuutu xx, yy, tile1
      IF tile1 = 0 AND map(mapnum, xx, yy) = 0 THEN
        CALL AsetaUkko(vuorossa, SotilaanTyyppi(mies$), xx, yy, kohta)
        kohta = kohta + 1
      ELSE
        IF uusiksi < 12 THEN '' koetetaan yh arpoa
          GOTO otataasuusi
        ELSE '' Haetaan 1. vapaa
          xx = INT(RND * 6): yy = 1
          DO
            xx = xx + 1
            IF xx > 19 THEN xx = 1: yy = yy + 1
            TarkistaRuutu xx, yy, tile1
          LOOP UNTIL tile1 = 0 AND map(mapnum, xx, yy) = 0
          kohta = kohta + 1
          CALL AsetaUkko(vuorossa, SotilaanTyyppi(mies$), xx, yy, kohta)
        END IF
      END IF
      uusiksi = 0
RETURN
END SUB

REM $STATIC
SUB AiLinkotuli
 DIM kohdeRak, sijY, sijX, osuma, blokki

 ''tila
 kohdeRak = 2: GOSUB etsiRak
  IF kohdeRak = 0 THEN kohdeRak = -1
 ''varasto
 IF kohdeRak > 0 THEN kohdeRak = 5: GOSUB etsiRak
 IF kohdeRak = 0 THEN kohdeRak = -1
 ''karjatila
 IF kohdeRak > 0 THEN kohdeRak = 7: GOSUB etsiRak
 IF kohdeRak = 0 THEN kohdeRak = -1
 ''muut rakennukset
 IF kohdeRak > 0 THEN
  FOR kohdeRak = 4 TO 6
   GOSUB etsiRak
   IF kohdeRak = 0 THEN kohdeRak = -1: EXIT FOR
  NEXT
 END IF

 IF kohdeRak = -1 THEN             ''kohde aktivoitu. Ammutaan
 RANDOMIZE TIMER
 osuma = INT(RND * 10) + 1
 blokki = INT(RND * LataaTile(MikaTile$(map(mapnum, sijX, sijY)), "pb", 0)) + 1
 '' Jos osuma niin tuhotaan kohde kartalta!!
 IF osuma > blokki THEN
    '' Poistetaan rakennelma hahmo()-taulukosta
    IF TileTyyppi(MikaTile$(map(mapnum, sijX, sijY))) = 2 THEN
     hahmo(mapnum).tiloja = hahmo(mapnum).tiloja - 1
    ELSEIF TileTyyppi(MikaTile$(map(mapnum, sijX, sijY))) = 4 THEN
     hahmo(mapnum).tornit = hahmo(mapnum).tornit - 1
    ELSEIF TileTyyppi(MikaTile$(map(mapnum, sijX, sijY))) = 5 THEN
     hahmo(mapnum).ladot = hahmo(mapnum).ladot - 1
    ELSEIF TileTyyppi(MikaTile$(map(mapnum, sijX, sijY))) = 6 THEN
     hahmo(mapnum).aidat = hahmo(mapnum).aidat - 1
    END IF
    '' Pyyhittn tile kartalta!
    '' Jos tilen koko 2 niin pyyhitn mys virell oleva tile
    IF LataaTile(MikaTile$(map(mapnum, sijX, sijY)), "koko", 0) = 2 THEN map(mapnum, sijX - 1, sijY) = 0
    map(mapnum, sijX, sijY) = 0
    PiirraKentta 0
   
    '' nollataan Taito -pisteet
    IF vuorossa = vastus(1).vastus THEN vastus(1).mana = 1 ELSE vastus(2).mana = 1
 END IF
 END IF
 EXIT SUB

etsiRak:
 ''Katsotaan kartalta lytyyk ositettua rakennusta
  FOR ky = 1 TO 11
   FOR kx = 1 TO 19
    IF map(mapnum, kx, ky) = kohdeRak THEN
       sijX = kx
       sijY = ky
       kohdeRak = 0
    END IF
  NEXT: NEXT
RETURN

END SUB

REM $DYNAMIC
SUB AImove (kumpi)
''(Pelaaja kumpi tekee AI-siirron)
DIM Kohteet AS INTEGER, vaarat AS INTEGER, aa AS INTEGER, vv AS INTEGER
DIM suhde AS INTEGER, ssuhde AS INTEGER
DIM xx AS INTEGER, yy AS INTEGER, typ AS INTEGER
DIM kvaara AS INTEGER, kkohde AS INTEGER, xm AS INTEGER, ym AS INTEGER
DIM rran AS INTEGER, eran AS INTEGER, bb AS INTEGER
'' 23.4.2005
CONST ampuu.d = 256
DIM blocked AS INTEGER, dirr AS INTEGER

  IF kumpi < 0 THEN kumpi = 1
  IF kumpi > 2 THEN kumpi = 2
  vast = 3 - kumpi

  ' Korjaus bugiin 1: jos vastustajia ei ole, ei myskn liikuta.
  IF CrNum(vast) < 1 THEN EXIT SUB
  IF vuorot < 1 THEN EXIT SUB

  ssuhde = -1
 
  '' Haetaan siirrettv ukkeli.
  ParasHahmo = 1 '' oletuksena
  FOR aa = 1 TO CrNum(kumpi)
    vaarat = 0: Kohteet = 0: typ = SotilaanTyyppi(Ukko(oliolinkit(kumpi, aa)).nimi)
    '' Haetaan hahmon range (muilla tiedoilla ei vli)...
    rran = LataaTile(Ukko(oliolinkit(kumpi, aa)).nimi, "kanto", 0)
    '' Montako vaaraa hahmolla on?
    vaarat = Vaaroja(Ukko(oliolinkit(kumpi, aa)).x, Ukko(oliolinkit(kumpi, aa)).y)
    '' Montako kohdetta hahmolla on?
    Kohteet = Kohteita(Ukko(oliolinkit(kumpi, aa)).x, Ukko(oliolinkit(kumpi, aa)).y, rran)
    '' Tekee yhteens...
    suhde = vaarat + Kohteet
   
    '' Pudotetaan suhdetta jos hahmo on toiminut aikaisemmin
    IF Kaytetty(oliolinkit(kumpi, aa)) > 0 THEN suhde = suhde - 2
    'PRINT "   "; STR$(aa); STR$(kohteet); STR$(vaarat)
    IF suhde > ssuhde AND Kaytetty(oliolinkit(kumpi, aa)) < 2 AND vuorot > Kaytetty(oliolinkit(kumpi, aa)) THEN
      ssuhde = suhde: ParasHahmo = aa: kvaara = vaarat: kkohde = Kohteet
    END IF
  NEXT aa

  '' hahmon tyyppi
  typ = SotilaanTyyppi(Ukko(oliolinkit(kumpi, ParasHahmo)).nimi)

  '' parashahmo = ukkeli, jota siirretn.
  ParasHahmo = oliolinkit(kumpi, ParasHahmo)

  xx = Ukko(ParasHahmo).x: yy = Ukko(ParasHahmo).y

  ' Tutkitaan ymprist
  GetBlock xx, yy, blocked

  hx% = xx: hy% = yy
  AktivoiTile xx, yy '' aktivoidaan kaiffari

  TarkistaRuutu xx, yy, 1  'oma$ = mit siirretn

  rran = LataaTile(Ukko(ParasHahmo).nimi, "kanto", ParasHahmo)

 '' Seuraava aktivoitava kohde on myskin xx, yy - ptelln se.
 '' haetaan paras mahdollinen kohde/suunta...
uusiliike:
  IF typ = 1 THEN
    '' Meleemiehelle haetaan suoraan sen lhin kohde ...
    kohde = -1: vv = 100
    FOR aa = 1 TO CrNum(vast)
      IF Ukko(oliolinkit(vast, aa)).x <> 0 THEN ''olio on yh pll
        xx = Ukko(ParasHahmo).x - Ukko(oliolinkit(vast, aa)).x
        yy = Ukko(ParasHahmo).y - Ukko(oliolinkit(vast, aa)).y
        IF max(ABS(xx), ABS(yy)) < vv THEN
          kohde = oliolinkit(vast, aa)
          vv = max(ABS(xx), ABS(yy))
        END IF
      END IF
    NEXT aa
   
    IF vv <= 1 THEN 'lhin mt on meleeiskualueella...
      xm = Ukko(kohde).x - Ukko(ParasHahmo).x
      ym = Ukko(kohde).y - Ukko(ParasHahmo).y
      'PRINT ">"; xm; ym; kohde; parashahmo
    '' Muuten jos kohde ei lymetisyydell, ptelln mihinka liikutaan
    '' jotta pstisiin lymn tt
    ELSE
      xm = 0: ym = 0
      IF Ukko(ParasHahmo).x > Ukko(kohde).x THEN
        xm = -1
      ELSEIF Ukko(ParasHahmo).x < Ukko(kohde).x THEN
        xm = 1
      END IF
      IF Ukko(ParasHahmo).y > Ukko(kohde).y THEN
        ym = -1
      ELSEIF Ukko(ParasHahmo).y < Ukko(kohde).y THEN
        ym = 1
      END IF
      '' Kenties vistelev liikett thn vliin?
      '' FUNCTION OnkoVaaraa(x,y)??
    END IF
 
  ELSE '' Jousiampuja/ Heittomies - liikutaanko vai ammutaanko?
    '' 23.4.2005: Jos ampujaa uhkaa 2 tai enemmn lhietisyydelt,
    '' se perntyy.
    ' Kohteita on, eik juurikaan vaaraa...
    IF kkohde > 0 AND kvaara < 5 THEN
      '' Onko kohteita tarjolla? haetaan ensimminen...
      kohde = -1
      FOR aa = 1 TO CrNum(vast)
        xx = Ukko(ParasHahmo).x - Ukko(oliolinkit(vast, aa)).x
        yy = Ukko(ParasHahmo).y - Ukko(oliolinkit(vast, aa)).y
        IF HasLine(Ukko(ParasHahmo).x, Ukko(ParasHahmo).y, Ukko(oliolinkit(vast, aa)).x, Ukko(oliolinkit(vast, aa)).y, LataaTile(Ukko(ParasHahmo).nimi, "kanto", 0)) THEN ''kohde!!
          'LOCATE 2, 1: PRINT "()"; xx; yy; max(ABS(xx), ABS(yy))
          kohde = oliolinkit(vast, aa): EXIT FOR
          xx = Ukko(kohde).x: yy = Ukko(kohde).y
        ELSE
          blocked = (blocked OR ampuu.d)
        END IF
      NEXT aa
      '' Ei tarvitse laskea suuntaa, jos etisyydell
      IF kohde >= 0 THEN
        blocked = (blocked OR ampuu.d)
        xx = Ukko(kohde).x: yy = Ukko(kohde).y
      'IF kohde <= 0 THEN ' Ei mukamas kohteita! xx,yy = nykyinen sijainti.
      '  xx = Ukko(ParasHahmo).x: yy = Ukko(ParasHahmo).y
      END IF
      ' Virheellinen sijainti
      IF xx < 1 OR yy < 1 OR xx > 19 OR yy > 11 THEN
        PRINT "Error (sijainti): J:<"; kohde; xx; yy; ">"
        END
      END IF
    ELSEIF kvaara < 5 THEN '' ei kohteita eik juurikaan vaaroja -  minne liikutaan?
      kohde = 0: eran = 0
      FOR aa = 1 TO CrNum(vast)
        IF Ukko(oliolinkit(vast, aa)).x <> 0 THEN ''olio on yh pll
          kohde = oliolinkit(vast, aa)
          xx = Ukko(ParasHahmo).x - Ukko(kohde).x
          yy = Ukko(ParasHahmo).y - Ukko(kohde).y
          vaara = ABS(xx) - ABS(yy)
          '' Minne pit liikkua ett oltaisiin vastustajan kanssa tulilinjalla?
          '' yy tai xx posit. jos ukko >> kohde, muuten negat.
          IF ABS(vaara) <= 2 THEN ' On mahdollista liikkua vinoviivalle tmn kanssa
            xm = 0: ym = 0
            SELECT CASE vaara
              CASE -2: xm = 1: ym = -1
              CASE 2: xm = -1: ym = 1
              CASE -1
                xm = INT(RND * 2): IF xm = 0 THEN ym = -1
                IF Ukko(ParasHahmo).x = 1 THEN xm = 1: ym = 0
              CASE 1
                xm = INT(RND * 2) - 1: IF xm = 0 THEN ym = 1
                IF Ukko(ParasHahmo).y = 11 THEN xm = -1: ym = 0
              CASE 0: ' Ollaan jo, liikutaanpa sitten lhemms ellei kantaman pss
                IF max(ABS(xx), ABS(yy)) > rran THEN
                  xm = SGN(Ukko(kohde).x - Ukko(ParasHahmo).x)
                  ym = SGN(Ukko(kohde).y - Ukko(ParasHahmo).y)
                ELSE
                  xm = 0: ym = 0: eran = 1
                  EXIT FOR
                END IF
            END SELECT
            IF ABS(vaara) <> 0 THEN
              IF xx < 0 THEN xm = 0 - xm
              IF yy < 0 THEN ym = 0 - ym
            END IF
            'xx = ukko(parashahmo).X + xm: yy = ukko(parashahmo).Y + ym
            ' Tulilinja on kentn ulkopuolella => askel sit kohti
            '' 21.1.2006 - muunnettu kentst pois ajautuminen.
            IF Ukko(ParasHahmo).x + xm < 1 OR Ukko(ParasHahmo).x + xm > 19 THEN
              xm = 0
            END IF
            IF Ukko(ParasHahmo).y + ym < 1 OR Ukko(ParasHahmo).y + ym > 11 THEN
              ym = 0
            END IF
            EXIT FOR
          END IF
        END IF
      NEXT aa
      '' Jos yh ollaan tll hengiss, ei lydetty vastustajaa.
      '' Liikutaan siis kohti lhint, eli muutetaan tyyli hetkeksi
      '' meleeijksi
      IF xm = 0 AND ym = 0 AND eran = 0 THEN typ = 1: GOTO uusiliike
'      PRINT STR$(xm); STR$(ym)
    ELSE '' PAKOON! 23.5.2005
      '' Haetaan suunta, jossa ei oliota ja sinne
      kohde = -1
      FOR aa = 1 TO CrNum(vast)
        IF Ukko(oliolinkit(vast, aa)).x <> 0 THEN ''olio on yh pll
          xx = Ukko(ParasHahmo).x - Ukko(oliolinkit(vast, aa)).x
          yy = Ukko(ParasHahmo).y - Ukko(oliolinkit(vast, aa)).y
'          PRINT STR$(xx); STR$(yy); "::";
          IF ABS(xx) = 1 AND ABS(yy) = 1 THEN
            kohde = oliolinkit(vast, aa)
            EXIT FOR
          END IF
        END IF
      NEXT aa
      '' Liike on negatiivinen, eli pakoonpin
      xm = SGN(Ukko(ParasHahmo).x - Ukko(kohde).x)
      ym = SGN(Ukko(ParasHahmo).y - Ukko(kohde).y)
'      PRINT STR$(xm); STR$(ym);
    END IF '' if kohteet
  END IF '' if jousiampuja

  ' Onko sijainti lukittu?
  DirByXYm xm, ym, dirr
  IF (blocked AND dirr) AND (blocked < ampuu.d) THEN
    '' Haetaan suunta jossa ei blokkia. Etsitn suunta, jossa ei
    '' ei estett ja pstn mahd. suoraan kimppuun
    '' Kaarretaan oikeaan, eli kerrotaan suuntaa kahdella
    vv = dirr
    FOR aa = 1 TO 4
      IF (blocked AND vv) THEN
        vv = vv * 2
        IF vv > 128 THEN vv = 1 'ympri
      END IF
    NEXT aa
    '' Vasempaan
    eran = dirr
    FOR bb = 1 TO 4
      IF (blocked AND eran) THEN
        eran = CINT(eran / 2)
        IF eran < 1 THEN eran = 128 'ympri
      END IF
    NEXT
    '' Kumman kautta 'lyhyempi' kntym?
    'PRINT "::"; aa; bb; vv; eran; "::";
    IF aa < bb THEN
      XYmByDir vv, xm, ym
    ELSE
      XYmByDir eran, xm, ym
    END IF
    'PRINT xm; ym; "::"
  END IF

  ' Lasketaan liikkumiskohteen sijainti
  IF blocked < ampuu.d THEN
    TarkistaSuunta xm, ym
    xx = Ukko(ParasHahmo).x + xm: yy = Ukko(ParasHahmo).y + ym
  END IF

  ' Aktivoidaan kenties paras kohta

  'PRINT xx; yy

  hx% = xx: hy% = yy '' Varmaan bugi, kun nm pit pivitt?

  '' Jumituksen esto. Lasketaan ain liikkeet, jos ai ei saa toimittua skipataan vuoro
  aiLiike = aiLiike + 1
  IF aiLiike > 5 THEN
    ''poistetaan vanhan hahmon korostus
    PUT ((tempX - 1) * 16 + 7, (tempY - 1) * 16 + 1), korostus, PSET
    vuorot = 0: Turnit
  END IF
  AktivoiTile xx, yy

END SUB

SUB AktivoiAi (liitto)
'' Aktivoi AI:n taistelua varten. liitto = kumpi pelaaja on listoissa 1.:n?
'' Eli 1 = hykkj, 2 = puolustaja. Tmn jlkeen
'' AI:ta komennetaan AIMove:lla, joka ottaa parametriksi 1:ksi asetetun
'' joukon. Eli jos kutsuttiin AktivoiAI 1, niin AiMove 1 liikuttaa
'' hykkj ja AiMove 2 puolustajaa. Tai jos aktivoitiin 2:lla, niin
'' AiMove 1 liikuttaa puolustajaa ja AiMove 2 hykkj.
  DIM aa
  CrNum(1) = 0: CrNum(2) = 0' Alustetaan olioiden mrt
  FOR aa = 1 TO 40
  '' Onko hahmo pll?
    IF RTRIM$(Ukko(aa).nimi) > "" THEN
      '' Onko hahmo tss liiton sotilas?
      IF KenenSotilas(Ukko(aa).nimi) = vastus(liitto).vastus THEN
        CrNum(1) = CrNum(1) + 1
        oliolinkit(1, CrNum(1)) = aa
      ELSE '' Vastustajan sotilas
        CrNum(2) = CrNum(2) + 1
        oliolinkit(2, CrNum(2)) = aa
      END IF
    END IF
  NEXT aa

END SUB

REM $STATIC
SUB DirByXYm (xx, yy, tulos)
CONST ylos.d = 1, alas.d = 16, oikea.d = 4, vasen.d = 64, ylaoik.d = 2, alaoik.d = 8, ylavas.d = 128, alavas.d = 32
'' Palauttaa suunnan (liput) annettujen xx:n ja yy:n mukaan. Molemmat e(-1,1)
  SELECT CASE (xx * 3 + yy) + 4
    CASE 0 'xm = -1, ym = -1
      tulos = ylavas.d
    CASE 1 'xm = -1, ym = 0
      tulos = vasen.d
    CASE 2 'xm = -1, ym = 1
      tulos = alavas.d
    CASE 3 'xm = 0, ym = -1
      tulos = ylos.d
    CASE 4 'xm = 0, ym = 0
      tulos = 0
    CASE 5 'xm = 0, ym = 1
      tulos = alas.d
    CASE 6 'xm = 1, ym = -1
      tulos = ylaoik.d
    CASE 7 'xm = 1, ym = 0
      tulos = oikea.d
    CASE 8 'xm = 1, ym = 1
      tulos = alaoik.d
  END SELECT
END SUB

SUB GetBlock (xx, yy, tulos)
''Tutkitaan hahmon lhiympristn
DIM x2, y2, zz, ss
  FOR y2 = -1 TO 1
  FOR x2 = -1 TO 1
    '' Katso mik on suunta
    DirByXYm x2, y2, ss
    '' Onko ukkoa?
    TarkistaRuutu xx + x2, yy + y2, zz
    '' Kyll jokin...
    IF zz > 0 THEN
      '' Tukkona on oma sotilas...
      IF KenenSotilas(Ukko(zz).nimi) = vuorossa THEN
        tulos = (tulos OR ss)
      END IF
    END IF
    ' Kohdassa on este...
    IF xx + x2 > 0 AND xx + x2 < 20 AND yy + y2 > 0 AND yy + y2 < 12 THEN
      IF map(mapnum, xx + x2, yy + y2) <> 0 THEN
        tulos = (tulos OR ss)
      END IF
    ELSE ''maailmanraja toimii mys esteen
      tulos = (tulos OR ss)
    END IF
  NEXT x2, y2
END SUB

FUNCTION HasLine (tempX AS INTEGER, tempY AS INTEGER, mihinX AS INTEGER, mihinY AS INTEGER, kantama AS INTEGER)
'' Onko kantamalla esteit
DIM x AS INTEGER, y AS INTEGER, xm AS INTEGER, ym AS INTEGER, num AS INTEGER, aija$
 
  x = tempX: y = tempY
  xm = SGN(mihinX - tempX)
  ym = SGN(mihinY - tempY)
  HasLine = 0
  FOR c = 1 TO kantama
    x = x + xm: y = y + ym
    IF x < 1 OR y < 1 OR x > 19 OR y > 11 THEN HasLine = 0: EXIT FOR
    'este?
    IF map(mapnum, x, y) <> 0 THEN IF NOT map(mapnum, x, y) = 7 THEN HasLine = 0: EXIT FOR
    'oma edess
    TarkistaRuutu x, y, num
    IF KenenSotilas(Ukko(num).nimi) = vuorossa THEN HasLine = 0: EXIT FOR
    'vapaa -_-
    IF x = mihinX AND y = mihinY THEN HasLine = 1: EXIT FOR
  NEXT
END FUNCTION

FUNCTION Kohteita (tempX AS INTEGER, tempY AS INTEGER, range AS INTEGER)
'' Katsotaan montako kohdetta lydmme kanto(range) etisyydelt annetusta sijainnista.
'' Funktio palauttaa kohteiden mrn
DIM Kohteet AS INTEGER, vv AS INTEGER

 '' Kydn lpi vastustajan hahmot. Onko annetusta sijantissa ampumalinja thn
 IF vuorossa = vastus(1).vastus THEN vast = 2 ELSE vast = 1   'varmistus
 Kohteet = 0
 FOR vv = 1 TO CrNum(vast)
  '' Onko sijainnista mahd. ampua vastustajaa
  IF HasLine(tempX, tempY, Ukko(oliolinkit(vast, vv)).x, Ukko(oliolinkit(vast, vv)).y, range) THEN Kohteet = Kohteet + 1
 NEXT

 Kohteita = Kohteet
END FUNCTION

FUNCTION max (xx, yy)
  IF xx > yy THEN max = xx ELSE max = yy
END FUNCTION

SUB TarkistaSuunta (tx AS INTEGER, ty AS INTEGER)
'' Viimeinen tarkistus mahd. bugien varalta ennen liikkumista.
'' Eli tarkistetaan jos jostain syyst yritetn tehd laitointa liikett
DIM ukkoX AS INTEGER, ukkoY AS INTEGER, laiton AS INTEGER
DIM num AS INTEGER, x2 AS INTEGER, y2 AS INTEGER

 ukkoX = Ukko(char).x
 ukkoY = Ukko(char).y
 laiton = 0

 '' Tarkistetaan sytetty liike, onko laillinen
 TarkistaRuutu ukkoX + tx, ukkoY + ty, num
 '' Hahmo tiell?
 IF KenenSotilas(Ukko(num).nimi) = vuorossa THEN laiton = TRUE
 '' Kohdassa on este...
 IF ukkoX + tx > 0 AND ukkoX + tx < 20 AND ukkoY + ty > 0 AND ukkoY + ty < 12 THEN
  IF map(mapnum, ukkoX + tx, ukkoY + ty) <> 0 THEN laiton = TRUE
 ELSE
  ''maailman rajat ylittv on mys laiton
  laiton = TRUE
 END IF

 '' Liike on todettu laittomaksi. Etsitn uusi suunta liikkeelle
 IF laiton THEN
  'LOCATE 1: PRINT "TL:"; ukkoX + tx; ukkoY + ty
   FOR y2 = -1 TO 1
    FOR x2 = -1 TO 1
      '' Tarkistetaan uusi ruutu onko esteit
      TarkistaRuutu ukkoX + x2, ukkoY + y2, num
      IF ukkoX + x2 > 0 AND ukkoX + x2 < 20 AND ukkoY + y2 > 0 AND ukkoY + y2 < 12 THEN
        IF num = 0 AND map(mapnum, ukkoX + x2, ukkoY + y2) = 0 THEN
           '' Vapaa ruutu lytyi
           IF Kohteita(ukkoX + x2, ukkoY + y2, LataaTile(Ukko(char).nimi, "kanto", char)) > Vaaroja(ukkoX + x2, ukkoY + y2) THEN
              '' Kohteitakin lytyy liikutaan siis tnne
              tx = x2: ty = y2
              num = -1
              EXIT FOR
           ELSE
              '' vapaa ruutu lydettiin mutta liikkaa vaaroja tai ei yhtn kumpaakaan.
              '' Otetaan suunta kuitenkin muistiin
              tx = x2: ty = y2
           END IF
        END IF
      END IF
    NEXT x2
    IF num = -1 THEN EXIT FOR
   NEXT y2
 END IF
END SUB

FUNCTION Vaaroja (tempX AS INTEGER, tempY AS INTEGER)
'' Tarkistetaan onko annuttu sijainti turvallinen.
'' Funktio palauttaa vaarojen mrn sijainnissa
DIM vaarat AS INTEGER, vv AS INTEGER, xx AS INTEGER, yy AS INTEGER
 '' Kydn lpi vastustajan hahmot. Onko annetusta sijantissa ampumalinja thn
 IF vuorossa = vastus(1).vastus THEN vast = 2 ELSE vast = 1   'varmistus

 vaarat = 0
 FOR vv = 1 TO CrNum(vast)
  '' Onko vastustajalla mahd. ampua
  xx = Ukko(oliolinkit(vast, vv)).x
  yy = Ukko(oliolinkit(vast, vv)).y
  IF HasLine(xx, yy, tempX, tempY, LataaTile(Ukko(oliolinkit(vast, vv)).nimi, "kanto", oliolinkit(vast, vv))) THEN vaarat = vaarat + 1
 NEXT

Vaaroja = vaarat
END FUNCTION

SUB XYmByDir (suunta, xm, ym)
'' uutta 23.4.2005 - esteenkierto. Katsotaan mitk suunnat on blokattu
'' eli mihin ei ainakaan menn. Listty siis funktio
'' GetBlock(x, y, tulos) joka sijoittaa tulokseen seuraavat liput:
CONST ylos.d = 1, alas.d = 16, oikea.d = 4, vasen.d = 64, ylaoik.d = 2, alaoik.d = 8, ylavas.d = 128, alavas.d = 32
'' Lisksi liikkuma otetaan nyt muulla tavalla kuin etsimisell...
'' Eli mukana mys funktiot XYmByDir ja DirByXYm.
  SELECT CASE suunta
    CASE ylos.d
      xm = 0: ym = -1
    CASE alas.d
      xm = 0: ym = 1
    CASE vasen.d
      xm = -1: ym = 0
    CASE oikea.d
      xm = 1: ym = 0
    CASE ylaoik.d
      xm = 1: ym = -1
    CASE alaoik.d
      xm = 1: ym = 1
    CASE ylavas.d
      xm = -1: ym = -1
    CASE alavas.d
      xm = -1: ym = -1
    CASE ELSE
      xm = 0: ym = 0
  END SELECT
END SUB

