PDA

View Full Version : Manipulating the AI keepers.



Woudo
September 10th, 2014, 15:15
What counts as a gold vein. Is it a single tile of gold (appropriately named "Gold Vein") or a bunch of gold tiles in a group (what a gold vein actually is)
If it's the group, what determines the shape in which the computer will dig gold? Assuming the entire map was gold and you told the AI to dig out 25000 value, would it just select every tile of gold within X radius and cancel once it's reached 25000?

What does "CHECK TO PRETTY" in computer AI processes do? I assume it means reinforcing walls?

Do gems count as gold in computer gold-digging processes?

Is it possible to stop tunnelers from digging without editing the creature file? I thought preplacing tunnelers or adding them to the map via action point and not ADD_PARTY_TO_LEVEL or ADD_TUNNELLER_TO_LEVEL would suffice but nope, they still dig.

- - -

I'm trying to make three AI's stay within in their walls and only dig outwards after a timer but they're not paying attention to the DIG_FOR_GOLD command;



SET_COMPUTER_PROCESS(PLAYER1,"DIG TO CLOSE GOLD",0,76666,2,5)
SET_COMPUTER_PROCESS(PLAYER2,"DIG TO CLOSE GOLD",0,76666,2,5)
SET_COMPUTER_PROCESS(PLAYER3,"DIG TO CLOSE GOLD",0,76666,2,5)

Purple always digs to one vein of gold in one corner of the map (well over the 5 tiles of distance).
Green always digs to a different vein of gold (also well over 5 tiles of distance).
All players have two gem seams near to their heart and they are selecting them, they're just selecting other seams as well.

It's like they're not paying attention to the code at all which makes me think i've implemented it wrong. The script reference doesn't state what the value after "DIG TO CLOSE GOLD" does although apparently it's [priority]. I changed the value from 0 to 10 and no difference was made.

- - -

I'm also having trouble with something else;


CREATE_PARTY(WHAT_HAPPENED)
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,5,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,5,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,7,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,10,0,STEAL_GOLD, 0)

IF_CONTROLS(PLAYER_GOOD,TUNNELLER == 0)
SET_TIMER(PLAYER_GOOD,TIMER0)
ENDIF

IF(PLAYER_GOOD,TIMER0 > 100)
ADD_PARTY_TO_LEVEL(PLAYER_GOOD,WHAT_HAPPENED,-1,2)
ENDIF


The tunnelers are preplaced on the map with a hero gate nearby. The dwarves are supposed to drop in only after the tunnelers are dead and the timer has passed (the timer being short for testing purposes) but the dwarves pop in at the very beginning of the map before the tunnelers are dead.
Yes the tunnelers are owned by the Heroes faction.
Yes I have LEVEL_VERSION(1) to allow KeeperFX script commands.

YourMaster
September 10th, 2014, 15:42
Well, this is the command line:

SET_COMPUTER_PROCESS(​[player],​ ["process name"],​[priority],​[money minimum],​ [turn scale],​[gold dug at once],​ [max distance])

This is your code:

SET_COMPUTER_PROCESS(PLAYER1,"DIG TO CLOSE GOLD",0,76666,2,5) ->
SET_COMPUTER_PROCESS(PLAYER1[PLAYER],"DIG TO CLOSE GOLD"[PROCESS NAME],0[PRIORITY],76666[MONEY MINIMUM],2[TURN SCALE],5[GOLD DUG AT ONCE])

So you notice you're short the MAX DISTANCE, your command won't work.

And as for your 'WHAT_HAPPENED' party, I suspect it loads the script before it actually notices the dwarfs on the map. Try this:


IF(PLAYER1,GAME_TURN > 200)
IF_CONTROLS(PLAYER_GOOD,TUNNELLER == 0)
SET_TIMER(PLAYER_GOOD,TIMER0)
ENDIF
ENDIF

mefistotelis
September 10th, 2014, 15:58
What counts as a gold vein. Is it a single tile of gold (appropriately named "Gold Vein") or a bunch of gold tiles in a group (what a gold vein actually is)
If it's the group, what determines the shape in which the computer will dig gold?

Gold veins contain multiple slabs, when there are multiple gold slabs in the area.

For details, read "check_map_for_gold()" function:
https://code.google.com/p/keeperfx/source/browse/trunk/keeperfx/src/player_complookup.c#186



Assuming the entire map was gold and you told the AI to dig out 25000 value, would it just select every tile of gold within X radius and cancel once it's reached 25000?

Computer player has currently no ability to cancel dig requests.
It counts the digging revenue while selecting. Ech game turn, only one slab is selected.


What does "CHECK TO PRETTY" in computer AI processes do? I assume it means reinforcing walls?
Yes. Computer can pick imps and put them near wall to reinforce or floor to claim.


Do gems count as gold in computer gold-digging processes?
They are recognized as something valuable different than gold.


Is it possible to stop tunnelers from digging without editing the creature file? I thought preplacing tunnelers or adding them to the map via action point and not ADD_PARTY_TO_LEVEL or ADD_TUNNELLER_TO_LEVEL would suffice but nope, they still dig.

I didn't knew the tunnellers are digging in that case. What is their destination?

You may use DWARFA instead - he can't dig.

Woudo
September 10th, 2014, 16:33
REM ###########################################
REM ###########################################

REM ##### SETUP REQUIRED FOR ONE-TIME HERO HARASS AT TREASURY #####

CREATE_PARTY(WHAT_HAPPENED)
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,5,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,5,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,7,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,10,0,STEAL_GOLD, 0)

IF(GAME_TURN > 6000)
ADD_PARTY_TO_LEVEL(PLAYER_GOOD,WHAT_HAPPENED,-1,2)
ENDIF

REM ###########################################
REM ###########################################

After butchering the Dwarf code over and over again, messing around with different flags and timers and what not (none of them working, mind you), I decided to try and cut the code down piece by piece to figure out which line it was upset with. The above is what I ended up with.
THE DWARVES STILL SPAWN INSTANTLY.
I figured "Maybe it's loading a different map with an old script somehow." and copy-pasted the map in the levels folder over to a separate folder. Loaded up KeeperFX and sure enough, the map isn't there anymore. It is 100% looking at that map script, reading that code and thinking "Yes, 6000 game turns have passed in this .5 of a second, I drop dwarves now."

I had a small eureka moment when I saw Tunnellers were referred to as DwarfB in AdiKted (red dwarves being DwarfA) but it was a dead end. This was before I figured out the script was just ignoring everything and dumping the dwarves immediately anyway.

- - - - -


I didn't knew the tunnellers are digging in that case. What is their destination?
The player heart.

Bear with me for a bit though. I think if I dump a few enemy keeper creatures into that spot via action point or preplace and cause the tunnelers to stop digging and fight, maybe they'll cease their digging commands. It works sometimes with imps in regular play.
I need to fix the other problems before I can test this though.

YourMaster
September 10th, 2014, 17:11
Could you share your entire script to have a look at?

Woudo
September 10th, 2014, 17:17
Have a bash, bugger me if I can tell what's wrong.

1516

mefistotelis
September 10th, 2014, 17:38
Have a bash, bugger me if I can tell what's wrong.

To check basics of level script, load the level in KeeperFX, then exit the game and check the log file (keeperfx.log).
If there are any script commands syntax errors, the game will issue an error. And even if syntax is fine, the parser can trace some basic logic inconsistencies and issue a warning.

In this case, you seem to use IF command syntax incorrectly - it always need a player as parameter, even if the variable is player-independent.

YourMaster
September 10th, 2014, 17:51
I have it working. You can always check the log for errors, and see what's wrong. You had several issues:

* Set generate speed was wrong
* DARK_MISTRESS name wrong
* You did not have an If statement around the party trigger.
* You lacked the 'Player' in the if statement you had.

This should work:


LEVEL_VERSION(1)

SET_GENERATE_SPEED(500)

COMPUTER_PLAYER(PLAYER1,0)
COMPUTER_PLAYER(PLAYER2,0)
COMPUTER_PLAYER(PLAYER3,0)

START_MONEY(PLAYER0,25000)
START_MONEY(PLAYER1,12500)
START_MONEY(PLAYER2,12500)
START_MONEY(PLAYER3,12500)

REM ###########################################
REM ###########################################

MAX_CREATURES(ALL_PLAYERS,20)

ADD_CREATURE_TO_POOL(FLY,10)
ADD_CREATURE_TO_POOL(BUG,10)
ADD_CREATURE_TO_POOL(SPIDER,10)
ADD_CREATURE_TO_POOL(SORCEROR,10)
ADD_CREATURE_TO_POOL(TROLL,10)
ADD_CREATURE_TO_POOL(DEMONSPAWN,10)
ADD_CREATURE_TO_POOL(DRAGON,10)
ADD_CREATURE_TO_POOL(BILE_DEMON,10)
ADD_CREATURE_TO_POOL(ORC,10)
ADD_CREATURE_TO_POOL(TENTACLE,10)
ADD_CREATURE_TO_POOL(DARK_MISTRESS,10)
ADD_CREATURE_TO_POOL(HELL_HOUND,10)

CREATURE_AVAILABLE(ALL_PLAYERS,FLY,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,BUG,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,SPIDER,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,TROLL,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,SORCEROR,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,BILE_DEMON,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,DARK_MISTRESS,1,2)
CREATURE_AVAILABLE(ALL_PLAYERS,ORC,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,TENTACLE,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,DRAGON,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,DEMONSPAWN,1,6)
CREATURE_AVAILABLE(ALL_PLAYERS,HELL_HOUND,1,6)

REM ###########################################
REM ###########################################
REM ##### COMPUTERS BANNED FROM BUILDING ROOMS, LESS DIGGING THEY DO THE BETTER #####

REM ##### STANDARD #####
ROOM_AVAILABLE(PLAYER0,TREASURE,1,1)
ROOM_AVAILABLE(PLAYER0,LAIR,1,1)
ROOM_AVAILABLE(PLAYER0,GARDEN,1,1)
ROOM_AVAILABLE(PLAYER0,TRAINING,1,1)
ROOM_AVAILABLE(PLAYER0,RESEARCH,1,1)
ROOM_AVAILABLE(PLAYER0,WORKSHOP,1,0)
ROOM_AVAILABLE(PLAYER0,PRISON,1,0)
ROOM_AVAILABLE(PLAYER0,BARRACKS,1,0)
ROOM_AVAILABLE(PLAYER0,TEMPLE,1,0)
ROOM_AVAILABLE(PLAYER0,TORTURE,1,0)
ROOM_AVAILABLE(PLAYER0,GRAVEYARD,1,0)

REM ##### RESEARCH VALUE ALTERED #####
ROOM_AVAILABLE(PLAYER1,BRIDGE,1,0)
ROOM_AVAILABLE(PLAYER1,BRIDGE,1,0)
ROOM_AVAILABLE(PLAYER1,BRIDGE,1,0)

RESEARCH(PLAYER1,ROOM,BRIDGE,20000)
RESEARCH(PLAYER2,ROOM,BRIDGE,20000)
RESEARCH(PLAYER3,ROOM,BRIDGE,20000)

REM ##### BANNED #####
ROOM_AVAILABLE(PLAYER0,GUARD_POST,0,0)
ROOM_AVAILABLE(PLAYER0,SCAVENGER,0,0)

REM ###########################################
REM ###########################################

DOOR_AVAILABLE(ALL_PLAYERS,BRACED,1,0)
DOOR_AVAILABLE(ALL_PLAYERS,STEEL,1,0)
DOOR_AVAILABLE(ALL_PLAYERS,MAGIC,1,0)

TRAP_AVAILABLE(ALL_PLAYERS,POISON_GAS,1,0)
TRAP_AVAILABLE(ALL_PLAYERS,LIGHTNING,1,0)
TRAP_AVAILABLE(ALL_PLAYERS,WORD_OF_POWER,1,0)
TRAP_AVAILABLE(ALL_PLAYERS,BOULDER,1,0)

REM ###########################################
REM ###########################################

MAGIC_AVAILABLE(ALL_PLAYERS,POWER_IMP,1,1)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_SPEED,1,0)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_OBEY,1,1)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CALL_TO_ARMS,1,0 )
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CONCEAL,1,0)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_PROTECT,1,0)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_HEAL_CREATURE,1, 0)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_LIGHTNING,1,0)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CAVE_IN,1,0)
MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CHICKEN,1,0)

REM ###########################################
REM ###########################################

REM ##### SETUP REQUIRED FOR ONE-TIME HERO HARASS AT TREASURY #####

CREATE_PARTY(WHAT_HAPPENED)
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,5,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,5,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,7,0,STEAL_GOLD,0 )
ADD_TO_PARTY(WHAT_HAPPENED,DWARFA,10,0,STEAL_GOLD, 0)

IF(PLAYER0,GAME_TURN > 200)
IF(PLAYER_GOOD,TUNNELLER == 0)
SET_TIMER(PLAYER_GOOD,TIMER0)
ENDIF
ENDIF

IF(PLAYER0,GAME_TURN > 6000)
ADD_PARTY_TO_LEVEL(PLAYER_GOOD,WHAT_HAPPENED,-1,2)
ENDIF

REM ###########################################
REM ###########################################

SET_COMPUTER_PROCESS(PLAYER1,"DIG TO CLOSE GOLD",0,0,76666,2,10)
SET_COMPUTER_PROCESS(PLAYER2,"DIG TO CLOSE GOLD",0,0,76666,2,10)
SET_COMPUTER_PROCESS(PLAYER3,"DIG TO CLOSE GOLD",0,0,76666,2,10)

REM ###########################################
REM ###########################################

IF(PLAYER0,ALL_DUNGEONS_DESTROYED == 1)
WIN_GAME
ENDIF

Woudo
September 10th, 2014, 18:05
That was just a result of my butchering it and then rushing old "good" code back in before packing it into the .rar. You can tell from my first post with the original code what I had to begin with. I know how to end IF statements, i'm not dumb I swear boss.
The other stuff I would have picked up on in later testing stages of the map. Creatures not spawning at all would have been a clear one.

I know for certain that code was one of the combinations I tried. At one point I figured it was a problem with recognizing KeeperFX specific script so I switched away from IF_CONTROLS to IF(PLAYER_GOOD,TUNNELLER == 0) but got no change from it. I probably forgot an ENDIF or something.

Either way, thank you guys for the help, I can get on to finishing it proper now. I wanted the player to come across a small "mining operation" but if I can't get the tunnelers to stop digging things, i'll kick them out and replace them with generic dwarves or something.
- - -
It feels bad hitting a snag i'm not able to fix myself.

YourMaster
September 10th, 2014, 19:41
I'm sure you had some if statements at some point:p. But probably kept having at least one mistake at a time by trying multiple fixes at once.
In what application are you writing your script? See my last topic, if you use notepad you could download the script-plugin I shared, so you can notice some script-typo's easier.

And what you could do, is add the tunneler only when the player comes across the party, but have the other creatures already present. This way it looks like you run into a tunneler party.
You could also try is to set the speed of the tunneler dwarf to something really slow.

Woudo
September 12th, 2014, 19:19
Is it possible to list a creature in a Resurrect Special without the player actually owning it and losing it? I'm mulling over the idea for a possession-style campaign where you choose your fighter from a list in a resurrect special. I could just have them spawn on top of a boulder, but maybe there's a cleaner way.

Also, how do you go about using the PLAY_MESSAGE command. Where would I need to dump the .wav file?

YourMaster
September 12th, 2014, 19:23
Instead of the boulder you could use the KILL_CREATURE command to kill the creatures straight away.

Woudo
October 4th, 2014, 13:10
Guys, I stopped working on my maps a while back because I got stuck on some code and the site was down.
Trying to get back into it but I honestly can't remember what I was doing.



RANDOM

It's not a command, but may be used instead of most parameters. If used instead of a number, then should look like:

RANDOM(min,max)

but may also be used instead of any other value. Examples:

REM Human player will have random creature limit between 12 and 19
MAX_CREATURES(PLAYER0,RANDOM(12,19))
REM Random creature will be added to pool
ADD_CREATURE_TO_POOL(RANDOM,20)

Note that when used instead of player name, RANDOM may return ALL_PLAYERS. Also, the command shouldn't be used in multiplayer maps, as it will lead to synchronization problems. Value represented by RANDOM is selected at start of a map, and never changes during the gameplay.


Alright so i'm trying to do a hero campaign and I wanted to take things a step further by removing imps for tunnelers and removing portals in favour of "reinforcements" from a Hero gate.
Turns out tunnelers are completely worthless as workers so i've thrown that half of the idea in the bin. Now the "ADD_CREATURE_TO_POOL(RANDOM,20)" of the above implies the RANDOM function works on creatures and not just numbers. I cooked up this;



REM SETUP PLAYER CREATURE SPAWNING

IF(PLAYER0,TOTAL_CREATURES >= 1)
SET_TIMER(PLAYER0,TIMER1)
ENDIF

IF(PLAYER0,TOTAL_CREATURES < 25)
IF(PLAYER0,TIMER1 >= 50)
NEXT_COMMAND_REUSABLE
ADD_CREATURE_TO_LEVEL(PLAYER0,RANDOM,-4,1,1,0)
NEXT_COMMAND_REUSABLE
SET_TIMER(PLAYER0,TIMER1)
ENDIF
ENDIF


But it just flat out doesn't work. Either i've scripted it incorrectly or it's not even possible and i'm wasting my time. The Hero Gates being random spawns are hugely important to get a good emulation of how portals regularly work.

Bear in mind the player starts with a :knight:.

YourMaster
October 4th, 2014, 16:51
Does the log give an error message?

Edit: I checked for myself, and indeed it does:

Error: script_scan_line(line 40): Not enough parameters for "ADD_CREATURE_TO_LEVEL"

Funnily enough, when I replace Random with Random(min,max) the command is accepted, but instead mentions that the number returned is not a creature, so no help there.

In any case, even if it would work, this script would not have the effect you want: Random is determined at the start of the game, and stays the same. So, it would pick a random creature and give you that creature every 2.5 seconds (when you have the timer on 50).

I think the game script needs a true random command, also for example for action points. So for example you can continuously spawn a party from a random action point.

Woudo
October 4th, 2014, 18:43
Well that sucks. So any ideas or will I have to stick with portals?

You should take a look at Tunnelers and their digging, they'll dig out one tile and then just stop. Not sure if it's worth putting up on the issues board or not.

YourMaster
October 4th, 2014, 21:32
Well, if you want it to work like normal dungeon keeper, portals are the way to go. I don't see a working alternative to simulate it using the script, as it really isn't a powerful script at all. On top of that you are very limited by the 48 if statements. If you look at the good campaign included, that's the way Lquiz went about it, using imps and portals. This was before KeeperFX even, you have the possibility to expand on that by including your own creature folder with attraction conditions for the heroes.

If I were to design a heroes campaign, I would stay away from the standard dungeon keeper conventions, and look at it more like a hero invasion of dark keepers. So don't mine gold, but conquer treasuries. And don't attract heroes in a trickle at random through a portal, but by conquering hero doors have certain heroes (a group of low level heroes of a single type) drop in all at once to join you. Perhaps have a loop that states if you have too few of that creature type, get reinforcements of that type. This works different, but still very well I think.

So something like this:

IF_ACTION_POINT(1,PLAYER0)
QUICK_INFORMATION(1,"Well done. With this hero door liberated, these barbarians will join you")
ADD_CREATURE_TO_LEVEL(PLAYER0,BARBARIAN,-1,5,1,0)
SET_TIMER(PLAYER0,TIMER1)
ENDIF

REM Every minute add a barbarian until the player is back up to 4 out of 5 barbarians.
IF(PLAYER0,TIMER1 >= 1200)
IF(PLAYER0, BARBARIAN <= 3)
NEXT_COMMAND_REUSABLE
ADD_CREATURE_TO_LEVEL(PLAYER0,BARBARIAN,-1,1,1,0)
ENDIF
NEXT_COMMAND_REUSABLE
SET_TIMER(PLAYER0,TIMER1)
ENDIF

IF_AVAILABLE(PLAYER_GOOD,SORCEROR <= 0)
QUICK_INFORMATION(1,"Good, with the Warlocks defeated, we can get the help of our wizards and sorceresses.")
ADD_CREATURE_TO_LEVEL(PLAYER0,WIZARD,-2,2,1,0)
ADD_CREATURE_TO_LEVEL(PLAYER0,WITCH,-2,2,1,0)
SET_TIMER(PLAYER0,TIMER2)
ENDIF

REM Every three minutes add a Wizard and Witch until the player has 2 wizards and 3 witches.
IF(PLAYER0,TIMER2 >= 3600)
IF(PLAYER0, WIZARD <= 2)
NEXT_COMMAND_REUSABLE
ADD_CREATURE_TO_LEVEL(PLAYER0,WIZARD,-2,1,1,0)
ENDIF
IF(PLAYER0, WITCH <= 3)
NEXT_COMMAND_REUSABLE
ADD_CREATURE_TO_LEVEL(PLAYER0,WITCH,-2,1,1,0)
ENDIF
NEXT_COMMAND_REUSABLE
SET_TIMER(PLAYER0,TIMER2)
ENDIF

If you run out of if statements, you can be a more efficient by using flags.

I've tried a level with the tunneler, and indeed it is more useless then it used to be. It keeps going idle. You can report this.