BAB - Blitz AI Battle

Übersicht Sonstiges Smalltalk

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

aMul

Sieger des Minimalist Compo 01/13

Betreff: BAB - Blitz AI Battle

BeitragDo, Jan 07, 2010 23:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Da Weihnachtsferien sind/waren bin ich anfang der Woche spontan zu kriD gefahren. Und wie das so ist, wenn zwei Genies länger als fünf Minuten im gleichen Raum sind, enstehen bei sowas gerne mal kleine Spielereien.
Und so präsentieren wir euch nun das...

user posted image

Beim BAB handelt es sich um ein Framework, geschrieben in BB, über welches man selbst geschriebene KIs in einer Arena gegeneinander antreten lassen kann.

Aber seht selbst(am besten in HD).

Im Video seht ihr einige Dummy-KIs, die von einer besseren 'Hunter'-KI auseinandergepflückt werden. Mr. Green


Die Regeln des BAB sind denkbar einfach. Gewonnen hat die KI deren Schiff am längsten überlebt/als letztes übrig bleibt.
Hierbei startet jedes Schiff mit 100 Lebenspunkten, verliert davon 10, wenn es getroffen wird und bekommt 20 dazu, wenn es ein anderes Schiff zerstört(heirbei kann es auch passieren, dass ein Schiff mehr als 100 LP hat).

Gesteuert werden die Schiffe mit nur drei Variablen, eine zum Beschleunigen, eine zum Drehen und eine zum Schießen, doch dazu später mehr.


Hier also der Code des Frameworks:
BlitzBasic: [AUSKLAPPEN]
Const SCRW = 1024
Const SCRH = 768

Const FPS = 100

Const ARENA_SIZE = 350

Const ENERGY_MAX = 200
Const ENERGY_REGEN = 1
Const ENERGY_COST = 30

Const SHIP_DRAWSIZE = 10
Const SHIP_COLLISIONSIZE = 8

Const SHIP_INERTIA# = 0.99
Const SHIP_ROTATION_INERTIA# = 0.99

Const SHIP_ACCELERATION# = 0.02
Const SHIP_ROTATION_ACCELERATION# = 0.02

Const SHIP_HP_MAX = 100
Const SHIP_HP_REWARD = 20

Const SHOT_DAMAGE = 10
Const SHOT_SPEED = 10
Const SHOOT_DELAY = 10


Const FORMATION_CIRCLE_OUTWARD = 1

Const PLAYERLISTITEM_HEIGHT = 40

;! ---------------------------------------------------------------------------------------------------------
;! ADD A COSNTANT FOR YOUR AI HERE
;! ---------------------------------------------------------------------------------------------------------

Const AI_KEYBOARD = 1
Const AI_CHEAP = 2

;! --------------------------------------------------------------------------------------------


SeedRnd MilliSecs()

Graphics SCRW, SCRH, 0, 2

Global Frame, Background, Skull, PlayerCount

InitImages()


Local timer, count

timer = CreateTimer(FPS)


SetBuffer BackBuffer()

Repeat

ResetAll()

;! ---------------------------------------------------------------------------------------------------------
;! CREATE YOUR AIs HERE WITH NewPlayer()
;! ---------------------------------------------------------------------------------------------------------

NewPlayer(AI_KEYBOARD, "EGO") ;! control with arrow-keys, shoot with space

CreateCheapaIs(10) ;! dummy-AIs for testing


;! --------------------------------------------------------

ShufflePlayer()
PositionPlayers(FORMATION_CIRCLE_OUTWARD, 100)


Repeat
UpdateAll()

If PlayerCount > 1 And KeyHit(28)
count = PlayerCount
Repeat
UpdateAll()
Until PlayerCount < count Or KeyHit(28)
EndIf

If (Frame Mod 2) = 0
DrawAll()

Flip 0
Cls
EndIf

If KeyHit(1)
End
End If
WaitTimer timer
Until KeyHit(60)

Forever

;! ---------------------------------------------------------------------------------------------------------
;! ADD YOUR OWN AIs IN THIS SECTION
;! ---------------------------------------------------------------------------------------------------------


;! AI_KEYBOARD --------------------------------------------------------------------------------------------

Function AIKeyboard_Update(p.TPlayer)
p\accelerating = KeyDown(200)
p\turning = KeyDown(205) - KeyDown(203)
p\shooting = KeyDown(57)
End Function

;! AI_CHEAP -------------------------------------------------------------------------------------------

Function AICheap_Update(p.TPlayer)
Local direction, fireOffset
direction = PeekInt(p\ai_bank, 0)
If direction = 0
direction = Rand(0, 1) * 2 - 1
PokeInt(p\ai_bank, 0, direction)
fireOffset = Rand(0, 360)
PokeInt(p\ai_bank, 4, fireOffset)
Else
fireOffset = PeekInt(p\ai_bank, 4)
EndIf
p\accelerating = 1
p\turning = Rand(-50, 100) * direction
p\shooting = Sin(Frame + fireOffset) > - 0.15
End Function


;! ---------------------------------------------------------------------------------------------------------
;! ADD A 'Case' FOR YOUR AI HERE AND CALL YOUR AIs FUNCTION
;! ---------------------------------------------------------------------------------------------------------

Function UpdateAI()
Local p.TPlayer, time
For p = Each TPlayer
time = MilliSecs()
Select p\ai_id
Case AI_KEYBOARD
AIKeyboard_Update(p)
Case AI_CHEAP
AICheap_Update(p)
End Select
p\ai_time = p\ai_time + MilliSecs() - time
Next
End Function


;! --------------------------------------------------------------------------------------------

Type TPlayer
Field listItem.TPlayerListItem
Field ai_id
Field name$
Field rgb
Field hp
Field energy
Field last_shot
Field p_x#
Field p_y#
Field p_a#
Field v_x#
Field v_y#
Field v_a#
Field turning
Field accelerating
Field shooting
Field ai_time
Field ai_bank
End Type

Type TShot
Field player.TPlayer
Field rgb
Field p_x#
Field p_y#
Field v_x#
Field v_y#
End Type

Type TExplosion
Field p_x
Field p_y
Field size#
Field size_max
Field speed#
Field rgb
Field startFrame
End Type

Type TPlayerListItem
Field player.TPlayer
Field target_y
Field y#
End Type

Type TDeathListItem
Field name$
Field rgb
Field deathFrame
Field ai_time
Field target_y
Field y#
End Type

;! --------------------------------------------------------------------------------------------

Function UpdateAll()
Frame = Frame + 1
UpdateAI()
UpdatePlayer()
UpdateShots()
UpdatePlayerList()
End Function

Function DrawAll()
DrawArena()
DrawPlayer()
DrawShots()
Draw_Explosion()
DrawPlayerList()
DrawHud()
End Function


Function ResetAll()
Delete Each TDeathListItem
Delete Each TExplosion
Delete Each TPlayer
Delete Each TPlayerListItem
Delete Each TShot
Frame = 0
PlayerCount = 0
End Function

Function ShufflePlayer()
Local p.TPlayer, i
For i = 1 To PlayerCount
p = GetRandomPlayer(i)
Insert p Before First TPlayer
Next
End Function

Function GetRandomPlayer.TPlayer(min = -1, max = -1)
Local p.TPlayer, i, n
If min = -1
min = 1
End If
If max = -1
max = PlayerCount
End If
n = Rand(min, max)
p = First TPlayer
For i = 2 To n
p = After p
Next
Return p
End Function

Function CreateCheapaIs(count = 6)
Local i
For i = 1 To count
NewPlayer(AI_CHEAP, "Dummy " + i, $FF00FF)
Next
End Function

Function UpdatePlayerList()
Local pli.TPlayerListItem, dli.TDeathListItem, i
For pli = Each TPlayerListItem
i = i + 1
pli\target_y = i * PLAYERLISTITEM_HEIGHT
If pli\target_y <> pli\y
pli\y = pli\y + (pli\target_y - pli\y) / 20.0
End If
Next
For dli = Each TDeathListItem
i = i + 1
dli\target_y = i * PLAYERLISTITEM_HEIGHT
If dli\target_y <> dli\y
dli\y = dli\y + (dli\target_y - dli\y) / 20.0
End If
Next
End Function

Function SortPlayerListItemDown(pli.TPlayerListItem)
Local pli2.TPlayerListItem
pli2 = After pli
While pli2 <> Null
If pli\player\hp < pli2\player\hp
Insert pli After pli2
Else
Exit
End If
pli2 = After pli
Wend
End Function

Function SortPlayerListItemUp(pli.TPlayerListItem)
Local pli2.TPlayerListItem
pli2 = Before pli
While pli2 <> Null
If pli\player\hp > pli2\player\hp
Insert pli Before pli2
Else
Exit
End If
pli2 = Before pli
Wend
End Function

Function CreateDeathListItem.TDeathListItem(p.TPlayer)
Local dli.TDeathListItem
dli = New TDeathListItem
dli\deathFrame = Frame
dli\ai_time = p\ai_time
dli\name = p\name
dli\rgb = p\rgb
dli\y = p\listItem\y
Insert dli Before First TDeathListItem
Return dli
End Function

Function NewPlayer.TPlayer(ai = AI_KEYBOARD, name$ = "Dummy", rgb = $FFFFFF, x = SCRW / 2, y = SCRH / 2, a = 0)
Local p.TPlayer, pli.TPlayerListItem
p = New TPlayer
p\ai_id = ai
p\name = name
p\rgb = rgb
p\p_x = x
p\p_y = y
p\p_a = a
p\energy = ENERGY_MAX
p\hp = SHIP_HP_MAX
p\ai_bank = CreateBank(32)
PlayerCount = PlayerCount + 1
pli = New TPlayerListItem
pli\player = p
p\listItem = pli
Return p
End Function

Function UpdatePlayer()
Local p.TPlayer, a#, a2#, v#
For p = Each TPlayer
p\p_x = p\p_x + p\v_x
p\p_y = p\p_y + p\v_y
p\p_a = p\p_a + p\v_a

p\v_x = p\v_x * SHIP_INERTIA
p\v_y = p\v_y * SHIP_INERTIA
p\v_a = p\v_a * SHIP_ROTATION_INERTIA

If (SCRW / 2 - p\p_x) * (SCRW / 2 - p\p_x) + (SCRH / 2 - p\p_y) * (SCRH / 2 - p\p_y) > ARENA_SIZE * ARENA_SIZE
a = ATan2((SCRH / 2 - p\p_y), (SCRW / 2 - p\p_x)) + 180
a2 = ATan2(p\v_y, p\v_x) + 180
v = Sqr(p\v_x * p\v_x + p\v_y * p\v_y)
p\p_x = SCRW / 2 + Cos(a) * ARENA_SIZE
p\p_y = SCRH / 2 + Sin(a) * ARENA_SIZE
a = 2 * a - a2
p\v_x = Cos(a) * v
p\v_y = Sin(a) * v
End If

p\energy = p\energy + ENERGY_REGEN

If p\energy > ENERGY_MAX
p\energy = ENERGY_MAX
End If

If p\accelerating <> 0
p\v_x = p\v_x + Cos(p\p_a) * SHIP_ACCELERATION
p\v_y = p\v_y + Sin(p\p_a) * SHIP_ACCELERATION
End If

If p\turning <> 0
p\v_a = p\v_a + Sgn(p\turning) * SHIP_ROTATION_ACCELERATION
End If

If Frame > 300
If p\shooting <> 0
If p\last_shot + SHOOT_DELAY < Frame
If p\energy > ENERGY_COST
PlayerShoot(p)
EndIf
End If
End If
EndIf
Next
End Function

Function PlayerShoot.TShot(p.TPlayer)
Local s.TShot
s = New TShot
s\rgb = p\rgb
s\p_x = p\p_x
s\p_y = p\p_y
s\v_x = Cos(p\p_a) * SHOT_SPEED
s\v_y = Sin(p\p_a) * SHOT_SPEED
s\player = p
p\energy = p\energy - ENERGY_COST
p\last_shot = Frame
Return s
End Function

Function PlayerDie(p.TPlayer)
Local i
For i = 1 To 5
NewExplosion(p\p_x + Rand(-10, 10) + Rand(-10, 10), p\p_y + Rand(-10, 10) + Rand(-10, 10), Rand(40, 80), Rand(3, 5), p\rgb)
Next
PlayerCount = PlayerCount - 1
CreateDeathListItem(p)
Delete p\listItem
Delete p
End Function

Function PositionPlayers(formation = FORMATION_CIRCLE_OUTWARD, radius = 50)
Local p.TPlayer, i, a
Select formation
Case FORMATION_CIRCLE_OUTWARD
For p = Each TPlayer
a = i * 360 / PlayerCount
p\p_x = SCRW / 2 + Cos(a) * radius
p\p_y = SCRH / 2 + Sin(a) * radius
p\p_a = a
i = i + 1
Next
End Select
End Function

Function UpdateShots()
Local s.TShot, p.TPlayer, a#
For s = Each TShot
s\p_x = s\p_x + s\v_x
s\p_y = s\p_y + s\v_y
If (SCRW / 2 - s\p_x) * (SCRW / 2 - s\p_x) + (SCRH / 2 - s\p_y) * (SCRH / 2 - s\p_y) > ARENA_SIZE * ARENA_SIZE
a = ATan2((SCRH / 2 - s\p_y), (SCRW / 2 - s\p_x)) + 180
NewExplosion(SCRW / 2 + Cos(a) * ARENA_SIZE, SCRH / 2 + Sin(a) * ARENA_SIZE, 30, 2, $3C3C3C)
Delete s
Else
For p = Each TPlayer
If s\player <> p
If (p\p_x - s\p_x) * (p\p_x - s\p_x) + (p\p_y - s\p_y) * (p\p_y - s\p_y) < SHIP_COLLISIONSIZE * SHIP_COLLISIONSIZE
p\hp = p\hp - SHOT_DAMAGE
If p\hp <= 0
If s\player <> Null
s\player\hp = s\player\hp + SHIP_HP_REWARD
SortPlayerListItemUp(s\player\listItem)
End If
PlayerDie(p)
Else
NewExplosion(s\p_x, s\p_y, 30, 2, s\rgb)
SortPlayerListItemDown(p\listItem)
EndIf
Delete s
Exit
EndIf
EndIf
Next
EndIf
Next
End Function

Function DrawPlayerList()
Local pli.TPlayerListItem, dli.TDeathListItem, x1, x2, x3, y1, y2, y3
For pli = Each TPlayerListItem
Color 100, 100, 100
Rect -1, pli\y - 3, 120, PLAYERLISTITEM_HEIGHT - 4, 0

If pli\player\hp > SHIP_HP_MAX
Color 241, 165, 0
Rect 15, pli\y, 100, 15
Else
If pli\player\hp < SHIP_HP_MAX
Color 45, 45, 45
Rect 15, pli\y, 100, 15
EndIf
Color 150 - pli\player\hp * 150 / SHIP_HP_MAX, pli\player\hp * 150 / SHIP_HP_MAX, 0
Rect 15, pli\y, 100 * pli\player\hp / SHIP_HP_MAX, 15
End If

Color 255, 255, 255
Text 15, pli\y, pli\player\name, 0, 0

Color 100, 100, 100
Text 0, pli\y + 16, "ai-time: ~" + pli\player\ai_time * 1000 / Frame + "us", 0, 0

Color 0, 0, pli\player\rgb
x1 = 7 + Cos(pli\player\p_a) * 5
y1 = pli\y + 7 + Sin(pli\player\p_a) * 5

x2 = 7 + Cos(pli\player\p_a + 140) * 5
y2 = pli\y + 7 + Sin(pli\player\p_a + 140) * 5

x3 = 7 + Cos(pli\player\p_a - 140) * 5
y3 = pli\y + 7 + Sin(pli\player\p_a - 140) * 5

Line x1, y1, x2, y2
Line x1, y1, x3, y3
Line x2, y2, x3, y3

Next
For dli = Each TDeathListItem
Color 100, 100, 100
Rect -1, dli\y - 3, 120, PLAYERLISTITEM_HEIGHT - 4, 0
DrawImage Skull, 2, dli\y + 1
Text 15, dli\y, dli\name + " +" + dli\deathFrame / FPS + "s", 0, 0
Text 0, dli\y + 16, "ai-time: ~" + dli\ai_time * 1000 / dli\deathFrame + "us", 0, 0
Next
End Function

Function DrawPlayer()
Local p.TPlayer, x1, x2, x3, y1, y2, y3
For p = Each TPlayer
Color 0, 0, p\rgb
x1 = p\p_x + Cos(p\p_a) * SHIP_DRAWSIZE
y1 = p\p_y + Sin(p\p_a) * SHIP_DRAWSIZE

x2 = p\p_x + Cos(p\p_a + 140) * SHIP_DRAWSIZE
y2 = p\p_y + Sin(p\p_a + 140) * SHIP_DRAWSIZE

x3 = p\p_x + Cos(p\p_a - 140) * SHIP_DRAWSIZE
y3 = p\p_y + Sin(p\p_a - 140) * SHIP_DRAWSIZE

Line x1, y1, x2, y2
Line x1, y1, x3, y3
Line x2, y2, x3, y3

Color 45, 45, 45
Rect p\p_x - 25, p\p_y - 10, 50, 4

If p\hp > SHIP_HP_MAX
Color 241, 165, 0
Rect p\p_x - 25, p\p_y - 10, 50, 2
Else
Color 255 - p\hp * 255 / SHIP_HP_MAX, p\hp * 255 / SHIP_HP_MAX, 0
Rect p\p_x - 25, p\p_y - 10, 50 * p\hp / SHIP_HP_MAX, 2
End If



Color 0, 0, 255
Rect p\p_x - 25, p\p_y - 8, 50 * p\energy / ENERGY_MAX, 2

Color 150, 150, 150
Text p\p_x, p\p_y - 25, p\name, 1
Next
End Function

Function DrawShots()
Local s.TShot
For s = Each TShot
Color 0, 0, s\rgb
Rect s\p_x - 1, s\p_y - 1, 3, 3
Next
End Function

Function NewExplosion.TExplosion(p_x = 0, p_y = 0, size_max = 100, speed# = 1, rgb)
Local e.TExplosion = New TExplosion
e\p_x = p_x
e\p_y = p_y
e\size_max = size_max
e\speed = speed
e\rgb = rgb
e\startFrame = Frame
Return e
End Function

Function Draw_Explosion()
Local e.TExplosion, size
For e = Each TExplosion
Color 0 , 0, e\rgb
Oval e\p_x - e\size / 2, e\p_y - e\size / 2, e\size, e\size, 0
e\size = (Frame - e\startFrame) * e\speed

If e\size >= e\size_max Then
Delete e
EndIf
Next
End Function

Function DrawArena()
DrawImage Background, 0, 0
End Function

Function DrawHud()
Local p.TPlayer, dli.TDeathListItem
Color 255, 255, 255
If Frame < 450
If Frame < 300
If Frame < 200
If Frame < 100
Text SCRW / 2, SCRH / 2, "- 3 -", 1, 1
Else
Text SCRW / 2, SCRH / 2, "- 2 -", 1, 1
EndIf
Else
Text SCRW / 2, SCRH / 2, "- 1 -", 1, 1
EndIf
Else
Text SCRW / 2, SCRH / 2, "FIGHT!", 1, 1
EndIf
EndIf
If PlayerCount = 1
p = First TPlayer
Text SCRW / 2, SCRH / 2, "LAST SHIP FLYING: " + p\name, 1, 1
ElseIf PlayerCount = 0
dli = First TDeathListItem
If dli <> Null
Text SCRW / 2, SCRH / 2, "LAST SHIP TO DIE: " + dli\name, 1, 1
End If
End If
End Function

Function InitImages()
Background = CreateImage(SCRW, SCRH)
SetBuffer ImageBuffer(Background)
Color 30, 30, 30
Rect 0, 0, SCRW, SCRH
Color 0, 0, 0
Oval SCRW / 2 - ARENA_SIZE, SCRH / 2 - ARENA_SIZE, ARENA_SIZE * 2, ARENA_SIZE * 2
Color 60, 60, 60
Oval SCRW / 2 - ARENA_SIZE, SCRH / 2 - ARENA_SIZE, ARENA_SIZE * 2, ARENA_SIZE * 2, 0

Skull = CreateImage(13, 12)
SetBuffer ImageBuffer(Skull)
Color 100, 100, 100
Rect 0, 1, 13, 10
Rect 1, 0, 11, 12

Color 0, 0, 0
Rect 2, 0, 9, 2
Rect 0, 2, 2, 7
Rect 11, 2, 2, 7
Rect 2, 10, 2, 2
Rect 9, 10, 2, 2
Rect 4, 5, 2, 2
Rect 7, 5, 2, 2
Rect 2, 7, 1, 2
Rect 10, 7, 1, 2

WritePixel 0, 9, 0
WritePixel 12, 9, 0
WritePixel 3, 9, 0
WritePixel 9, 9, 0

WritePixel 2, 3, 0
WritePixel 3, 2, 0
WritePixel 10, 3, 0
WritePixel 9, 2, 0
End Function

Um eine eigene KI zu schreiben seht ihr euch am besten zurerst die Beispiel-KIs an. Die entsprechenden Funktionen findet ihr direkt nach der Hauptschleife.
Zusätzlich zu einer solchen Update-Funktion braucht jede KI noch eine Konstante, definiert am Code-Beginn und einen Case-Eintrag in der Funktion 'UpdateAI()', durch den die entsprechende Funktion aufgerufen wird. Diese Stellen sind ebenso wie der Teil der Hauptschleife in welchem ihr Schiffe mit euren KIs erstellen müsst durch Kommentare gekennzeichnet.
Wir hoffen, dass dieses System nicht zu kompliziert ist, aber durch den Mangel an Funktionspointern in BB geht es leider nicht wirklich einfacher.

Wie bereits erwähnt werden die Schiffe über drei Variablen gesteuert. Dies kann man in der Beispiel-"KI" 'AI_KEYBOARD', die sich mit der Tastatur steuern lässt sehr schön sehen.
Der Vollständigkeit halber eine kurze Dokumentation:
Code: [AUSKLAPPEN]
p\accelerating
= 0 -> Schiff beschleunigt nicht
<> 0 -> Schiff beschleunigt(mit voller Stärke)

p\turning
= 0 -> Schiff dreht sich nicht
> 0 -> Schiff dreht sich im Uhrzeigersinn(mit voller Stärke)
< 0 -> Schiff dreht sich gegen den Uhrzeigersinn(wieder mit voller Stärke)

p\shooting
= 0 -> Schiff schießt nicht
<> 0 -> Schiff schießt(vorausgesetzt Energie ist vorhanden)


Dies sind im Prinzip die einzigen drei Variablen die in der Update-Funktion einer KI verändert werden sollten.
Weiterhin ist noch eine Bank('p\ki_bank') für das Speichern von beliebigen Daten vorgesehen. Zum Beispiel könnte man hier das Handle eines Schiffes hinterlegen, auf das es die KI gerade abgesehen hat, oder auch ihre Lieblings-Eissorte, sollte das relevant sein.


Da es immer spannender ist sich mit anderen zu messen(auch wenn diesmal keiner selber spielen kann) organisieren wir einen offiziellen Wettbewerb.

Um teilzunehmen müsst ihr mir nur die Update-Funktion eurer KI (und eure Lieblingsfarbe) per PN schicken.
Sobald einige KIs eingegangen sind startet die erste(von hoffentlich zahlreichen) Runde, in welcher diese in mehreren Durchläufen gegeneinandere antreten werden. Hiervon werden wir natürlich ein Video, ähnlich dem bereits gezeigten, veröffentlichen.
Natürlich steht es jedem frei, seine KI auch einfach hier zu posten, aber wir denken dass es mehr Spaß macht, das Verhalten der gegnerischen KIs nur mit Hilfe der Videos zu analysieren.
Außerdem entwickeln sich so sicherlich vielseitigere KIs, da man sich nicht direkt vom Code der anderen "inspirieren" lassen kann. Wink

Damit das ganze nicht im Chaos endet gibt es ein paar Regeln, die jeder Teilnehmer beachten muss:

  1. Abgegeben wird nur eine einzelne Funktion, zusätzliche F. oder gar neue Types/globale Variablen sind nicht erlaubt
  2. Die Funktion muss als einzigen Parameter den zu behandelnden TPlayer anehmen
  3. Lokale Variablen dürfen in der Funktion nach belieben erstellt und verwendet werden
  4. Für das längerfristige Speichern von Daten steht die bereits genannte Bank 'p\ki_bank' mit 32 byte zur Verfügung
  5. Die Funktion darf alle globalen Variablen und Types auslesen(jedoch nicht verändern)
  6. Um "Mobbing" zu verhindern dürfen Name, ai_id und die Bank anderer KIs nicht verwendet werden
  7. Funktionen die sehr viel Rechenzeit in Anspruch nehmen scheiden aus Performance-Gründen aus
  8. Wie bereits oben angedeutet wurde sind die drei Steuerungs-Variablen neben der Bank die einzigen, die von der Funktion verändert werden dürfen


kriD und ich werden natürlich als Veranstalter nicht am Wettbewerb teilnehmen.

(Wenn die Regeln oder der Code Fragen aufwerten stehen wir natürlich zur Verfügung.)



Wir hoffen auf rege Teilnahme.

Happy Coding!

kriD & aMul


EDIT

Auf Anfrage hier eine Beispielfunktion, in der noch einmal aufgeführt wird, auf was die KI alles zugreifen darf:
BlitzBasic: [AUSKLAPPEN]
Function AIExample_Update(p.TPlayer)
Local p2.TPlayer, s.TShot
; ausgelesen werden dürfen:
; Alle Globalen und Konstanten, insbesodere:
; Frame -> Aktueller Zeitindex
; SHIP_*, ENERGY_*, etc. durch die die Spielregeln definiert sind.
; zusätzlich dürfen alle Felder des eigenen Schiffes (p\*) ausgelesen werden
For p2 = Each TPlayer
; ausgelesen werden dürfen:
; p2\accelerating -> beschleunigt der andere Spieler?
; p2\energy -> wieviel (Schuss-)Energie hat der andere Spieler?
; p2\hp -> wieviel Lebenspunkte hat der andere?
; p2\last_shot -> in welchem Frame hat der Spieler das letzte mal geschossen?
; p2\p_a -> in welche Richtung ist der Spieler gedreht?
; p2\p_x -> x-Position das Spielers
; p2\p_y -> y-Position des Spielers
; p2\shooting -> schießt der Spieler gerade?
; p2\turning -> will sich der Spieler gerade drehen?
; p2\v_a -> dreht sich der Spieler gerade?
; p2\v_x -> x-Bewegung das Spielers
; p2\v_y -> y-Bewegung das Spielers
Next
For s = Each TShot
; ausgelesen werden dürfen:
; s\player -> welcher Spieler hat diese Geschoss geschossen?
; s\p_x -> x-Position das Geschosses
; s\p_y -> y-Position des Geschosses
; s\v_x -> x-Bewegung des Geschosses
; s\v_y -> y-Bewegung des Geschosses
Next
; Verändert werden dürfen:
; p\accelerating -> diesen Frame beschleunigen? (True/False)
; p\turning -> diesen Frame drehen? (=0: Nein, >0: im Uhrzeigersinn, <0: gegen den Uhrzeigersinn)
; p\shooting -> diesen Frame schießen? (True/False)
; zusätzlich dürfen die 32 Byte der p\ai_bank mit Poke- und Peek-Befehlen beliebig bearbeitet werden
End Function
  • Zuletzt bearbeitet von aMul am Fr, Jan 15, 2010 17:30, insgesamt 4-mal bearbeitet

hectic

Sieger des IS Talentwettbewerb 2006

BeitragDo, Jan 07, 2010 23:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Pack ein paar LockBuffers mit ein, so ist es bei mir grottig langsam.

Edit1: Ich finde die Idee nicht schlecht, dennoch wäre es hilfreich zu wissen welche Funktion man ändern soll und wie man die Positionen der Gegner bzw. deren Geschwindigkeiten einlesen kann. Einfach mal so in den bestehen Code reinhacken kann jeder, ist aber keine Vorgabe.

Also eine Beispielfunktion erstellen die genau die Werte aufzeichnet aber nichts daraus macht. Also keine KI aufweist.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

Smily

BeitragFr, Jan 08, 2010 10:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Ohne mir den Code jetzt angeschaut zu haben.
In Bmax wäre ein KI-Framework sauber lösbar, ohne irgendwelche funktionen ändern zu müssen.
Ich hab mir die Tage auch mal gedanken gemacht, wie man sowas am besten strukturell löst
Man erstellt sich ne abstrakte klasse Tai und daraus werden dann die KIs abgeleitet, die sich jeder selbst entwickeln kann und denen einen namen nach einer bestimmten Konvention gibt. Der aufrufende code sähe dann wohl etwa so aus:

(Natürlich halber pseudocode.. es geht um die struktur)
Code: [AUSKLAPPEN]

  include "game.bmx"
  include "user1_ki.bmx"
  include "user2_ki.bmx"

  field = new TGameField
  player1 = new TPlayer
  player1.setAi(new Tai_user1)
  player2 = new TPlayer
  player2.setAi(new Tai_user2)
  field.addPlayer(player1)
  field.addPlayer(player2)

  renderer = new TFieldRenderer

  repeat
     field.update()

     cls
     renderer.render(field)
     flip
  until keyhit(1) 


die update()-methode aus field ruft nacheinander eine update-methode für jeden player auf, die sozusagen einen schritt ausführen soll.
Die Struktur ist recht vielseitig. so kann man natürlich auch ein "AI-Modul" schreiben, dass auf tastendrücke reagiert, damit hat man dann den menschlichen spieler implementiert. Oder man schreibt was, dass die bewegungsdaten von einem server bekommt, dann hat man die grundlage für ein netzwerkspiel etc. etc.
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org

DaysShadow

BeitragFr, Jan 08, 2010 14:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich war mal so frei, das ganze nach BlitzMax zu portieren, allerdings ist es buggy, ich hab irgendwo einen Fehler den ich nicht finde, zu finden in der Funktion SortPlayerListItemUp(), die entsprechende Stelle ist markiert( Z.410 )

Aber zum anschauen reicht es Razz

BlitzMax: [AUSKLAPPEN]
SuperStrict

Const SCRW:Int = 1024
Const SCRH:Int = 768

Const FPS:Int = 60

Const ARENA_SIZE:Int = 350

Const ENERGY_MAX:Int = 200
Const ENERGY_REGEN:Int = 1
Const ENERGY_COST:Int = 30

Const SHIP_DRAWSIZE:Int = 10
Const SHIP_COLLISIONSIZE:Int = 8

Const SHIP_INERTIA:Float = 0.99
Const SHIP_ROTATION_INERTIA:Float = 0.99

Const SHIP_ACCELERATION:Float = 0.02
Const SHIP_ROTATION_ACCELERATION:Float = 0.02

Const SHIP_HP_MAX:Int = 100
Const SHIP_HP_REWARD:Int = 20

Const SHOT_DAMAGE:Int = 10
Const SHOT_SPEED:Int = 10
Const SHOOT_DELAY:Int = 10


Const FORMATION_CIRCLE_OUTWARD:Int = 1

Const PLAYERLISTITEM_HEIGHT:Int = 40

'! ---------------------------------------------------------------------------------------------------------
'! ADD A COSNTANT For YOUR AI HERE
'! ---------------------------------------------------------------------------------------------------------

Const AI_KEYBOARD:Int = 1
Const AI_CHEAP:Int = 2

'! --------------------------------------------------------------------------------------------


SeedRnd MilliSecs( )
Graphics( SCRW, SCRH, 0, 60 )

Global Frame:Int, Background:TImage, Skull:TImage, PlayerCount:Int

InitImages( )

Local timer:TTimer, count:Int

timer = CreateTimer( FPS )

Repeat

ResetAll( )

'! ---------------------------------------------------------------------------------------------------------
'! Create YOUR AIs HERE WITH NewPlayer( )
'! ---------------------------------------------------------------------------------------------------------

NewPlayer( AI_KEYBOARD, "EGO" ) '! control with arrow-keys, shoot with space

CreateCheapaIs( 10 ) '! dummy-AIs For testing


'! --------------------------------------------------------

ShufflePlayer( )
PositionPlayers( FORMATION_CIRCLE_OUTWARD, 100 )


Repeat

UpdateAll( )

If PlayerCount > 1 And KeyHit( KEY_ENTER )

count = PlayerCount

Repeat
UpdateAll( )
Until PlayerCount < count Or KeyHit( KEY_ENTER )
EndIf

If ( Frame Mod 2 ) = 0
DrawAll( )

Flip 0
Cls
EndIf

If KeyHit( KEY_ESCAPE )
End
End If
WaitTimer timer

Until KeyHit( KEY_F2 )

Forever

'! ---------------------------------------------------------------------------------------------------------
'! ADD YOUR OWN AIs IN THIS SECTION
'! ---------------------------------------------------------------------------------------------------------


'! AI_KEYBOARD --------------------------------------------------------------------------------------------

Function AIKeyboard_Update( p:TPlayer )

p.accelerating = KeyDown( KEY_UP )
p.turning = KeyDown( KEY_RIGHT ) - KeyDown( KEY_LEFT )
p.shooting = KeyDown( KEY_SPACE )

End Function

'! AI_CHEAP -------------------------------------------------------------------------------------------

Function AICheap_Update( p:TPlayer )

Local p2:TPlayer, direction:Int, fireOffset:Int

direction = PeekInt( p.ai_bank, 0 )
If direction = 0
direction = Rand( 0, 1 ) * 2 - 1
PokeInt( p.ai_bank, 0, direction )
fireOffset = Rand( 0, 360 )
PokeInt( p.ai_bank, 4, fireOffset )
Else
fireOffset = PeekInt( p.ai_bank, 4 )
EndIf

p.accelerating = 1
p.turning = Rand( -50, 100 ) * direction
p.shooting = Sin( Frame + fireOffset ) > - 0.15

End Function


'! ---------------------------------------------------------------------------------------------------------
'! ADD A 'Case' FOR YOUR AI HERE AND CALL YOUR AIs FUNCTION
'! ---------------------------------------------------------------------------------------------------------

Function UpdateAI( )

Local p:TPlayer, time:Int

For p = EachIn TPlayer.List

time = MilliSecs( )

Select p.ai_id

Case AI_KEYBOARD

AIKeyboard_Update( p )

Case AI_CHEAP

AICheap_Update( p )

End Select

p.ai_time = p.ai_time + MilliSecs( ) - time

Next

End Function


'! --------------------------------------------------------------------------------------------

Type TPlayer

Global list:TList = CreateList( )

Field listItem:TPlayerListItem
Field ai_id:Int
Field name:String
Field rgb:Int
Field hp:Int
Field energy:Int
Field last_shot:Int
Field p_x:Float
Field p_y:Float
Field p_a:Float
Field v_x:Float
Field v_y:Float
Field v_a:Float
Field turning:Int
Field accelerating:Int
Field shooting:Int
Field ai_time:Int
Field ai_bank:TBank

End Type

Type TShot

Global list:TList = CreateList( )

Field player:TPlayer
Field rgb:Int
Field p_x:Float
Field p_y:Float
Field v_x:Float
Field v_y:Float
End Type

Type TExplosion

Global list:TList = CreateList( )

Field p_x:Int
Field p_y:Int
Field size:Float
Field size_max:Int
Field speed:Float
Field rgb:Int
Field startFrame:Int

End Type

Type TPlayerListItem

Global list:TList = CreateList( )

Field player:TPlayer
Field target_y:Int
Field y:Float

End Type

Type TDeathListItem

Global list:TList = CreateList( )

Field name:String
Field rgb:Int
Field deathFrame:Int
Field ai_time:Int
Field target_y:Int
Field y:Float

End Type

'! --------------------------------------------------------------------------------------------

Function UpdateAll( )

Frame = Frame + 1
UpdateAI( )
UpdatePlayer( )
UpdateShots( )
UpdatePlayerList( )

End Function

Function DrawAll( )

DrawArena( )
DrawPlayer( )
DrawShots( )
Draw_Explosion( )
DrawPlayerList( )
DrawHud( )

End Function


Function ResetAll( )

TDeathListItem.List.Clear( )
TExplosion.List.Clear( )
TPlayer.List.Clear( )
TPlayerListItem.List.Clear( )
TShot.List.Clear( )
Frame = 0
PlayerCount = 0

End Function

Function ShufflePlayer( )

Local p:TPlayer, i:Int

For i = 1 To PlayerCount

p = GetRandomPlayer( i )
'Insert p Before First TPlayer
TPlayer.list.AddFirst( p )

Next

End Function

Function GetRandomPlayer:TPlayer( mini:Int = - 1, maxi:Int = - 1 )

Local p:TPlayer, pLink:TLink, i:Int, n:Int

If mini = - 1

mini = 1

End If

If maxi = - 1

maxi = PlayerCount

End If

n = Rand( mini, maxi )

pLink = TPlayer.list.FirstLink( )

For i = 2 To n

pLink = pLink.NextLink( )

Next

Return TPlayer( pLink.Value( ) )

End Function

Function CreateCheapaIs( count:Int = 6 )

Local i:Int

For i = 1 To count

NewPlayer( AI_CHEAP, "Dummy " + i, $FF00FF )

Next

End Function

Function UpdatePlayerList( )

Local pli:TPlayerListItem, dli:TDeathListItem, i:Int

For pli = EachIn TPlayerListItem.list

i = i + 1

pli.target_y = i * PLAYERLISTITEM_HEIGHT

If pli.target_y <> pli.y

pli.y = pli.y + ( pli.target_y - pli.y ) / 20.0

End If

Next

For dli = EachIn TDeathListItem.list

i = i + 1

dli.target_y = i * PLAYERLISTITEM_HEIGHT

If dli.target_y <> dli.y

dli.y = dli.y + ( dli.target_y - dli.y ) / 20.0

End If

Next

End Function

Function SortPlayerListItemDown( pli:TPlayerListItem )

Local pli2:TPlayerListItem
Local pliLink:TLink, pli2Link:TLink

pliLink = TPlayerListItem.List.FindLink( pli )

pli2Link = pliLink.NextLink( )

While pli2 <> Null

pli2 = TPlayerListItem( pli2Link.Value( ) )

If pli.player.hp < pli2.player.hp

'Insert pli After pli2
TPlayerListItem.List.InsertAfterLink( pli, pli2Link )

Else

Continue

End If

pli2Link = pliLink.NextLink( )

Wend

End Function

Function SortPlayerListItemUp( pli:TPlayerListItem )

Local pli2:TPlayerListItem
Local pliLink:TLink, pli2Link:TLink

pliLink = TPlayerListItem.List.FindLink( pli ) ' Manchmal findet er pli nicht -> Programm schmiert ab, Funktion wird von UpdateShots() aufgerufen

pli2Link = pliLink.PrevLink( )

While pli2 <> Null

pli2 = TPlayerListItem( pli2Link.Value( ) )

If pli.player.hp > pli2.player.hp

'Insert pli Before pli2
TPlayerListItem.List.InsertBeforeLink( pli, pli2Link )

Else

Continue

End If

pli2Link = pliLink.PrevLink( )

Wend

End Function

Function CreateDeathListItem:TDeathListItem( p:TPlayer )

Local dli:TDeathListItem

dli = New TDeathListItem
dli.deathFrame = Frame
dli.ai_time = p.ai_time
dli.name = p.name
dli.rgb = p.rgb
dli.y = p.listItem.y

'Insert dli Before First TDeathListItem
TDeathListItem.List.AddFirst( dli )

Return dli

End Function

Function NewPlayer:TPlayer( ai:Int = AI_KEYBOARD, name:String = "Dummy", rgb:Int = $FFFFFF, x:Int = SCRW / 2, y:Int = SCRH / 2, a:Int = 0 )

Local p:TPlayer, pli:TPlayerListItem

p = New TPlayer
p.ai_id = ai
p.name = name
p.rgb = rgb
p.p_x = x
p.p_y = y
p.p_a = a
p.energy = ENERGY_MAX
p.hp = SHIP_HP_MAX
p.ai_bank = CreateBank( 32 )
PlayerCount = PlayerCount + 1
pli = New TPlayerListItem
pli.player = p
p.listItem = pli

TPlayerListItem.List.AddLast( pli )
TPlayer.List.AddLast( p )

Return p

End Function

Function UpdatePlayer( )

Local p:TPlayer, a:Float, a2:Float, v:Float

For p = EachIn TPlayer.List

p.p_x = p.p_x + p.v_x
p.p_y = p.p_y + p.v_y
p.p_a = p.p_a + p.v_a

p.v_x = p.v_x * SHIP_INERTIA
p.v_y = p.v_y * SHIP_INERTIA
p.v_a = p.v_a * SHIP_ROTATION_INERTIA

If ( SCRW / 2 - p.p_x ) * ( SCRW / 2 - p.p_x ) + ( SCRH / 2 - p.p_y ) * ( SCRH / 2 - p.p_y ) > ARENA_SIZE * ARENA_SIZE

a = ATan2( ( SCRH / 2 - p.p_y ), ( SCRW / 2 - p.p_x ) ) + 180
a2 = ATan2( p.v_y, p.v_x ) + 180
v = Sqr( p.v_x * p.v_x + p.v_y * p.v_y )
p.p_x = SCRW / 2 + Cos( a ) * ARENA_SIZE
p.p_y = SCRH / 2 + Sin( a ) * ARENA_SIZE
a = 2 * a - a2
p.v_x = Cos( a ) * v
p.v_y = Sin( a ) * v

End If

p.energy = p.energy + ENERGY_REGEN

If p.energy > ENERGY_MAX

p.energy = ENERGY_MAX

End If

If p.accelerating <> 0

p.v_x = p.v_x + Cos( p.p_a ) * SHIP_ACCELERATION
p.v_y = p.v_y + Sin( p.p_a ) * SHIP_ACCELERATION

End If

If p.turning <> 0

p.v_a = p.v_a + Sgn( p.turning ) * SHIP_ROTATION_ACCELERATION

End If

If Frame > 300

If p.shooting <> 0

If p.last_shot + SHOOT_DELAY < Frame

If p.energy > ENERGY_COST

PlayerShoot( p )
EndIf

End If

End If

EndIf

Next

End Function

Function PlayerShoot:TShot( p:TPlayer )

Local s:TShot

s = New TShot
s.rgb = p.rgb
s.p_x = p.p_x
s.p_y = p.p_y
s.v_x = Cos( p.p_a ) * SHOT_SPEED
s.v_y = Sin( p.p_a ) * SHOT_SPEED
s.player = p
p.energy = p.energy - ENERGY_COST
p.last_shot = Frame

TShot.List.AddLast( s )

Return s

End Function

Function PlayerDie( p:TPlayer )

Local i:Int

For i = 1 To 5

NewExplosion( p.p_x + Rand( - 10, 10 ) + Rand( - 10, 10 ), p.p_y + Rand( - 10, 10 ) + Rand( - 10, 10 ), Rand( 40, 80 ), Rand( 3, 5 ), p.rgb )

Next

PlayerCount = PlayerCount - 1

CreateDeathListItem( p )

TPlayerListItem.List.Remove( p.listItem )
TPlayer.List.Remove( p )

End Function

Function PositionPlayers( formation:Int = FORMATION_CIRCLE_OUTWARD, radius:Int = 50 )

Local p:TPlayer, i:Int, a:Int

Select formation

Case FORMATION_CIRCLE_OUTWARD

For p = EachIn TPlayer.List

a = i * 360 / PlayerCount
p.p_x = SCRW / 2 + Cos( a ) * radius
p.p_y = SCRH / 2 + Sin( a ) * radius
p.p_a = a
i = i + 1

Next

End Select

End Function

Function UpdateShots( )

Local s:TShot, p:TPlayer, a:Float

For s = EachIn TShot.List

s.p_x = s.p_x + s.v_x
s.p_y = s.p_y + s.v_y

If ( SCRW / 2 - s.p_x ) * ( SCRW / 2 - s.p_x ) + ( SCRH / 2 - s.p_y ) * ( SCRH / 2 - s.p_y ) > ARENA_SIZE * ARENA_SIZE

a = ATan2( ( SCRH / 2 - s.p_y ), ( SCRW / 2 - s.p_x ) ) + 180
NewExplosion( SCRW / 2 + Cos( a ) * ARENA_SIZE, SCRH / 2 + Sin( a ) * ARENA_SIZE, 30, 2, $3C3C3C )
TShot.List.Remove( s )

Else

For p = EachIn TPlayer.List

If s.player <> p

If ( p.p_x - s.p_x ) * ( p.p_x - s.p_x ) + ( p.p_y - s.p_y ) * ( p.p_y - s.p_y ) < SHIP_COLLISIONSIZE * SHIP_COLLISIONSIZE

p.hp = p.hp - SHOT_DAMAGE

If p.hp <= 0

If s.player <> Null

s.player.hp = s.player.hp + SHIP_HP_REWARD
SortPlayerListItemUp( s.player.listItem )

End If

PlayerDie( p )

Else

NewExplosion( s.p_x, s.p_y, 30, 2, s.rgb )
SortPlayerListItemDown( p.listItem )

EndIf

TShot.List.Remove( s )

Exit

EndIf

EndIf

Next

EndIf

Next

End Function

Function DrawPlayerList( )

Local pli:TPlayerListItem, dli:TDeathListItem, x1:Int, x2:Int, x3:Int, y1:Int, y2:Int, y3:Int

For pli = EachIn TPlayerListItem.List

SetColor 100, 100, 100
DrawRect -1, pli.y - 3, 120, PLAYERLISTITEM_HEIGHT - 4', 0

If pli.player.hp > SHIP_HP_MAX

SetColor 241, 165, 0
DrawRect 15, pli.y, 100, 15

Else

If pli.player.hp < SHIP_HP_MAX

SetColor 45, 45, 45
DrawRect 15, pli.y, 100, 15

EndIf

SetColor 150 - pli.player.hp * 150 / SHIP_HP_MAX, pli.player.hp * 150 / SHIP_HP_MAX, 0
DrawRect 15, pli.y, 100 * pli.player.hp / SHIP_HP_MAX, 15

End If

SetColor 255, 255, 255
DrawText pli.player.name, 15, pli.y

SetColor 100, 100, 100
DrawText "ai-time: " + Chr(134) + pli.player.ai_time * 1000 / Frame + "us", 0, pli.y + 16

SetColor 0, 0, pli.player.rgb
x1 = 7 + Cos( pli.player.p_a ) * 5
y1 = pli.y + 7 + Sin( pli.player.p_a ) * 5

x2 = 7 + Cos( pli.player.p_a + 140 ) * 5
y2 = pli.y + 7 + Sin( pli.player.p_a + 140 ) * 5

x3 = 7 + Cos( pli.player.p_a - 140 ) * 5
y3 = pli.y + 7 + Sin( pli.player.p_a - 140 ) * 5

DrawLine x1, y1, x2, y2
DrawLine x1, y1, x3, y3
DrawLine x2, y2, x3, y3

Next

For dli = EachIn TDeathListItem.List

SetColor 100, 100, 100
DrawRect -1, dli.y - 3, 120, PLAYERLISTITEM_HEIGHT - 4', 0
DrawImage Skull, 2, dli.y + 1
DrawText dli.name + " +" + dli.deathFrame / FPS + "s", 15, dli.y
DrawText "ai-time: "+ Chr(134) + dli.ai_time * 1000 / dli.deathFrame + "us", 0, dli.y + 16

Next

End Function

Function DrawPlayer( )

Local p:TPlayer, x1:Int, x2:Int, x3:Int, y1:Int, y2:Int, y3:Int

For p = EachIn TPlayer.List

SetColor 0, 0, p.rgb
x1 = p.p_x + Cos( p.p_a ) * SHIP_DRAWSIZE
y1 = p.p_y + Sin( p.p_a ) * SHIP_DRAWSIZE

x2 = p.p_x + Cos( p.p_a + 140 ) * SHIP_DRAWSIZE
y2 = p.p_y + Sin( p.p_a + 140 ) * SHIP_DRAWSIZE

x3 = p.p_x + Cos( p.p_a - 140 ) * SHIP_DRAWSIZE
y3 = p.p_y + Sin( p.p_a - 140 ) * SHIP_DRAWSIZE

DrawLine x1, y1, x2, y2
DrawLine x1, y1, x3, y3
DrawLine x2, y2, x3, y3

SetColor 45, 45, 45
DrawRect p.p_x - 25, p.p_y - 10, 50, 4

If p.hp > SHIP_HP_MAX
SetColor 241, 165, 0
DrawRect p.p_x - 25, p.p_y - 10, 50, 2
Else
SetColor 255 - p.hp * 255 / SHIP_HP_MAX, p.hp * 255 / SHIP_HP_MAX, 0
DrawRect p.p_x - 25, p.p_y - 10, 50 * p.hp / SHIP_HP_MAX, 2
End If



SetColor 0, 0, 255
DrawRect p.p_x - 25, p.p_y - 8, 50 * p.energy / ENERGY_MAX, 2

SetColor 150, 150, 150
DrawText p.name, p.p_x - TextWidth( p.name ) / 2, p.p_y - 25

Next
End Function

Function DrawShots( )

Local s:TShot

For s = EachIn TShot.List

SetColor 0, 0, s.rgb
DrawRect s.p_x - 1, s.p_y - 1, 3, 3

Next

End Function

Function NewExplosion:TExplosion( p_x:Int = 0, p_y:Int = 0, size_max:Int = 100, speed:Float = 1, rgb:Int )

Local e:TExplosion = New TExplosion

e.p_x = p_x
e.p_y = p_y
e.size_max = size_max
e.speed = speed
e.rgb = rgb
e.startFrame = Frame

TExplosion.List.AddLast( e )

Return e

End Function

Function Draw_Explosion( )

Local e:TExplosion, size:Int

For e = EachIn TExplosion.List

SetColor 0 , 0, e.rgb
DrawOval e.p_x - e.size / 2, e.p_y - e.size / 2, e.size, e.size', 0
e.size = ( Frame - e.startFrame ) * e.speed

If e.size >= e.size_max Then
TExplosion.List.Remove( e )
EndIf

Next

End Function

Function DrawArena( )

DrawImage Background, 0, 0

End Function

Function DrawHud( )

Local p:TPlayer, dli:TDeathListItem

SetColor 255, 255, 255

If Frame < 450

If Frame < 300

If Frame < 200

If Frame < 100

DrawText "- 3 -", SCRW / 2 - TextWidth( "- 3 -" ) / 2, SCRH / 2 - TextHeight( "- 3 -" ) / 2

Else

DrawText "- 2 -", SCRW / 2 - TextWidth( "- 2 -" ) / 2, SCRH / 2 - TextHeight( "- 2 -" ) / 2

EndIf

Else

DrawText "- 1 -", SCRW / 2 - TextWidth( "- 1 -" ) / 2, SCRH / 2 - TextHeight( "- 1 -" ) / 2

EndIf
Else

DrawText "FIGHT!", SCRW / 2 - TextWidth( "FIGHT!" ) / 2, SCRH / 2 - TextHeight( "FIGHT" ) / 2

EndIf

EndIf

If PlayerCount = 1

p = TPlayer( TPlayer.List.First( ) )
DrawText "LAST SHIP FLYING: " + p.name, SCRW / 2 - TextWidth( "LAST SHIP FLYING: " + p.name ) / 2, SCRH / 2 - TextHeight( "LAST SHIP FLYING: " + p.name ) / 2

ElseIf PlayerCount = 0

dli = TDeathListItem( TDeathListItem.List.First( ) )

If dli <> Null

DrawText "LAST SHIP TO DIE: " + dli.name, SCRW / 2 - TextWidth( "LAST SHIP TO DIE: " + dli.name ) / 2, SCRH / 2 - TextHeight( "LAST SHIP TO DIE: " + dli.name ) / 2

End If

End If

End Function

Function InitImages( )

Background = CreateImage( SCRW, SCRH )
Local pixmap:TPixmap = LockImage( Background )
Local x:Float, y:Float

pixmap.ClearPixels( $FF1E1E1E )

'Color 0, 0, 0
'Oval SCRW / 2 - ARENA_SIZE, SCRH / 2 - ARENA_SIZE, ARENA_SIZE * 2, ARENA_SIZE * 2

x = SCRW / 2
y = SCRH / 2

For Local r:Float = 0 To ARENA_SIZE Step 0.1

For Local a:Float = 0 To 360 Step 0.1

pixmap.WritePixel( x + r * Sin( a ), y + r * Cos( a ), $FF000000 )

Next

Next

'Color 60, 60, 60
'Oval SCRW / 2 - ARENA_SIZE, SCRH / 2 - ARENA_SIZE, ARENA_SIZE * 2, ARENA_SIZE * 2, 0

For Local a:Float = 0 To 359 Step 0.1

pixmap.WritePixel( x + ARENA_SIZE * Sin( a ), y + ARENA_SIZE * Cos( a ), $FF3C3C3C )

Next

UnlockImage( Background )

Skull = CreateImage( 13, 12 )
pixmap = LockImage( Skull )

'Color 100, 100, 100
'Rect 0, 1, 13, 10

For y = 1 To 10

For x = 0 To 12

pixmap.WritePixel( x, y, $FF646464 )

Next

Next

'Rect 1, 0, 11, 12

For y = 0 To 11

For x = 1 To 11

pixmap.WritePixel( x, y, $FF646464 )

Next

Next

'Color 0, 0, 0
'Rect 2, 0, 9, 2
For y = 0 To 1

For x = 2 To 11

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

' Rect 0, 2, 2, 7
For y = 2 To 8

For x = 0 To 1

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

'Rect 11, 2, 2, 7
For y = 2 To 8

For x = 11 To 12

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

'Rect 2, 10, 2, 2
For y = 10 To 11

For x = 2 To 3

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

'Rect 9, 10, 2, 2
For y = 10 To 11

For x = 9 To 10

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

'Rect 4, 5, 2, 2
For y = 5 To 6

For x = 4 To 5

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

'Rect 7, 5, 2, 2
For y = 5 To 6

For x = 7 To 8

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

'Rect 2, 7, 1, 2
For y = 7 To 8

For x = 2 To 2

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

'Rect 10, 7, 1, 2
For y = 7 To 8

For x = 10 To 10

pixmap.WritePixel( x, y, $FF000000 )

Next

Next

pixmap.WritePixel 0, 9, $FF000000
pixmap.WritePixel 12, 9, $FF000000
pixmap.WritePixel 3, 9, $FF000000
pixmap.WritePixel 9, 9, $FF000000

pixmap.WritePixel 2, 3, $FF000000
pixmap.WritePixel 3, 2, $FF000000
pixmap.WritePixel 10, 3, $FF000000
pixmap.WritePixel 9, 2, $FF000000

UnlockImage( Skull )

End Function


Ich wollte es eigentlich schon heute Nacht auf euch loslassen, aber ich dachte ich finde den Fehler noch =/

Übrigens eine sehr lustige Idee und es wäre sicher spannend mal ein paar Kämpfe von unterschiedlichen KIs zu sehen Smile

MfG DaysShadow
Blessed is the mind too small for doubt

Smily

BeitragFr, Jan 08, 2010 15:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn sich dadurch keiner auf die füße getreten fühlt, würde ich am wochenende mal so ein Framework auf OOP-Basis basteln, wie oben beschrieben.

Grüße,
Micha
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org

aMul

Sieger des Minimalist Compo 01/13

BeitragFr, Jan 08, 2010 15:23
Antworten mit Zitat
Benutzer-Profile anzeigen
@hectic:
Du hast recht. Die Grafik ist nicht unbedingt auf gute Performance optimiert.
Bei Gelegenheit werden wir uns da noch einmal ransetzen, der eigentliche Programmablauf bleibt aber von den FPS unabhängig, da alles Frame- und nicht Zeit-basiert ist.

Wegen der Funktion: Ich hab gerade den ersten Post editiert, ich hoffe so wird es klar(er).

@Smily:
ja, in BMax ließe sich die Einbindung neuer KIs eifnacher realisieren. Aber unser Framework ist nunmal in BB, was sicher auch Vorteile hat, da so mehr Leute mitmachen können.
Und ich denke, dass wir mit den begrenzten BB-Mitteln eine sehr gute Lösung gefunden haben.

@DaysShadow:
Ähm.. Nun, wenn man das ganze schon in Bmax schreibst sollte man aber auch gleich die Vorzüge der Sprache nutzen und wie von Smily richtig beschrieben die einbindung von KIs einfacher gestalten.

Wie dem auch sei. Es bleibt bei dem oben geposteten Framework. Zumindest die Einbindung der KI und die grundlegende Spiellogik wird nicht mehr verändert.

EDIT:
@Smily²:
Von uns aus kannst du das gerne machen.
Nur bitte dann in einen eigenen Thread, das hier ist unsrer. Razz Wink
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver

Xeres

Moderator

BeitragSa, Jan 09, 2010 10:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Ausgezeichnete Idee die sehr spaßig werden kann!
Aber noch zum Ablauf: Gibt es unterschiedliche Disziplinen? Werden es nur 1 vs. 1 kämpfe? (Zufällige) Teams? Unentschieden wenn sich zwei nach einer bestimmten Zeit immer noch nicht abgeschossen haben?
Gibt es noch einen "chat" in den die Bots schreiben können (zu debug zwecken aber auch zur allgemeinen belustigung)?

Wie auch immer, ich bastel denn mal etwas an meinem Bot...
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

aMul

Sieger des Minimalist Compo 01/13

BeitragSa, Jan 09, 2010 13:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Bisher gibt es nur simples FFA-Deathmatch.
Aber natürlich ließen sich noch weitere Spielmodi einbauen. Aber ich denke, dass einer für den Anfang genug ist.
Unentschieden ist bisher auch nicht vorgesehen, die Chance, dass das passiert halte ich auch für ausgesprochen gering.
Einen Chat gibt es auch nicht, aber ich werde mich bei nächster Gelegenheit(bin seit gestern Abend wieder zu Hause) mit kriD kurzschließen, ob und wie wir das Framework verändern/verbessern wollen.

So oder so danke für die Ideen. Ich sehe großes Potenzial in Wettbewerben wie diesem, und wer weiß wo das hier hinführen wird. Smile
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver

ComNik

BeitragSa, Jan 09, 2010 20:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Ach ja die AI Arena Idee...
Lang ists her aber ich hab noch eine Roboter/Auto Grafik von dir kriD Wink

Naja:

1. Kann es sein das ihr da Fliehkräfte mit eingebaut habt, weil sich die Npcs so schön drehen?
2. Ist eine gute Idee, aber nur für "Kampf" Kis geeignet oder?

lg
ComNik
WIP: Vorx.Engine

aMul

Sieger des Minimalist Compo 01/13

BeitragSa, Jan 09, 2010 21:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Fliehkräfte? Ich weiß nicht genau was du damit meinst. Trägheit haben wir aber, ja. Ansonsten wäre das steuern der Schiffe zu einfach, würde unrealistisch wirken und ein paar interessante Manöver wären nicht möglich. /imho Wink

"Kampf"-KI:
Ja, es sei denn, du schaffst es eine KI zu schreiben, die die letzten beiden Spieler dazu bekommt sich im gleichen Moment gegenseitig vom Himmel zu holen. Ansonsten gibt es bisher keine Möglichkeit zu gewinnen ohne zumindest ein anderes Schiff zu versenken.
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver

FireballFlame

BeitragSa, Jan 09, 2010 22:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Tolle Idee eigentlich. Ich finde es nur schade, dass das Ganze in BB ist und noch dazu so starke Einschränkungen existieren (keine eigenen Funktionen etc.).
Werde trotzdem mal probieren, ob ich was vernünftiges hinkriege. Rolling Eyes

Noch zwei Fragen:
in deinen Regeln steht "5. Die Funktion darf alle globalen Variablen und Types auslesen(jedoch nicht verändern)", der Beispielcode führt aber z.B. s\player nicht auf. Wie sieht es denn damit aus?
Ist Rekursion erlaubt?
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit

aMul

Sieger des Minimalist Compo 01/13

BeitragSa, Jan 09, 2010 23:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Da die Möglichkeiten der KI doch recht beschränkt ist sehen wir es nicht als notwendig an, zusätzliche Funktionen zu erlauben. Weiterhin sind die gegebenen Einschränkungen ein wichtiger Eckpfeiler des Wettbewerbs. Wenn man z.B. so viel Speicher oder gar eigene Types zur Verfügung hätte würden die KIs nur unnötig komplex werden und es würde nicht mehr der gewinnen der aus limitierten Ressourcen das meiste herausholen kann. Und das ist doch eine der Sachen die am Programmieren so viel Spaß macht. Wink

Zu den Fragen:
1. Ja, s\player darf man benutzen, werde das gleich oben hinzufügen(frag mich nicht, warum es da nicht schon steht). Was die anderen Sachen angeht, s. Regel Nr.6 Wink

2. Ja, Rekursion ist erlaubt. Also du darfst wenn du willst deine Funktion in derselben nochmal aufrufen(solange man nicht andere Spieler übergibt um an ihren Daten rumzufuschen natürlich Razz). Warum das jemand machen wollen würde weiß ich nicht, aber wenn man damit wirklich was schlaues machen kann bin ich der erste der das sehen will. Hierbei zu beachten ist aber natürlich die Performance. Aber bisher hab ich noch keine KI gesehen die in diesem Framework auch nur annähernd merkbar Rechenleistung braucht. Wenn das einer schafft(und zwar mit vernünftigen Berechnungen, nicht mir irgendwelchen leeren For-Schleifen) erkläre ich mich im Voraus beeindruckt.
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver

Tankbuster

BeitragSa, Jan 09, 2010 23:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Mal ein kleiner Tipp. Wäre es nicht vielleicht lustig, noch ein paar "Fähigkeiten" einzubaun?
Ich stelle mir darunter zum Beispiel einen Schub vor, sodass die KI (bzw. das Dreieck) kurzzeitig einen Geschwindigkeitsschub bekommt.
Das könnte ja einen cooldown haben, aber das würde die Kämpfe sicherlich interessanter machen, da man eine sehr gute Fluchtmöglichkeit hat Razz
Twitter
Download Jewel Snake!
Windows|Android

FireballFlame

BeitragSo, Jan 10, 2010 1:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Noch eine Frage: in welchem Maße sind Änderungen an den Spielregeln (also den Konstanten oben) zwischen verschiedenen Spielen zu erwarten? Wär ja doof, wenn jemand viel Zeit investiert, die KI auf alle Eventualitäten einzustellen und am Ende wird nur mit den Standardregeln gespielt Razz
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit

kriD

BeitragSo, Jan 10, 2010 2:28
Antworten mit Zitat
Benutzer-Profile anzeigen
@Tankbuster: Die von dir angesprochenen Fähigkeiten hatten wir auch schon in unsere Überlegungen mit eingeschlossen, ajedoch zunächst verworfen, da es erstens vom eigentlichen ablenken würde und zweitens das spiel unnnötig verkompliziert (und so vielleicht potentielle KI-Schtreiber abschreckt). jedoch lässt der Code solche Fähigkeitenänderungen zu. Ich werde mich mal mit aMul unterhalten um die sache weiter zu besprechen.

@FireballFlame: an spielregeländerungen hatten wir zunächst nicht gedacht. es ist jedoch ein interessanter gedanke. ich will aber wiedermal nichts voreiliges verkünden, das muss erst besprochen werden.


alles in einem wiedermal schöne Vorschläge! schön, dass leute gefallen an unserem framework finden Smile
antworten auf die fragen und vorschläge gibts morgen nach rücksprache..

lg kriD
Wenn ich du wäre, wäre ich lieber ich!

FireballFlame

BeitragSo, Jan 10, 2010 4:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Also dafür, dass Regeländerungen überhaupt stattfinden, bin ich auf jeden Fall! Ich finde es viel interessanter, wenn die KI die Konstanten auslesen und sich auf unterschiedliche Bedingungen einstellen muss, anstatt eine "hardgecodete" Taktik zu benutzen Twisted Evil
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit

Smily

BeitragMo, Jan 11, 2010 15:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie angekündigt, mein Versuch, das ganze mal in bmax umzusetzen
Ich wusste nicht, wo das hinpasst, also hab ichs erstmal ins codearchiv gepostet

Grüße,
Smily
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org

Xeres

Moderator

BeitragMo, Jan 11, 2010 16:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Übers Wochenende hab ich die Versionsnummer 04 des ersten Modells meiner AI erreicht:
- Defensive Duck and Cover Taktik (jaja, immer diese camper...)
- Richtet sich auf sein Ziel aus
- Feuert auf Gegner in Sicht
- Erfolgsquote von ~82% bei 7 Dummy Gegnern

Video-Demo
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

da_poller

BeitragMo, Jan 11, 2010 19:42
Antworten mit Zitat
Benutzer-Profile anzeigen
zum battle selbst:

das is mal ne richtig schöne idee.. sitz auch schon an den ersten ideen einer ki. jedoch hab ich noch 0(komma nix) erfahrung mit künstlichen intiligenzen und vermute, dass zuerstmal viele fehlschläge kommen werden, aber keine angst ich krieg euch noch Razz

Xerxes:


deine ki gewinnt gegen die dummys is aber doch recht deffensiv. absicht oder nur der bisherige status und die offensivmanöver noch nicht zu sehen? Wink alles in allem aber sehr nett anzusehn die taktik.

allgemein:

wie werden die battles ablaufen? 1vs1? 1 vs x dummys?
frage: mit welchem tool macht ihr die videos immer?

kriD

BeitragMo, Jan 11, 2010 20:18
Antworten mit Zitat
Benutzer-Profile anzeigen
@ Xeres: sehr schön anzusehen, auch toll, das du ein demovideo zu deiner KI gemacht hast. noch toller finde ich deine "winnershow" am ende! hab gehofft, das die leute sowas einbauen.

(ich denke, das am ende (nach dem sieg) auch an den "verbotenen" typeeinträgen, zB player\energy etc rumgeändert werden darf, um eine wirklich tolle winnershow o.ä. zu erstellen..
aber das nur am rande..)

@da_poller oder @wettkampfs-ablauf: wenn es nicht zu viele KIs werden (dann müsste man sich ein faires turnier überlegen) wollten wir alle KIs in einem deathmatch gegeneinander antreten lassen.
unser video haben wir mit camtasia studio gemacht.

@Tankbuster und FireballFlame: die erste runde wird mit den standartregeln statfinden und auch ohne spezial-fähigkeiten auskommen müssen. danach überlegen wir, ob wir zur nächsen runde (vlt zu jeder neuen runde) neue fähigkeiten oder physikalische änderungen vornehmen, um den wettkampf abwechslungsreich zu gestalten, oder ob die regeln wie gehabt bleiben, damit man die KIs perfektionieren kann. sicher hat beides seine reize.
also: die regeln bleiben zur ersten runde gleich.

lg kriD
Wenn ich du wäre, wäre ich lieber ich!

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group