Euflorium: The Eufloria Community
Eufloria => Eufloria Classic => Eufloria Classic Mods => Topic started by: Aino on February 07, 2011, 04:44:56 AM
-
(Changed layout of this topic, dunno why though :D)
Current Code:
Engine download below, NOTE IT'S ALPHA 0.1 VERSION and only the basics is in the code!
And second note: The pririties aren't fully done and it may lag, you will know where to change though(if you don't it is cairuns!)!
Current problem:
My AI can't attack properly and the priority levels are some bugged, but playable :)
Requests:
Try download and find bugs for me!!!
.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
Past Problems:
There is no error message poppin' up anymore, which seems good, but I get a problem... The priority ain't changing...
Fixed, YEY!
attempt to index field '?' (a nil value)
at line 189. FIXED!
Another problem is:
invalid arguments to method call
at line 123. FIXED!
Another problem, not that big, but gets big over time:
Why are the roids recognized as "having treespace remaining" while it doesn't?
Picture info:
200 Means it is supposed to be scouted, but only if the neighbours have a higher priority(number).
100 Means need trees, now why won't this code work?
GetAsteroid(asteroids):AvailableStructureSpace()
and yes, I know it is a boolean :) FIXED and it works for people that will use this :)
DOWNLOAD:
Recomended number of roids is under or 50 roids!!!!!
-
It's because you haven't initialised the values for your array slots. Line 189 checks a bunch of things against different array slots. The error means it tried to do the compare operation, but one of the values was a number and the other was "nil".
for i = 0,numberofasteroids do
array[i] = 0
end
That would be sufficient, presuming that array is meant to hold numbers.
-
Need help witht he second problem, it tries to call something from the function argument, but there is nothing in it(I belive this is what happens!).
-
It's because you haven't initialised the values for your array slots. Line 189 checks a bunch of things against different array slots. The error means it tried to do the compare operation, but one of the values was a number and the other was "nil".
for i = 0,numberofasteroids do
array[i] = 0
end
That would be sufficient, presuming that array is meant to hold numbers.
I have allready done that:
for i = 0,numberofasteroids do
cairoidpriority[i] = 1500
GetAsteroid(i):Reveal(1)
end
but I made an if check, so it only runs if the roids have something :)
Note: The reveal is for testing purposes, if you wonder :P
-
Please help, the error is somewhere around here:
i = math.random(0,numberofasteroids)
for asteroids = 0,numberofasteroids do
if i ~= asteroids then
length = GetAsteroid(asteroids).position.x - GetAsteroid(i).position.x
height = GetAsteroid(asteroids).position.y - GetAsteroid(i).position.y
distancetoroid = math.sqrt((length * length) + (height * height))
distancetoroid = distancetoroid - GetAsteroid(asteroids).Radius
if distancetoroid < GetAsteroid(i).SendDistance then
numberofneighbours = numberofneighbours + 1
neighbours[numberofneighbours] = GetAsteroid(asteroids)
if neighbours[asteroids] ~= nil then
if neighbours[asteroids].owner ~= caiid and GetAsteroid(asteroids):IsVisible(caiid) == true and GetAsteroid(asteroids):GetNumSeedlingsExcluding(caiid)*2 < GetAsteroid(i):GetNumSeedlings(caiid) and GetAsteroid(asteroids):GetNumSeedlingsExcluding(caiid) > 0 then
GetAsteroid(i):SendSeedlingsToTarget(caiid, GetAsteroid(asteroids):GetNumSeedlings(caiid), GetAsteroid(asteroids))
end
--is there any lower priorities here?
if cairoidpriority[asteroids] > cairoidpriority[i] and GetAsteroid(i).owner == caiid then
--nope, but is there any enemies nearby?
if GetAsteroid(asteroids).owner ~= caiid and GetAsteroid(asteroids).owner ~= 0 then
--yes, enemies nearby and no help to give around, lets make ourself a gatheringpoint!
cairoidpriority[i] = 700
end
end
if cairoidpriority[asteroids] < cairoidpriority[i] then
if GetAsteroid(i).owner == caiid or GetAsteroid(i).owner == 0 then
if needed[asteriods] == (-1) then
needed[asteroids] = GetAsteroid(i):GetNumSeedlings(caiid) - cailearned
end
GetAsteroid(i):SendSeedlingsToTarget(caiid, needed[asteroids], GetAsteroid(asteroids))
cairoidsent[i] = needed[asteroid]
cairoidpriority[i] = cairoidpriority[asteroids] + 1
end
end
end
end
end
end
Hope you may try to help, cause I want this AI to be published :D
-
Ok, fixed it... Now I feel so stupid cause it was this single little line:
GetAsteroid(asteroid).Name = cairoidpriority[i]
at line 222 -.-
-
How is this coming along now? :>
-
Going fine, cept that priority problem I have D:
-
Getting the priority system (or metric, as I called it) right was definitely one of the hardest things about building my AI.
What I did is set each asteroid name to the priority number, that way I could click on each asteroid in-game to see what its metric number was. That allowed me to identify problems with the propogation of the numbers across a given metric network. It's actually surprisingly hard to produce a series of rules that will always self-correct...
-
Well, it isn't so hard... only make the priority(metric) and if the neighbour has a higher, then the neighbour will have the same as the roid + 1 :P
like this:
selected roid's roidpriority = some number
if neighbour's roidpriority > selected roid's roidpriority then
neighbour's roidpriority = selected roid's roidpriority + 1
end
(in quote because it's not a code...)
But this may be hard, since you did it first and I wouldn't be able to do this without your help with the neighbour stuff, didn't know you would need square root :P
EDIT: Though, I am getting problems... Maybe you can help me tell if the code I am having problems with work?(Cause it won't it seems like)
-
What I think will be cool, is that the AI will try configure itself by the way you attack/defend yourself, you can also fool it though xD
-
Problems are inevitable with this sort of system. Just work through them I guess. If there's anything you're really stuck on then post up and I'll try to help.
The problem arises thusly; suppose you set a metric of 0 whenever an asteroid detects that it is under attack. The immediate neighbour of that asteroid might then set itself to metric 1, to indicate that seedlings should proceed to the asteroid with metric 0.
Now imagine that hte asteroid with metric 0 is no longer under siege; all the attackers have been destroyed. What now?
Maybe you reset that asteroid's metric to 1500. That asteroid will then glance at its neighbour, see the metric of 1, and change its own metric to 2.
The neighbour will then see the metric of 2, and set its own metric of 3...
And so on. This would just spiral upwards, and result in seedlings flying around apparently at random.
This is the sort of problem that you really need to solve conceptually first, before you can program the desired behaviour. Diagrams are key for this. If you think you know exactly how it would work, draw it out on a diagram. Write down the rules that will determine the metric numbers. Make up some imaginary scenarios and figure out if the rules you are using for your metric system will provide correct behaviour. For this type of project, 30 minutes spent on conceptual diagrams is worth 10 hours of coding, in my experience.
-
Mhm, ye :P Gonna remake the system so it will take care of that :)
-
By the way, the square root in there is a result of using Pythagoras to calculate how far away one asteroid is from another asteroid.
Pythagoras is that thing you've forgotten you learned in school, that allows you to find the "hypotenuse" of a right-angled triangle assuming you know the lengths of the opposite and adjacent sides.
The formula is:
a^2 = b^2 + c^2
But we need a, not a^2. So we take the square root of both sides:
a = math.sqrt(b^2 + c^2)
"a" is the distance between the centers of the 2 asteroids (ie, the hypotenuse)
"b" is the horizontal difference (the adjacent)
"c" is the vertical difference (the opposite)
To find b, subtract the X-coordinate of one asteroid from the other.
To find c, subtract the Y-coordinate of one asteroid from the other.
Finally, we can check if Asteroid 1 is in range of Asteroid 2 by checking if "c" plus the radius of Asteroid 1, is less than the send distance of Asteroid 2.
-
O.o
I haven't learnt it yet you see, 9th grade xD
But, it's nice learning it before you do at school, cause then you know what the teacher is talking about before you are done with it :D
Neither did I know of "hypotenuse" o.O
-
Oh, right. Well, when you come to do it in school, they probably won't give you many practical examples of what it is used for.
Or if they do, they'll be totally boring and relatively pointless, like "Jim has two pieces of wood as shown. How much string will Jim need to tie one end of the wood to the other?"
That was my experience, anyway.
In fact, pythagoras is about the most useful equation you could possibly know for coding. It's used for absolutely loads of stuff - usually where you need to calculate the distance between two objects. It features prominently in the AI engine, the gravity engine, and the 3D starfield engine. The position of stars in the latter is actually calculated using just 4 lots of pythagoras calculations. :>
For a quick run over pythagoras, see here: http://www.bbc.co.uk/schools/ks3bitesize/maths/shape_space/pythagoras_theorem/revise1.shtml
Let me know if that link doesn't make sense.. :>
-
Also, if you learn about it now then when they try to teach you about it in school you can tell them all about it, and how you've already written your own artificial intelligence engine that uses those calculations. :> I should imagine your maths teacher will be all like o.O
:>
-
Wow, I learnt something, but I need to check the site once again if i need to know once more :P
But one thing is confusing the first time you look at page 2:
In b in the question in page 2:
The smalest side with 5cm is higer than both 13 and 12 cm it looks like, which cause confusion unless you study it closely.
-
Yeah it's not very clear that, is it? But yea, if it helps, just draw your own triangle that IS to scale.. :>
By the way, page 5 has an example that is _exactly_ the sort of thing you might need to do in Eufloria. You can imagine that those 2 points on the graph are actually asteroids...
-
Hah, the math teacher will(and the whiole class too) be like "He said WHOOT?!" :D
-
I would rather do that than looking at a confusing picture again xD
-
What am I doing, I am combining two parts in my engine into one and hoping it works properly :D
-
New problem -.- Please help :)
-
One little thing...
Math.sqrt() is fairly processor-heavy. However, you do not have to square-root the hypotenuse (longest side) to compare distances, because if length A is greater than length B, A^2 will always be bigger than B^2.
EDIT: Also, if you do get it to learn from mistakes, and the IO library is solved, you could have your AI store its knowledge elsewhere, and learn more and more every match it plays. Though I think that may be a little hard.
-
Mhm, I know square root is a heavy task... May say that to annikk too, cause his AI uses it too :P
EDIT: My computer runs 58(I think) roids fine with three runs per while loop :D
And I think the AI should be reset everytime you play, because then you can play diferently against "the same AI" adn I jsut gotta get over the barriers of problems before I start with the learning for real...
My plan:
1st: Finish seed movement and tree planting
2nd: Allow flowers to be used
3rd: IF gatheringpoints are bugged(which they would be I guess) fix them.(mainly called include, but they are there already :P)
4th: AI learning :D
-
stuff
And I think the AI should be reset everytime you play, because then you can play diferently against "the same AI"
more stuff
That's my point. If you were to make what it learns usable in other matches, it would force you to play a different style eventually, because it would know how you play, and play to beat that. If it was reset every time you started a level, you could play the same strategy every time, and it wouldn't know any better.
-
Mhm, maybe I'll add it, IF POSSIBLE and I know how...
In the meantime I have a god damn problem about the game crashing right after a tree reaches the core, but only by the AI...
-
Yeah, if possible is the main problem there...
-
Ye, else we just gotta live with the same AI reseting, untill it is posiible(if it will ever be :))
-
YES!!!
I'm so happy, cause now I can begin with other stuff, but first: how does my AI fight against the normal AI?
-
I can't after all, cause of this little code:
if GetAsteroid(asteroids).owner == caiid then
GetAsteroid(asteroids):SetGraceTime(99999)
elseif GetAsteroid(asteroids).owner ~= caiid and GetAsteroid(asteroids).owner ~= 1 then
GetAsteroid(asteroids):SetGraceTime(0)
end
Which should work, but my AI is breaking the rules(planting flowers and sending seedling to places it shouldn't!) which indicates the normal AI is still somewhere in it's heart controlling it's brain like a virus(kinda wierd explanation, but that seems to be it...).
-
Just stick Globals.AI.GraceTimer=(9999999) at the top of your LevelSetup. That should turn it completely off for all Empires.
If you want the default AI on for some empires (in the example below, it turns the default AI on for empires 2 and 3), then put this code in your LevelSetup
function LevelSetup()
-- roids and stuff created here
for i = 0, math.huge do
if GetAsteroid(i) == nil then
highroidID = i - 1
break
end
end
for i = 0,highroidID do
if GetAsteroid(i).owner == 2 or GetAsteroid(i).owner == 3 then
GetAsteroid(i):SetGraceTime(0)
else
GetAsteroid(i):SetGraceTime(9999999)
end
end
And this OUTSIDE of any other function. Just after LevelLogic is a good place, but I don't think it would have an effect whereever you put it.
OnAsteroidTaken(id, owner)
if GetAsteroid(id).owner == 2 or GetAsteroid(i).owner == 3 then
GetAsteroid(i):SetGraceTime(0)
else
GetAsteroid(i):SetGraceTime(99999)
end
end
Basically, that's a mashup of a few snippets I've learnt from Annikk and also a few I built myself. The LevelSetup block checks a potentially infinite list of asteroids, and as soon as it hits the end of the list, saves the highest ID of the asteroids. Then, it goes through the new, shorter list of asteroids and sets the GraceTimer to 0 (turns the default AI on) for that asteroid's owner - otherwise, it turns it off.
The second bit is called every time an asteroid is captured, and does the same thing as the second FOR loop in LevelSetup.
I think it works, but I haven't tested it.
-
The AI works as expected, but the priority levels get incredibly high... I don't think it will damage the gameplay though :)
-
Pilchard: I want all to be in one function, which it allready is, but sadly the code isn't working properly "GetAsteroid(roidnumber):SetGraceTime(float)" to be excact :P
-
Got a picture form a little gameplay with(or against) my AI, ofcourse I didn't do much as I got amazed by my AI's behaviour :D
WARNING: The next picture is not predicting the future(not?)...
-
lol :>
Awesome dude! Great job on this :>
It's so satisfying when you finally get something like this working. It really is a great feeling. :>
-
You know that AI ended up taking all the 50 roids (cept for mine, cause it can't attack properly yet...) and it ended up having 1300 seedlings flying around in a circle xD
-
Ehhm... I have a question:
What is wrong with this code?
*CODES FTW*
elseif GetAsteroid(asteroids):AvailableStructureSpace() == true and attacked[asteroids] == false then
if GetAsteroid(asteroids).owner == caiid or GetAsteroid(asteroids).owner == 0 then
attacked[asteroids] = false
needtrees[asteroids] = true
needscouting[asteroids] = false
gatheringpoint[asteroids] = false
end
elseif *MORE CODE*
D:
-
elseif GetAsteroid(asteroids):AvailableStructureSpace() == true and attacked[asteroids] == false then
Here is how I would recommend phrasing that:
elseif GetAsteroid(asteroids):GetNumTrees() < GetAsteroid(asteroids).TreeCap and attacked[asteroids] == false then
-
fixed it :P
It will just rule any map now, but it lags with many roids D:
-
Dowload now possible!
-
Tho it’s too late now … I’d recomment creating a new thread rather than perusing the first post of an existing thread for such … seeing that you also changed the text of the opening post.
Why? Because it disrupts the thread and may make (then good) replies to your initial text look silly, but certainly somewhat un-understandable. Also it may be harder for all interested pppl to find things … also discussion of your new code is harder for ppl starting to read this thread later.
Or do I err — and coders don’t care about such things? ;-)
Peace, Tom
(no coder ((yet) (but (as you can see,) (in my previous life) I have learnt some (very little) LISP (, among other languages)))) (You knew that LISP does NOT mean “Lots of Irritating Single Parentheses?) (OK, no new lines & indents, just for some fun)
-
You're right, changed it back now :P
-
cool, thx
-
God, still having a problem with correcting the priorities x.x
Like this it should be:
303 -> 302 -> 301 -> 300 <- 301 etc...
But it acts more like this(1000 means idle, and it should set toa number right after :P):
300 <- 301 <- 1000 <- 1000 -> 201 -> 200
WHY?!
-
Rewriting the AI for the 4th time, hope I will be done with that soon :)