purebasic.info

PureBasic forum
Текущее время: Ср июн 19, 2019 6:11 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 13 ] 
Автор Сообщение
 Заголовок сообщения: Игра "жизнь" и подобные
СообщениеДобавлено: Вт янв 01, 2019 6:05 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Чт июн 25, 2009 1:02 pm
Сообщений: 2317
Откуда: Russia — Belarus
Благодарил (а): 7 раз.
Поблагодарили: 73 раз.
Пункты репутации: 11
Захотелось создать нечто подобное популярной игре "Жизнь". Оказывается, это весьма сложная задача.

  • Как лучше организовать хранение списка "ботов" в игровом мире? Изначально думал делать на List'е, но его оказалось ужасно неудобно "листать", особенно когда листаешь в рекурсии (он же один и текущий его элемент меняется и т.д.).
    Сейчас список "ботов" это простой массив под структурой. Хоть меня и напрягает то, что он обязательно должен существовать изначально (Dim) и то, что я не могу нормально удалить элемент (бота) из массива без его пересортировки и т.д. (в List'е это просто DeleteElement().
  • Начал писать логику ботов. Вызвала вопросы простейшая функция lookaround (заставляет бота осмотреться вокруг себя и вернуть список всех объектов, которые находятся вокруг него). Собственно написать функцию осмотра вокруг себя не проблема, но как функцией вернуть список всех обнаруженных объектов (а их может быть больше дюжины) для дальнейшей обработки логикой бота уже вне функции?

Прикрепляю текущий код. л.кн. мыши создает стоячего бота, пр.кн. мыши создает бота с рендомным кол-вом шагов вправо-вниз (Random в PB не может быть отрицательным, просто facepalm). Средняя кнопка мыши -- удаление бота (а точнее его перемещение в 0х0 координату ибо массив).

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
EnableExplicit
 
Structure bot
  unique_id.i
  x.i
  y.i
  x_move.i
  y_move.i
  look_range.i
EndStructure
 
Global NewList bots.bot()
Global bot_counter.i
 
Procedure.i id_by_pos(x.i, y.i, return_unique_id.i = 0)
  Define result.i = -1
  PushListPosition(bots())
  ForEach bots()
    If bots()\x = x And bots()\y = y
      If return_unique_id
        result = bots()\unique_id
      Else
        result = ListIndex(bots())
      EndIf
      Break
    EndIf
  Next
  PopListPosition(bots())
  ProcedureReturn result
EndProcedure
 
Procedure.i add(x.i, y.i)
  Define result.i
  If id_by_pos(x, y) = -1
    PushListPosition(bots())
    If AddElement(bots())
      bot_counter + 1
      bots()\unique_id = bot_counter
      bots()\x = x
      bots()\y = y
      bots()\x_move = 0
      bots()\y_move = 1
      bots()\look_range = 10
      Debug "bot added at: " + Str(x) + "x" + Str(y) + " (UNIQUE ID: " + bots()\unique_id + ", " + "LISTID: " + ListIndex(bots()) + ")"
      result = 1
    EndIf
    PopListPosition(bots())
  EndIf
  ProcedureReturn result
EndProcedure
 
Procedure.i remove(id.i, by_unique_id.i = 0)
  If id > -1
    PushListPosition(bots())
    If by_unique_id
      Debug "remove by unique id"
      ForEach bots()
        If bots()\unique_id = id
          DeleteElement(bots())
          Break
        EndIf
      Next
    Else
      If SelectElement(bots(), id)
        DeleteElement(bots())
      EndIf
    EndIf
    PopListPosition(bots())
  EndIf
EndProcedure
 
Structure look
  id.i
  x.i
  y.i
EndStructure
 
;add(10, 10)
 
Define i_counter.i
Define i_counterr.i
For i_counter = 50 To 150
  i_counter + 1
  For i_counterr = 50 To 150
    i_counterr + 1
    add(i_counter, i_counterr)
Next
Next
 
;GUI
#zoom = 3
#w = 640
#h = 480
#ms_per_tick = 50
 
Enumeration
  #window_world
  #g_canvas
  #g_image
EndEnumeration
 
Global g_ms.i
Global g_tick.i
 
If OpenWindow(#window_world, #PB_Ignore, #PB_Ignore, #w, #h, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateImage(#g_image, #w, #h)
    CanvasGadget(#g_canvas, 0, 0, #w, #h, #PB_Canvas_ClipMouse)
  SetGadgetAttribute(#g_canvas, #PB_Canvas_Image, ImageID(#g_image))
 
  Repeat
   
    g_ms.i = ElapsedMilliseconds()
    If g_ms / #ms_per_tick <> g_tick
      g_tick + 1
      SetWindowTitle(#window_world, Str(g_tick))
 
      ;LOGIC
      PushListPosition(bots())
      ClearDebugOutput()
      ForEach bots()
        Define random_step.i = Random(1, 0)
        Define random_minus.i = Random(1, 0)
        If random_minus = 1
          random_step = random_step * -1
        EndIf
       
        Define random_axis.i = Random(1, 0)
        If random_axis = 0
          ;x
          bots()\x_move = random_step
        Else
          ;y
          bots()\y_move = random_step
        EndIf
       
        If bots()\x_move <> 0
          If id_by_pos(bots()\x + bots()\x_move, bots()\y) = -1
            bots()\x + bots()\x_move
          EndIf
        ElseIf bots()\y_move <> 0
          If id_by_pos(bots()\x, bots()\y + bots()\y_move) = -1
            bots()\y + bots()\y_move
          EndIf
        EndIf
       
        bots()\x_move = 0
        bots()\y_move = 0
      Next
      PopListPosition(bots())
  EndIf
 
    ;DRAW WORLD
    If StartDrawing(ImageOutput(#g_image))
      Box(0, 0, #w, #h, RGB(90, 90, 90))
      PushListPosition(bots())
      ForEach bots()
        If bots()\unique_id = 1
          Box(bots()\x * #zoom, bots()\y * #zoom, #zoom, #zoom, RGB(255, 0, 0))
        Else
          Box(bots()\x * #zoom, bots()\y * #zoom, #zoom, #zoom, RGB(255, 255, 120))
        EndIf
        Line(bots()\x * #zoom, bots()\y * #zoom, #zoom, 1, RGB(0, 0, 0))
        Line(bots()\x * #zoom, bots()\y * #zoom, 1, #zoom, RGB(0, 0, 0))
        Line(bots()\x * #zoom + #zoom -1, bots()\y * #zoom + #zoom - 1, 1, -#zoom, RGB(0, 0, 0))
        Line(bots()\x * #zoom, bots()\y * #zoom + #zoom - 1, #zoom, 1, RGB(0, 0, 0))
      Next
      PopListPosition(bots())
 
      StopDrawing()
    EndIf
    SetGadgetAttribute(#g_canvas, #PB_Canvas_Image, ImageID(#g_image))
   
    Select WindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #g_canvas
            Select EventType()
              Case #PB_EventType_LeftClick
                add(GetGadgetAttribute(#g_canvas, #PB_Canvas_MouseX) / #zoom, GetGadgetAttribute(#g_canvas, #PB_Canvas_MouseY)  / #zoom)
              Case #PB_EventType_RightClick
              Case #PB_EventType_MiddleButtonDown
                remove(id_by_pos(GetGadgetAttribute(#g_canvas, #PB_Canvas_MouseX) / #zoom, GetGadgetAttribute(#g_canvas, #PB_Canvas_MouseY)  / #zoom))
            EndSelect
        EndSelect
      Case #PB_Event_CloseWindow
        Break
    EndSelect
  ForEver
EndIf


_________________
EnableExplicit User


Последний раз редактировалось qpAHToMAS Ср янв 02, 2019 3:06 pm, всего редактировалось 3 раз(а).

Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Вт янв 01, 2019 6:10 pm 
Не в сети
профессор

Зарегистрирован: Пт фев 20, 2009 12:57 pm
Сообщений: 1761
Откуда: Алматы
Благодарил (а): 17 раз.
Поблагодарили: 49 раз.
Пункты репутации: 5
аааа... я обнаружил ахента Великобритании!!! :)
Цитата:
а их может быть больше дюжины

по поводу рандома - а почему-бы не сделать что-то типа:
рандом от 0 до 100. а после 0-50 это отрицатальное число, 51-100 - положительное.
то есть (рандом от 0 до 100) - 50


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Вт янв 01, 2019 7:05 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Чт июн 25, 2009 1:02 pm
Сообщений: 2317
Откуда: Russia — Belarus
Благодарил (а): 7 раз.
Поблагодарили: 73 раз.
Пункты репутации: 11
Можно сделать и еще один Random(1, 0), который решает, умножить на -1 или нет, но суть не в этом, а в том, что PB "топорен" вот в таких вот местах. За место кодинга пока у тебя есть мысль и идея ты должен изобретать вот такие вот велосипеды, которые встречаются на пути.

_________________
EnableExplicit User


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Вт янв 01, 2019 8:29 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
qpAHToMAS писал(а):
неудобно "листать", особенно когда листаешь в рекурсии
Рекурсию в программе не заметил. Посмотри функции PushListPosition и PopListPosition.

qpAHToMAS писал(а):
но как функцией вернуть список всех обнаруженных объектов (а их может быть больше дюжины) для дальнейшей обработки логикой бота уже вне функции?
Из процедуры можно возвращать списки или массивы (что будет удобнее).
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Procedure DebugList(c.l, List ParameterList.Point())
 
  AddElement(ParameterList())
  ParameterList()\x = 1
 
  AddElement(ParameterList())
  ParameterList()\x = 2
 
  AddElement(ParameterList())
  ParameterList()\x = 3
 
EndProcedure
 
NewList Test.Point()
 
DebugList(10, Test())
 
ForEach Test()
  Debug Str(Test()\x)
Next



qpAHToMAS писал(а):
Random в PB не может быть отрицательным
Код:
1
2
x = (Random($7FFFFFFF , 0)-$7FFFFFFF/2)
Debug x


_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Вт янв 01, 2019 11:12 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 853
Благодарил (а): 2 раз.
Поблагодарили: 40 раз.
Пункты репутации: 9
Создавать либо только на прибавку количества ботов а отключенные типа в ид ставить -1
или делать каждый раз смещение в памяти или массиве на структуру бота и после редим или реаллок.
а лучше всего я вижу на каждого бота выделять отдельную память и в ид писать адрес памяти а нумерацию сделать отдельно и когда любого удаляем чистим памть и пишим в ид -1
по закрытию проги бегём по количеству ботов и смотрим на ид если -1 значит бота уже не существует в противном случае удаляем.и когда вновь создаваемый бот проверять нумерацию и смотреть незанят ли номер(типа ид-1 ранее был удалён,значит под этим номером создаём новоё чудо юдо) :D :roll:


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 7:44 am 
Не в сети
профессор

Зарегистрирован: Вт май 13, 2014 4:12 am
Сообщений: 823
Благодарил (а): 82 раз.
Поблагодарили: 23 раз.
Пункты репутации: 5
не ищи себе приключений, выделил память и не трогай её, память нельзя проверить типа isMemory, а значит лучше её не трогать, только метить, живой не живой
как вариант, выдели лишнего и метки ставь в памяти перед началом бота
выдели один большой кусок и в нём разложи их всех, по любому адреса нужны, а один кусок, как мне кажется, это лучше чем куча мелких
а будешь память туды сюды дёргать, найдёшь приключений

Сергейчик писал(а):
по закрытию проги бегём по количеству ботов....

после закрытия проги? ты крутой :D :D :D
но мы поняли о чём ты


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 10:13 am 
Не в сети
МОДЕРАТОР

Зарегистрирован: Вт дек 05, 2006 8:46 am
Сообщений: 6519
Благодарил (а): 28 раз.
Поблагодарили: 215 раз.
Пункты репутации: 57
Вариант реализации на 60 строк
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Define.l x,y,i,col,frame,oldframe
Global Dim LifeArray.b(1,255,255)
InitKeyboard():InitSprite()
OpenScreen(1024, 768, 32, "Игра Жизнь")
CreateSprite(0,256,256,#PB_Sprite_AlphaBlending)
ZoomSprite(0, 768,768)
SpriteQuality(#PB_Sprite_NoFiltering)
col=$3AEBAC:frame=0:oldframe=0
Procedure RandomLife()
For y=0 To 255
  For x=0 To 255
    LifeArray(0,x,y)=Random(1)
  Next
Next
EndProcedure
randomlife()
Repeat
  FlipBuffers()
  oldframe=frame
  frame=1-frame
  For y=0 To 255
    For x=0 To 255
      i=LifeArray(oldframe,(x-1)&255,(y-1)&255)
      i=i+LifeArray(oldframe,x,(y-1)&255)
      i=i+LifeArray(oldframe,(x+1)&255,(y-1)&255)
      i=i+LifeArray(oldframe,(x-1)&255,y)
      i=i+LifeArray(oldframe,(x+1)&255,y)
      i=i+LifeArray(oldframe,(x-1)&255,(y+1)&255)
      i=i+LifeArray(oldframe,x,(y+1)&255)
      i=i+LifeArray(oldframe,(x+1)&255,(y+1)&255)
      If i=2 And LifeArray(oldframe,x,y)=1
        LifeArray(frame,x,y)=1
      ElseIf i=3
        LifeArray(frame,x,y)=1
      Else
        LifeArray(frame,x,y)=0
      EndIf
    Next
  Next
  StartDrawing(SpriteOutput(0))
  Box(0, 0, 256, 256 ,0)
  For y=0 To 255
    For x=0 To 255
      If LifeArray(frame,x,y)
        Plot(x,y,col)
      EndIf
    Next
  Next
  StopDrawing()
  ClearScreen(0)
  StartDrawing(ScreenOutput())
  DrawText(10, 10, "ESC=Выход",$ffffff)
  DrawText(10, 50, "Space=Снова",$ffffff)
  StopDrawing()
  DisplaySprite(0,(1024-768)/2,0)
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Space)
    randomlife()
  EndIf
Until KeyboardPushed(#PB_Key_Escape)


Адаптация с кода 2004 г. Автор оригинала где то на офф. форуме

_________________
read-only ¯\_(ツ)_/¯


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 2:12 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Чт июн 25, 2009 1:02 pm
Сообщений: 2317
Откуда: Russia — Belarus
Благодарил (а): 7 раз.
Поблагодарили: 73 раз.
Пункты репутации: 11
Обновил код в первом посте. Спасибо Петру за команды List'ов, теперь список ботов именно на List'е.

2601 точка, которая перемещается рендомно каждый тик (с учетом столкновений друг в друга). Запускать лучше без дебаггера.

_________________
EnableExplicit User


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 4:28 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 853
Благодарил (а): 2 раз.
Поблагодарили: 40 раз.
Пункты репутации: 9
Было бы интересней если боты создавались за единицу времени(временной цикл создания) и пожирали друг друга если не успел сбежать от другого бота(скорость движения в рандоме)
и смотреть равновесное состояние(сколько живых при разном интервале создания) а не счётчик циклов. :roll:


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 5:39 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Чт июн 25, 2009 1:02 pm
Сообщений: 2317
Откуда: Russia — Belarus
Благодарил (а): 7 раз.
Поблагодарили: 73 раз.
Пункты репутации: 11
Сергейчик писал(а):
Было бы интересней если боты создавались за единицу времени(временной цикл создания) и пожирали друг друга если не успел сбежать от другого бота(скорость движения в рандоме)
и смотреть равновесное состояние(сколько живых при разном интервале создания) а не счётчик циклов. :roll:

Да, именно так и планируется!
Причем помимо скорости передвижения будете еще индивидуальный параметр "реакции" бота и остальные вещи.

Я бы в идеале хотел сделать "искуственное ДНК" как в этом видео:
https://www.youtube.com/watch?v=PCx228KcOow
Но не совсем понимаю, как лучше его реализовать. И честно говоря, ДНК как в этом видео без какой-либо логики мне не очень нравится.
Автор этого видео уже экспериментирует с нейросетями, но на такую глобальную работу я даже не заикаюсь, а было бы супер!

_________________
EnableExplicit User


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 6:18 pm 
Не в сети
профессор

Зарегистрирован: Пт фев 20, 2009 12:57 pm
Сообщений: 1761
Откуда: Алматы
Благодарил (а): 17 раз.
Поблагодарили: 49 раз.
Пункты репутации: 5
*мечтаю:
подключил микрофон. запускаешь эту нейросеть... и говоришь:
- сделай мне игру, как а маунт анд блейд, но чтоб как в майнкрафте замки строить, добывать железо в шахтах, ковать мечи, чтоб нпс разговаривали...
и она все делает. ты сидишь только хотелки свои в микрофон проговариваешь :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 7:55 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
SereZa писал(а):
как в майнкрафте замки строить, добывать железо в шахтах
Зачем добывать железо. Есть же карьер.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Игра "жизнь" и подобные
СообщениеДобавлено: Ср янв 02, 2019 9:12 pm 
Не в сети
профессор

Зарегистрирован: Пт фев 20, 2009 12:57 pm
Сообщений: 1761
Откуда: Алматы
Благодарил (а): 17 раз.
Поблагодарили: 49 раз.
Пункты репутации: 5
ну нюансы что где откопать - дело пятое :) я люблю песочницы. чтоб железо, уголь, медная руда, золотая руда, осина, ель, сосна, береза, красное дерево какое-нить там... выделка кожи. браузерка Therian Saga кароче рулит :) мне очень понравилась, хотя и схематичная-двумерная. а вот 3д бы, да с полной кустомизацией, плюс ММО, с непрямым управлением так сказать... а что-то похожее на Dungeon Keeper - то есть возможность из изометрической стратегии переключится в 3D - вселившись в конкретного юнита. сами юниты имеют тыщу характеристик и прокачивают их путем занятия тем или иным делом. типа изначально все просто бестолковые болванки. послал кого-то пилить лес. у него прокачивается навык рубки леса. кого-то на охоту - соответственно навык охоты... и изначально у тебя в "подчинении" скажем пяток таких болванок. построив дом... где-то на глобальной ММО карте - то к тебе могут прибиваться другие такие-же болванки. типа проходил мимо... О! у вас ДОМ?!?! пустите меня к себе жить! я могу грибы собирать! тут раз мимо живой человек проходил. пришел на переговоры: чо, может вместе поселимся? - а давай! уже в двоем поселением управляют, каждый своей бригадой... и так далее и тому подобное :) и нейросеть тебе это дело заночь напрограммит. ты сидишь, в носу ковыряешься, и придумываешь чем бы еще эту нейросеть озадачить :))) а так вобще и вобщем - как представлю объем кода, который нужно будет родить, чтоб придумать что-то подобное по моим хотелкам - то плохо становится :) со своим редактором то куда проще задачи стоят - и то этого кода требуется вагон (к 100 тыщам строк уже подбираюсь. хотя это грязный код. нет стандарта и часто повторяется, а еще часто чужой код, который без понятия что делает :)). а уж полноценную игру пилить... эх.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: AZJIO и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB