AI Bug

User avatar
Kyran
Posts: 499
Joined: Sat Dec 31, 2011 5:19 pm
Location: Australia
Contact:

AI Bug

Post by Kyran »

My AI isn't building lumber mills. Is this happening for anyone else?
04:27 jim4 why haven't you added wc1 support? this project sucks. i'm only going to use freecraft
05:06 jim4 finished wc1 support yet? i've been waiting for 6 years
05:10 jim4 new things scare me
User avatar
b_o
Posts: 328
Joined: Sun Jan 01, 2012 12:07 pm

Re: AI Bug

Post by b_o »

yeah.. I think mine hasn't been building them either.
User avatar
Andrettin
Posts: 433
Joined: Sun Jun 30, 2013 9:58 pm
Location: Vienna, Austria
Contact:

Re: AI Bug

Post by Andrettin »

From what I see of the Wargus AI, it is supposed to build a lumber mill after building the stables/ogre mound - but in my test it didn't build a lumber mill even then (although it could still upgrade towers into guard towers). It seems to me that the AI isn't very responsive to the commands given to it under the default format, and that using Kyran's AI format works better.

I have been trying my hand at rewriting the AI under Kyran's format, and this is what I have so far:

Code: Select all

function AiLandAttack()
	if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiCityCenter()) < 1) then
		AiSet(AiCityCenter(), 1)
	end
	if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiFarm()) < 1) then
		AiSet(AiFarm(), 1)
	end
	if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiWorker()) < 5) then
		AiSet(AiWorker(), 5)
	end
	if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) < 1) then
		AiSet(AiBarracks(), 1)
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) == 1) then
		if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiFarm()) >= 2) then
			if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiWorker()) >= 5) then
				if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) >= 4) then
					AiForce(0, {AiSoldier(), 1})
					AiForce(1, {AiSoldier(), 3})
					AiAttackWithForce(1)
					AiSet(AiBarracks(), 2)
				else
					AiSet(AiSoldier(), 4)
				end
			else
				AiSet(AiWorker(), 5)
			end
		else
			AiSet(AiFarm(), 2)
		end
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) >= 2) then
		if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiFarm()) >= 7) then
			if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiWorker()) >= 10) then
				if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) >= 16) then
					AiForce(0, {AiSoldier(), 4})
					AiForce(1, {AiSoldier(), 12})
					AiAttackWithForce(1)
				else
					AiSet(AiSoldier(), 16)
				end
			else
				AiSet(AiWorker(), 10)
			end
		else
			AiSet(AiFarm(), 7)
		end
	end
end

DefineAi("land-attack", "*", "land-attack", AiLandAttack)
It is a simple AI capable of building a town hall, barracks and farms, as well as grunts/footmen, and it attacks with them, too.
User avatar
Kyran
Posts: 499
Joined: Sat Dec 31, 2011 5:19 pm
Location: Australia
Contact:

Re: AI Bug

Post by Kyran »

There is something preventing all the AIs from building a lumber mill. I've been trying to improve my Nephrite AI, but it is rather annoying that I can't test it properly.

Code: Select all

--       _________ __                 __
--      /   _____//  |_____________ _/  |______     ____  __ __  ______
--      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
--      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ \ 
--     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
--             \/                  \/          \//_____/            \/ 
--  ______________________                           ______________________
--                        T H E   W A R   B E G I N S
--         Stratagus - A free fantasy real time strategy game engine
--
--	ai_nephrite_2013.lua - Nephrite AI 2013
--
--	(c) Copyright 2012-2013 by Kyran Jackson
--
--      This program is free software; you can redistribute it and/or modify
--      it under the terms of the GNU General Public License as published by
--      the Free Software Foundation; either version 2 of the License, or
--      (at your option) any later version.
--  
--      This program is distributed in the hope that it will be useful,
--      but WITHOUT ANY WARRANTY; without even the implied warranty of
--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--      GNU General Public License for more details.
--  
--      You should have received a copy of the GNU General Public License
--      along with this program; if not, write to the Free Software
--      Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
--

-- This edition was started on 11/11/2013.

local nephrite_build -- What the AI is going to build.
local nephrite_attackbuffer -- The AI attacks when it has this many units.
local nephrite_attackforce
local nephrite_wait -- How long the AI waits for the next attack.
local nephrite_increment -- How large the attack force is increased by.

function AiNephrite_2013()
	if (nephrite_attackforce ~= nil) then
		-- Basic start build. After this is done we'll move onto the adaptive part.
		AiNephrite_Train_2013()
		AiNephrite_Pick_2013()
		if (nephrite_wait < 2) then
			AiNephrite_Attack_2013()
		else
			nephrite_wait = nephrite_wait - 1
		end
		AiNephrite_Research_2013()
		AiNephrite_Expand_2013()
	else
		nephrite_build = "Soldier"
		nephrite_attackbuffer = 5
		nephrite_wait = 0
		nephrite_attackforce = 1
		nephrite_modifier_cav = 1
		nephrite_modifier_archer = 1
    end
end

function AiNephrite_Pick_2013()
	-- What am I going to build next?
	nephrite_build = SyncRand(6)
	if (nephrite_build >= 3) then
		nephrite_build = "Footman"
	elseif (nephrite_build == 2) then
		if (nephrite_modifier_cav == 0) then
			nephrite_build = "Footman"
		else
			nephrite_build = "Knight"
		end
	elseif (nephrite_build == 1) then
		if (nephrite_modifier_archer == 0) then
			nephrite_build = "Footman"
		else
			nephrite_build = "Archer"
		end
	end
	if ((((GetPlayerData(AiPlayer(), "UnitTypesCount", AiShooter()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry())) > ((GetPlayerData(AiPlayer(), "UnitTypesCount", AiWorker())) * 2)) and (GetPlayerData(AiPlayer(), "UnitTypesCount", AiCityCenter()) > 0)) or (GetPlayerData(AiPlayer(), "UnitTypesCount", AiWorker()) < 7)) then
		nephrite_build = "Worker"
	end
end

function AiNephrite_Attack_2013()
	AddMessage("It is time to attack.")
	--AddMessage(nephrite_attackforce)
	--AddMessage(GetPlayerData(AiPlayer(), "UnitTypesCount", AiShooter()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry()))
	if ((GetPlayerData(AiPlayer(), "UnitTypesCount", AiShooter()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry())) >= nephrite_attackbuffer) then
		AddMessage("Attacking with force 1.")
		AiForce(nephrite_attackforce, {AiSoldier(), GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()), AiCavalry(), GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry()), AiShooter(), GetPlayerData(AiPlayer(), "UnitTypesCount", AiShooter())})
		AiAttackWithForce(nephrite_attackforce)
		nephrite_wait = 20
		if (nephrite_attackforce >= 7) then
			nephrite_attackforce = 1
			nephrite_attackbuffer = nephrite_attackbuffer + nephrite_increment
			AiForce(1, {})
			AiForce(2, {})
			AiForce(3, {})
			AiForce(4, {})
			AiForce(5, {})
			AiForce(6, {})
			AiForce(7, {})
			AiForce(8, {})
			AiForce(9, {})
		else
			nephrite_attackforce = nephrite_attackforce + 1
		end
	end
end

function AiNephrite_Expand_2013()
	-- New in Nephrite 2013 is the expand function.
	if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) == 0) then
		if (GetPlayerData(AiPlayer(), "Resources", "gold") > 1000) then
			AiSet(AiBarracks(), 1)
		end
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) == 1) then
		if (GetPlayerData(AiPlayer(), "Resources", "gold") > 2000) then
			AiSet(AiBarracks(), 2)
		end
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) == 2) then
		if (GetPlayerData(AiPlayer(), "Resources", "gold") > 4000) then
			AiSet(AiBarracks(), 3)
		end
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) == 3) then
		if (GetPlayerData(AiPlayer(), "Resources", "gold") > 8000) then
			AiSet(AiBarracks(), 4)
		end
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) == 4) then
		if (GetPlayerData(AiPlayer(), "Resources", "gold") > 16000) then
			AiSet(AiBarracks(), 5)
		end
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) == 5) then
		if (GetPlayerData(AiPlayer(), "Resources", "gold") > 32000) then
			AiSet(AiBarracks(), 6)
		end
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) > 5) then
		if (((GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) / GetPlayerData(AiPlayer(), "TotalResources", "gold")) > 1200) and (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) < 8)) then
			AiSet(AiBarracks(), (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) + 1))
		end
	end
	if (GetPlayerData(AiPlayer(), "Resources", "gold") < 4000) then
		if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiCityCenter()) == 0) then
			AiSet(AiCityCenter(), 1)
		end
	elseif (GetPlayerData(AiPlayer(), "Resources", "gold") < 8000) then
		if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiCityCenter()) < 2) then
			AiSet(AiCityCenter(), 2)
		end
	end
	if (GetPlayerData(AiPlayer(), "Resources", "gold") > 1000) then
		if ((GetPlayerData(AiPlayer(), "TotalNumUnits") / GetPlayerData(AiPlayer(), "UnitTypesCount", AiFarm())) > 4) then
			AiSet(AiFarm(), (GetPlayerData(AiPlayer(), "UnitTypesCount", AiFarm()) + 1))
		end
	end
end
	
function AiNephrite_Research_2013()
	-- New in Nephrite 2013 is the research function.
	-- TODO: Add captapult
	if ((GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry())) >= (nephrite_attackbuffer/3)) then
		if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBlacksmith()) == 0) then
			AiSet(AiBlacksmith(), 1)
		else
			if ((GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry())) >= (nephrite_attackbuffer/3)) then
				AiResearch(AiUpgradeWeapon1())
				AiResearch(AiUpgradeArmor1())
				if ((GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry())) >= (nephrite_attackbuffer/2)) then
					AiResearch(AiUpgradeArmor2())
					AiResearch(AiUpgradeWeapon2())
				end
			end
			if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiShooter()) >= (nephrite_attackbuffer/3)) then
				if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiLumberMill()) == 0) then
					AiSet(AiLumberMill(), 1)
				else
					AiResearch(AiUpgradeMissile1())
					AiResearch(AiUpgradeMissile2())
					if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiStables()) == 0) then
						AiSet(AiStables(), 1)
					else
						if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBestCityCenter()) == 0) then
							AiUpgradeTo(AiBestCityCenter())
						else
							AiResearch(AiUpgradeEliteShooter())
							AiResearch(AiUpgradeEliteShooter2())
							AiResearch(AiUpgradeEliteShooter3())
						end
					end	
				end
			end
		end
	end
end

function AiNephrite_Train_2013()
	if (nephrite_build == "Worker") then
		AiSet(AiWorker(), GetPlayerData(AiPlayer(), "UnitTypesCount", AiWorker()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiCityCenter()))
	elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()) > 0) then
		if (nephrite_build == "Footman") then
			AiSet(AiSoldier(), GetPlayerData(AiPlayer(), "UnitTypesCount", AiSoldier()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()))
		elseif (nephrite_build == "Catapult") then
			if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBlacksmith()) > 0) then
				--FIXME: Following line crashes the game.
				--AiSet(AiCatapult(), GetPlayerData(AiCatapult(), "UnitTypesCount", AiCatapult()) + 1)
			else
				AiSet(AiBlacksmith(), 1)
			end
		elseif (nephrite_build == "Archer") then
			AiSet(AiShooter(), GetPlayerData(AiPlayer(), "UnitTypesCount", AiShooter()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()))
		elseif (nephrite_build == "Knight") then
			if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiStables()) > 0) then
				AiSet(AiCavalry(), GetPlayerData(AiPlayer(), "UnitTypesCount", AiCavalry()) + GetPlayerData(AiPlayer(), "UnitTypesCount", AiBarracks()))
			else
				if ((GetPlayerData(AiPlayer(), "UnitTypesCount", AiBetterCityCenter()) > 0) or (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBestCityCenter()) > 0)) then
					AiSet(AiStables(), 1)
				elseif (GetPlayerData(AiPlayer(), "UnitTypesCount", AiCityCenter()) > 0) then
					if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiLumberMill()) > 0) then
						if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBlacksmith()) > 0) then
							AiUpgradeTo(AiBetterCityCenter())
						else
							AiSet(AiBlacksmith(), 1)
						end
					else
						AiSet(AiLumberMill(), 1)
					end
				else
					AiSet(AiCityCenter(), 1)
				end
			end
		end
	else
		AiSet(AiBarracks(), 1)
	end
end

function AiNephrite_NoCav_2013()
	if (nephrite_attackforce ~= nil) then
		AiNephrite_2013()
		if (nephrite_attackbuffer > 20) then
			nephrite_attackbuffer = 15
		end
	else
		nephrite_attackforce = 1
		nephrite_build = "Soldier"
		nephrite_attackbuffer = 12
		nephrite_wait = 500
		nephrite_modifier_cav = 0
		nephrite_modifier_archer = 1
		nephrite_increment = 0.1
	end
end

function AiNephrite_Level5()
	if (nephrite_attackforce ~= nil) then
		if (GetPlayerData(2, "Resources", "gold") > 1000) then
			AiNephrite_Train_2013()
			AiNephrite_Pick_2013()
			if (nephrite_wait < 2) then
				AiNephrite_Attack_2013()
			else
				nephrite_wait = nephrite_wait - 1
			end
			AiNephrite_Research_2013()
			if (GetPlayerData(AiPlayer(), "UnitTypesCount", AiBlacksmith()) > 0) then
				AiNephrite_Expand_2013()
			end
		end
	else
		nephrite_attackforce = 1
		nephrite_build = "Archer"
		nephrite_attackbuffer = 6
		nephrite_wait = 100
		nephrite_modifier_cav = 0
		nephrite_modifier_archer = 1
		nephrite_increment = 0.1
	end
end

DefineAi("ai_nephrite_2013", "*", "ai_nephrite_2013", AiNephrite_2013)
DefineAi("ai_nephrite_nocav_2013", "*", "ai_nephrite_nocav_2013", AiNephrite_NoCav_2013)
Last edited by Kyran on Mon Nov 18, 2013 3:42 pm, edited 2 times in total.
04:27 jim4 why haven't you added wc1 support? this project sucks. i'm only going to use freecraft
05:06 jim4 finished wc1 support yet? i've been waiting for 6 years
05:10 jim4 new things scare me
User avatar
Andrettin
Posts: 433
Joined: Sun Jun 30, 2013 9:58 pm
Location: Vienna, Austria
Contact:

Re: AI Bug

Post by Andrettin »

I found this in the Stratagus launchpad page:

https://bugs.launchpad.net/stratagus/+bug/1093794

So it seems that in version 2.2.8 this bug won't happen anymore :)
User avatar
Kyran
Posts: 499
Joined: Sat Dec 31, 2011 5:19 pm
Location: Australia
Contact:

Re: AI Bug

Post by Kyran »

Yes, 2.2.7 has been out for so long, I keep forgetting about the bugs that were reported years ago. I should probably start testing against the trunk version. Dinky, give us an updated binary. :)

Here is my AI roadmap, just for fun:

Jadeite - A group of functions focused on strategy, and picking the most appropriate strategy. The Jadeite AI will be able to react to what is happening in a broad sense.

Nephrite - A group of functions focused on what to do at a particular second. The Nephrite AI excels at short term, but doesn't implement a broad strategy.

Zoisite - A demonstration of how to build an AI using the Jadeite and Nephrite functions. This AI will implement a broad strategy, but will be able to put it on hold for short term emergencies.
04:27 jim4 why haven't you added wc1 support? this project sucks. i'm only going to use freecraft
05:06 jim4 finished wc1 support yet? i've been waiting for 6 years
05:10 jim4 new things scare me
User avatar
cybermind
Posts: 110
Joined: Sat Dec 31, 2011 11:43 pm

Re: AI Bug

Post by cybermind »

Kyran wrote:math.random(5)
Use SyncRand(num) instead. This function may desync your game in multiplayer or while watching replay.
User avatar
Kyran
Posts: 499
Joined: Sat Dec 31, 2011 5:19 pm
Location: Australia
Contact:

Re: AI Bug

Post by Kyran »

cybermind wrote:Use SyncRand(num) instead. This function may desync your game in multiplayer or while watching replay.
Ah, that's the one! Jarod told me to do that years ago, but I forgot the command.
04:27 jim4 why haven't you added wc1 support? this project sucks. i'm only going to use freecraft
05:06 jim4 finished wc1 support yet? i've been waiting for 6 years
05:10 jim4 new things scare me
User avatar
Kyran
Posts: 499
Joined: Sat Dec 31, 2011 5:19 pm
Location: Australia
Contact:

Re: AI Bug

Post by Kyran »

Can anyone remind me what the lua function is to return the resources of a player? Was it GetResources(player, id)?

Damn it, I'm going to go setup that wiki now.
04:27 jim4 why haven't you added wc1 support? this project sucks. i'm only going to use freecraft
05:06 jim4 finished wc1 support yet? i've been waiting for 6 years
05:10 jim4 new things scare me
User avatar
Andrettin
Posts: 433
Joined: Sun Jun 30, 2013 9:58 pm
Location: Vienna, Austria
Contact:

Re: AI Bug

Post by Andrettin »

It is (replacing "player_id" with the player's id and "resource_name" with the resource):
GetPlayerData(player_id, "TotalResources", resource_name)
Post Reply