Jump to content

Recommended Posts

Hi.
I have been reading the 1982 book by David L. Heiserman titled "Projects in Machine Intelligence For Your Home Computer" which I found on Ebay a while back. At first glance, it looked like a very primitive book for the beginner programmer with a lofty title, but then as I dug further into it out of boredom while on a plane ride, it started to reveal some very interesting concepts particularly about the emergence of seemingly complex behavior out of simple reflexive elements.
So I decided to start a thread on my experimentations with this topic, basing it on the concepts detailed in the book.
First the framework: a box with two bugs and random obstacles. The bugs have fight and flight behavior, and have an even chance of destroying an obstacle or their counterpart versus fleeing away. Their direction of motion is randomly chosen and will only change when an impenetrable obstacle blocks the way. The activities of the bugs are simulated through asynchronous multitasking. Here's what it looks like:

http://youtu.be/L_5Sy0NYdiY

As you can see, it's very simple, for now. Over the course of the next several weeks (or months), I will be adding more features. For example, what happens if I add resource competition? How about random mutations that add or subtract capabilities? And if I add non-aggressive strains to the mix, will predator-pray behavior emerge?
We shall see icon_smile.gif Stay tuned...
Oh and it's written in XB of expediency and ease of programming. Here's the listing:

5 CALL CLEAR :: RANDOMIZE
6 DIM PHASE(2),PX(2),PY(2),BUG(2),CX(2),CY(2)
10 CALL CHAR(96,"FFFFFFFFFFFFFFFF",104,"007E7E7E7E7E7E00",112,"80433C3C3C7C8204",120,"80433C3C3C7C8204")
20 CALL COLOR(10,15,1,11,10,1,12,6,1)::CALL SCREEN(4)
25 BUG(1)=112::BUG(2)=120
30 REM SET UP FIELD
40 CALL HCHAR(1,1,96,32) :: CALL VCHAR(2,1,96,23) :: CALL VCHAR(2,32,96,23) :: CALL HCHAR(24,2,96,30)
50 FOR I=1 TO 40 :: CALL PLACE(X,Y) :: CALL HCHAR(Y,X,104) :: NEXT I
60 FOR ID=1 TO 2::CALL PLACE(PX(ID),PY(ID)) :: CALL HCHAR(PY(ID),PX(ID),BUG(ID))::PHASE(ID)=1::NEXT ID
100 REM ALPHA BEHAVIOR
101 ID=1
102 IF PHASE(ID)=0 THEN 150 ELSE IF PHASE(ID)=2 THEN 120
103 REM PHASE 1 - SELECT MOVE DIRECTION
110 CALL MOVE(CX(ID),CY(ID))
111 REM PHASE 2 - DETECT OBSTACLE AND MOVE
120 CALL DETECT(PX(ID),PY(ID),CX(ID),CY(ID),RC,R,NX,NY)
130 IF R=1 THEN CALL SOUND(10,110,15) :: PHASE(ID)=1::GOTO 150
131 IF R=2 AND ID=1 THEN PHASE(2)=0 ELSE IF R=2 AND ID=2 THEN PHASE(1)=0
132 PHASE(ID)=2
140 CALL HCHAR(PY(ID),PX(ID),32) :: PX(ID)=NX :: PY(ID)=NY :: CALL HCHAR(PY(ID),PX(ID),BUG(ID)) :: CALL SOUND(10,2000,15)
150 IF ID=1 THEN ID=2 ELSE ID=1
160 GOTO 102
10000 SUB PLACE(X,Y)
10010 X=INT(RND*30)+2 :: Y=INT(RND*21)+2
10020 CALL GCHAR(Y,X,C) :: IF C<>32 THEN 10010
10030 SUBEND
10040 SUB MOVE(CX,CY)
10050 CX=INT(RND*2) :: DIR=INT(RND*9)+1 :: IF DIR>5 THEN CX=-CX
10060 CY=INT(RND*2) :: DIR=INT(RND*9)+1 :: IF DIR>5 THEN CY=-CY
10065 IF CX=0 AND CY=0 THEN 10050
10070 SUBEND
10080 SUB DETECT(X,Y,CX,CY,RC,R,NX,NY)
10090 NX=X :: NY=Y :: SX=SGN(CX) :: SY=SGN(CY) :: AX=ABS(CX) :: AY=ABS(CY) :: R=0
10100 IF AX=0 THEN 10130
10110 AX=AX-1 :: IF SX=1 THEN NX=NX+1 ELSE NX=NX-1
10130 IF AY=0 THEN 10150
10140 AY=AY-1 :: IF SY=1 THEN NY=NY+1 ELSE NY=NY-1
10150 CALL GCHAR(NY,NX,RC)
10160 IF RC=32 THEN 10170
10161 IF RC=96 THEN R=1::GOTO 10180
10162 KILL=INT(RND*9)+1::IF KILL>5 THEN CALL SOUND(10,-5,15) ELSE R=1::GOTO 10180
10163 IF RC=112 OR RC=120 THEN R=2::GOTO 10180
10170 IF AX>0 OR AY>0 THEN 10100
10180 SUBEND
Edited by Vorticon
  • Like 2
Link to comment
https://forums.atariage.com/topic/208936-musings-in-machine-intelligence/
Share on other sites

That is pretty cool. I also think I have that book, but I can't check until I get unpacked. I have always been interested in AI for games, but many of the "modern" books are geared for systems that have CPU and RAM to spare. I always think about arcade video games and how the AI might have been done for various games, which are not a simple as most people think they are.

 

It would be nice to have a small reference of usable AI routines for games written in XB or assembly. I wonder if anyone has done some research and collecting before? Off to Google I go...

That is pretty cool. I also think I have that book, but I can't check until I get unpacked. I have always been interested in AI for games, but many of the "modern" books are geared for systems that have CPU and RAM to spare. I always think about arcade video games and how the AI might have been done for various games, which are not a simple as most people think they are.

 

To that end, if you search around on this forum there is a fantastic thread discussing the AI of the ghosts in PacMan. Very readable, and very cool to see how they work. :)

I'll have to check it out. But this is the best article on PacMan I have ever read:

 

http://www.gamasutra.com/view/feature/132330/the_pacman_dossier.php?print=1

 

I wish there was something like that for every classic video game.

  • Like 2

Thanks for pointing out that book! It sounds interesting, so I just bought a copy from Amazon.

 

I was interested in artificial life back in the 90s. I wrote a program called "critters" for the A8 back then that featured little critters that moved, fought, bred, ate, and died. There were also plants that were food for them. It would be neat to revisit the topic of a-life again.

So here's Beta. It's a little evolutionary leap from it's predecessor, Alpha, in that while it retains the fight or flight behavior, now it can remember its actions and the outcomes, and eventually will settle into a "safe" pattern based on its previous experiences. In most cases, this will happen very quickly, but sometimes the patterns created can be pretty convoluted. So now we are seeing a higher level of complexity with only the addition of extremely primitive learning mechanisms. In this version, there is only a single bug which leaves a trail of dots as it moves about. Thinking ahead, I wonder if adding several Beta bugs together will yield to some form of territoriality, each bug following its own wholly separate and non-intersecting pattern...

To allow for active experimentation, the program has several single key commands available:

C: clear the bug's memory
F: force a new movement direction
D: displace the bug to a random location while retaining its memory
G: Generate a new landscape again with no loss of memory
T: erase the trails so you can visualize the stable patterns better

Below is a demo of a run. At first, the bug settles into a stable pattern rather quickly, so I tried to force a few new motion codes by pressing F, tried to displace it, cleared its memory, and it finally settled into a more elaborate pattern. It's interesting to see that intermittent forced direction changes very quickly settle back into the same pattern. Even full displacement does not seem to alter it much. There is really a lot of complexity under the surface... (the video has a lot of artifacts and my bug is now a square for some off reason, but you get the idea)

http://youtu.be/fZuqHHsA4wg

Here's the listing for Beta:

5 CALL CLEAR :: RANDOMIZE
6 REM INITIALIZE VARIABLES
9 DIM MEM(4,4,2)
10 CALL CHAR(91,"0000001818000000",96,"FFFFFFFFFFFFFFFF",104,"007E7E7E7E7E7E00",112,"80433C3C3C7C8204")
20 CALL COLOR(8,14,1,10,15,1,11,10,1)::CALL SCREEN(4)
21 GOSUB 8040
30 REM SET UP FIELD
40 CALL HCHAR(1,1,96,32) :: CALL VCHAR(2,1,96,23) :: CALL VCHAR(2,32,96,23) :: CALL HCHAR(24,2,96,30)
50 FOR I=1 TO 40 :: CALL PLACE(X,Y) :: CALL HCHAR(Y,X,104) :: NEXT I
60 CALL PLACE(PX,PY)::CALL HCHAR(PY,PX,112)
62 REM BETA BEHAVIOR
64 CALL MOVE(CX,CY)
66 CALL DETECT(PX,PY,CX,CY,R,RC,NX,NY)
68 IF R=0 THEN GOSUB 8070::GOTO 110 ! PATH CLEAR. KEEP MOVING
70 MRX=CX+2::MRY=CY+2::MK=MEM(MRX,MRY,0)::MX=MEM(MRX,MRY,1)::MY=MEM(MRX,MRY,2) ! PATH BLOCKED. CHECK MEMORY FOR RESPONSE
71 IF MX=5 OR MY=5 THEN GOSUB 8010::IF KL=1 THEN MEM(MRX,MRY,0)=1::GOTO 73 ELSE 82 ! NO CODE IN MEMORY. ATTEMPT KILL
72 IF MK<>1 OR RC=96 THEN 74 ELSE CALL SOUND(10,-5,15)::GOSUB 8070::GOTO 110
73 MEM(MRX,MRY,1)=CX::MEM(MRX,MRY,2)=CY::GOSUB 8070::GOTO 110 ! KILL RESPONSE FOUND
74 CALL DETECT(PX,PY,MX,MY,R,RC,NX,NY) ! VALID MOTION CODE IN MEMORY. TEST CODE
76 IF R=0 THEN CX=MX::CY=MY::GOSUB 8070::GOTO 110 ! PATH CLEAR. EXECUTE STORED MOVE
78 GOSUB 8010 ! PATH BLOCKED. TRY TO KILL OBSTACLE
80 IF KL=1 THEN MEM(MRX,MRY,0)=1::CX=MX::CY=MY::GOSUB 8070::GOTO 110
82 CALL MOVE(CX,CY)
84 CALL DETECT(PX,PY,CX,CY,R,RC,NX,NY)
86 IF R=0 THEN MEM(MRX,MRY,0)=0::MEM(MRX,MRY,1)=CX::MEM(MRX,MRY,2)=CY::GOSUB 8070::GOTO 110
88 GOSUB 8010::IF KL=0 THEN 82
90 MEM(MRX,MRY,0)=1::MEM(MRX,MRY,1)=CX::MEM(MRX,MRY,2)=CY::GOSUB 8070
100 REM COMMAND TRAPPING
110 CALL KEY(0,KY,S)
120 IF KY<>67 AND KY<>99 THEN 140 ! C PRESSED: CLEAR BUG MEMORY
130 GOSUB 8040::GOTO 66
140 IF KY<>70 AND KY<>102 THEN 160 ! F PRESSED: FORCE NEW MOTION CODE
150 CALL MOVE(NCX,NCY)::IF NCX=CX AND NCY=CY THEN 150 ELSE CX=NCX::CY=NCY::GOTO 66
160 IF KY<>68 AND KY<>100 THEN 180 ! D PRESSED: DISPLACE BUG TO NEW LOCATION
170 CALL HCHAR(PY,PX,32)::CALL PLACE(PX,PY)::CALL HCHAR(PY,PX,112)::GOTO 66
180 IF KY<>71 AND KY<>103 THEN 220 ! G PRESSED: GENERATE NEW FIELD
190 CALL CLEAR::CALL HCHAR(1,1,96,32) :: CALL VCHAR(2,1,96,23) :: CALL VCHAR(2,32,96,23) :: CALL HCHAR(24,2,96,30)
200 FOR I=1 TO 40
201 CALL PLACE(X,Y)::IF X=PX AND Y=PY THEN 201
205 CALL HCHAR(Y,X,104)::NEXT I
210 CALL HCHAR(PY,PX,112)::GOTO 66
220 IF KY<>84 AND KY<>116 THEN 66 ! T PRESSED: CLEAR BUG TRAIL
230 FOR X=2 TO 31::FOR Y=2 TO 23::CALL GCHAR(Y,X,C)::IF C=91 THEN CALL HCHAR(Y,X,32)
240 NEXT Y::NEXT X
250 GOTO 66
8000 REM KILL DECISION ROUTINE
8010 KL=0::IF RC<>96 THEN KILL=INT(RND*10)+1::IF KILL>5 THEN CALL SOUND(10,-5,15)::KL=1
8020 RETURN
8030 REM CLEAR BUG MEMORY ROUTINE
8040 FOR I=0 TO 4::FOR J=0 TO 4::FOR K=0 TO 2::MEM(I,J,K)=5::NEXT K::NEXT J::NEXT I
8050 RETURN
8060 REM DISPLAY BUG MOVEMENT ROUTINE
8070 CALL HCHAR(PY,PX,91)::PX=NX::PY=NY::CALL HCHAR(PY,PX,112)
8080 RETURN
9999 REM RANDOM OBJECT SCREEN PLACEMENT ROUTINE
10000 SUB PLACE(X,Y)
10010 X=INT(RND*30)+2 :: Y=INT(RND*21)+2
10020 CALL GCHAR(Y,X,C) :: IF C<>32 THEN 10010
10030 SUBEND
10035 REM RANDOM MOVEMENT GENERATION ROUTINE
10040 SUB MOVE(CX,CY)
10050 CX=INT(RND*3) :: DIR=INT(RND*10)+1 :: IF DIR>5 THEN CX=-CX
10060 CY=INT(RND*3) :: DIR=INT(RND*10)+1 :: IF DIR>5 THEN CY=-CY
10065 IF CX=0 AND CY=0 THEN 10050
10070 SUBEND
10075 REM OBSTACLE DETECTION ROUTINE
10080 SUB DETECT(X,Y,CX,CY,R,RC,NX,NY)
10090 NX=X :: NY=Y :: SX=SGN(CX) :: SY=SGN(CY) :: AX=ABS(CX) :: AY=ABS(CY) :: R=0
10100 IF AX=0 THEN 10130
10110 AX=AX-1 :: IF SX=1 THEN NX=NX+1 ELSE NX=NX-1
10130 IF AY=0 THEN 10150
10140 AY=AY-1 :: IF SY=1 THEN NY=NY+1 ELSE NY=NY-1
10150 CALL GCHAR(NY,NX,RC)
10160 IF RC=32 OR RC=91 THEN 10170
10163 R=1::GOTO 10180
10170 IF AX>0 OR AY>0 THEN 10100
10180 SUBEND

More to come icon_smile.gif Edited by Vorticon

Thanks for pointing out that book! It sounds interesting, so I just bought a copy from Amazon.

 

I was interested in artificial life back in the 90s. I wrote a program called "critters" for the A8 back then that featured little critters that moved, fought, bred, ate, and died. There were also plants that were food for them. It would be neat to revisit the topic of a-life again.

 

Perhaps you can recreate that program for the TI? It sounds incredibly interesting!

Bought the book! I've been wanting to learn how to build seemingly complex behaviors in simple code. Book should be fun.

The book is really a good starting point for experimentation from a concepts standpoint. I've been having a lot of fun working with it. The code examples given are for the TRS-80 and Apple II computers, but the actual concepts are also well explained, making the task of implementation on the TI pretty straightforward. One of the issues I'm starting to encounter is the fact that with increasing behavioral complexity, I can never be too sure whether the program is misbehaving or the bugs are coming up with unexpected behavior :grin:

Is this a TAB book? I think I have it. I looked at a couple of the programs and wasn't impressed so it went on the shelf and I haven't seen it since.

I guess I didn't give it enough of a chance.

Yes it is, TAB# 1391. I had the same exact first impression, until I started thinking about the underlying concepts. But there is so much more to explore than what's in the book, and the fun is in thinking of new ways to expand on these :)

Perhaps you can recreate that program for the TI? It sounds incredibly interesting!

 

It was written in 6502 assembly, so it'd be tough to port it to another platform. :(

 

I like how your program is coming along!

I'll have to check it out. But this is the best article on PacMan I have ever read:

 

http://www.gamasutra...ier.php?print=1

 

Incredible. Apparently more work was put into this early title than I would have expected. Quite a lot of elements and tuning (up to level 21).

I guess it’s not impossible to recreate the look and feel of Pac-Man (Arcade), Adventure and Miniature Golf (both Atari 2600) on the 4A, - but to get it “right”, you almost have to disassemble and mimic the inner details.

Incredible. Apparently more work was put into this early title than I would have expected. Quite a lot of elements and tuning (up to level 21).

I guess it’s not impossible to recreate the look and feel of Pac-Man (Arcade), Adventure and Miniature Golf (both Atari 2600) on the 4A, - but to get it “right”, you almost have to disassemble and mimic the inner details.

 

That's what they did on the colecovision with the Pac-Man collection --> http://opcodegames.com/pacmancol_cv.htm

Edited by retroclouds

The amount of work that went into the early 80's arcade games is simply amazing. The fact that each ghost in PacMan has it *own* AI is just incredible, especially when you look at the system specs:

 

1MHz Z80

2K RAM (mostly screen memory)

30K-ish ROM (code AND graphics)

 

It always bugs me when people give the advice to aspiring game programmers that they should "start with a simple game like PacMan". Heh.

 

Hi guys! Interesting stuff. By the way, for a definitive look into the logic of Pac-Man, check out The Pac-Man Dossier, by Jamey Pittman.

 

Very accessible. Fascinating that such recognizably complex behaviour arises from some very simple rules.

 

dZ.

 

Edit: Oh! The Gamasutra article is the precursor to the Dossier. Good stuff!

And here's beta2, essentially beta with 2 bugs instead of 1. The bugs have flight behavior when confronted with the opposite bug or its trail. However, if a kill response is learned along a particular direction of motion, then the bugs will cross the opposite trail. Otherwise, it's the usual fight or flight response to obstacles. The same single key commands are available as in beta. Again, asynchronous multitasking is implemented for the bugs' behavior algorithms.

Interestingly, this version creates significant complexity, again far more than the simple rules imply. The bugs tend now to take much longer to fall into a stable pattern, and the pattern itself will -usually- tend to be more complex than the previous beta behavior. Furthermore, the bugs will tend to gravitate away from each other and will create wholly separate patterns even when trails are penetrated.

In the video below, you will see that each bug will roam over a wide area, but in the end the red bug will settle in a fairly complex track whereas the blue bug will settle into a very simple horizontal pattern despite having had greater mobility than its counterpart. And each bug will end up "owning" a corner as far away as possible from the other. Fascinating... Next iteration: predator and prey. This could get interesting :)

 

 

Here's the listing:

1 REM BETA2
5 CALL CLEAR :: RANDOMIZE
6 REM INITIALIZE VARIABLES
9 DIM MEM(2,4,4,2),PHASE(2),BUG(2),TRAIL(2),PX(2),PY(2),CX(2),CY(2),NX(2),NY(2),RC(2)
10 CALL CHAR(80,"0000001818000000",91,"0000001818000000",96,"FFFFFFFFFFFFFFFF",104,"007E7E7E7E7E7E00",112,"80433C3C3C7C8204",120,"80433C3C3C7C8204")
20 CALL COLOR(7,10,1,8,6,1,10,15,1,11,10,1,12,6,1)::CALL SCREEN(4)
21 GOSUB 8040
22 ID=1::PHASE(1)=1::PHASE(2)=1::BUG(1)=112::BUG(2)=120::TRAIL(1)=80::TRAIL(2)=91
30 REM  SET UP FIELD
40 CALL HCHAR(1,1,96,32) :: CALL VCHAR(2,1,96,23) :: CALL VCHAR(2,32,96,23) :: CALL HCHAR(24,2,96,30)
50 FOR I=1 TO 40 :: CALL PLACE(X,Y) :: CALL HCHAR(Y,X,104):: NEXT I
60 FOR I=1 TO 2::CALL PLACE(PX(I),PY(I))::CALL HCHAR(PY(I),PX(I),BUG(I))::NEXT I
70 FOR I=1 TO 2:: CALL MOVE(CX(I),CY(I))::NEXT I
200 REM BETA BEHAVIOR
210 ON PHASE(ID) GOTO 230, 260,350
220 REM PHASE 1 - PATH CLEAR
230 CALL DETECT(ID,PX(ID),PY(ID),CX(ID),CY(ID),R,RC(ID),NX(ID),NY(ID))
240 IF R=0 THEN GOSUB 8070::GOSUB 7830::GOSUB 7800::GOTO 210 ELSE PHASE(ID)=2::GOSUB 7800::GOTO 210 ! PATH CLEAR. KEEP MOVING
250 REM PHASE 2 - PATH BLOCKED. RESPONSE FOUND
260 MRX=CX(ID)+2::MRY=CY(ID)+2::MK=MEM(ID,MRX,MRY,0)::MX=MEM(ID,MRX,MRY,1)::MY=MEM(ID,MRX,MRY,2) ! PATH BLOCKED. CHECK MEMORY FOR RESPONSE
270 IF MX=5 OR MY=5 THEN GOSUB 8010::IF KL=1 THEN MEM(ID,MRX,MRY,0)=1::GOTO 290 ELSE PHASE(ID)=3::GOSUB 7830::GOSUB 7800::GOTO 210 ! NO CODE IN MEMORY. ATTEMPT KILL
280 IF MK<>1 OR (MK=1 AND (RC(ID)=96 OR RC(ID)=112 OR RC(ID)=120)) THEN 300 ELSE CALL SOUND(10,-5,15)::GOSUB 8070::GOSUB 7830::PHASE(ID)=1::GOSUB 7800::GOTO 210
290 MEM(ID,MRX,MRY,1)=CX(ID)::MEM(ID,MRX,MRY,2)=CY(ID)::GOSUB 8070::GOSUB 7830::PHASE(ID)=1::GOSUB 7800::GOTO 210 ! KILL RESPONSE FOUND
300 CALL DETECT(ID,PX(ID),PY(ID),MX,MY,R,RC(ID),NX(ID),NY(ID)) ! VALID MOTION CODE IN MEMORY. TEST CODE
310 IF R=0 THEN CX(ID)=MX::CY(ID)=MY::GOSUB 8070::GOSUB 7830::PHASE(ID)=1::GOSUB 7800::GOTO 210 ! PATH CLEAR. EXECUTE STORED MOVE
320 GOSUB 8010 ! PATH BLOCKED. TRY TO KILL OBSTACLE
330 IF KL=1 THEN MEM(ID,MRX,MRY,0)=1::CX(ID)=MX::CY(ID)=MY::GOSUB 8070::GOSUB 7830::PHASE(ID)=1::GOSUB 7800::GOTO 210 ELSE GOSUB 7830::PHASE(ID)=3::GOSUB 7800::GOTO 210
340 REM PHASE 3 - PATH BLOCKED. NO RESPONSE FOUND
350 CALL MOVE(CX(ID),CY(ID))
360 CALL DETECT(ID,PX(ID),PY(ID),CX(ID),CY(ID),R,RC(ID),NX(ID),NY(ID))
370 IF R=0 THEN MEM(ID,MRX,MRY,0)=0::MEM(ID,MRX,MRY,1)=CX(ID)::MEM(ID,MRX,MRY,2)=CY(ID)::GOSUB 8070::GOSUB 7830::PHASE(ID)=1::GOSUB 7800::GOTO 210
380 GOSUB 8010::IF KL=0 THEN 350
390 MEM(ID,MRX,MRY,0)=1::MEM(ID,MRX,MRY,1)=CX(ID)::MEM(ID,MRX,MRY,2)=CY(ID)::GOSUB 8070::GOSUB 7830::PHASE(ID)=1::GOSUB 7800::GOTO 210
7790 REM ID ROTATION ROUTINE
7800 IF ID=1 THEN ID=2 ELSE ID=1
7810 RETURN
7820 REM COMMAND TRAPPING ROUTINE
7830 CALL KEY(0,KY,S)
7840 IF KY<>67 AND KY<>99 THEN 7860 ! C PRESSED: CLEAR BUG MEMORY
7850 GOSUB 8040::RETURN
7860 IF KY<>70 AND KY<>102 THEN 7880 ! F PRESSED: FORCE NEW MOTION CODE
7870 CALL MOVE(NCX,NCY)::IF NCX=CX(ID) AND NCY=CY(ID) THEN 7870 ELSE CX(ID)=NCX::CY(ID)=NCY::RETURN
7880 IF KY<>68 AND KY<>100 THEN 7900 ! D PRESSED: DISPLACE BUG TO NEW LOCATION
7890 FOR I=1 TO 2::CALL HCHAR(PY(I),PX(I),32)::CALL PLACE(PX(I),PY(I))::CALL HCHAR(PY(I),PX(I),BUG(I))::NEXT I::RETURN
7900 IF KY<>71 AND KY<>103 THEN 7960 ! G PRESSED: GENERATE NEW FIELD
7910 CALL CLEAR::CALL HCHAR(1,1,96,32) :: CALL VCHAR(2,1,96,23) :: CALL VCHAR(2,32,96,23) :: CALL HCHAR(24,2,96,30)
7920 FOR I=1 TO 40
7930 CALL PLACE(X,Y)::IF (X=PX(1) AND Y=PY(1)) OR (X=PX(2) AND Y=PY(2)) THEN 7930
7940 CALL HCHAR(Y,X,104)::NEXT I
7950 FOR I=1 TO 2::CALL HCHAR(PY(I),PX(I),BUG(I))::NEXT I::RETURN
7960 IF KY<>84 AND KY<>116 THEN RETURN! T PRESSED: CLEAR BUG TRAIL
7970 FOR X=2 TO 31::FOR Y=2 TO 23::CALL GCHAR(Y,X,C)::IF C=80 OR C=91 THEN CALL HCHAR(Y,X,32)
7980 NEXT Y::NEXT X
7990 RETURN
8000 REM KILL DECISION ROUTINE
8010 KL=0::IF RC(ID)=96 OR RC(ID)=BUG(1) OR RC(ID)=BUG(2) THEN 8020
8015 IF(ID=1 AND RC(ID)=TRAIL(2)) OR (ID=2 AND RC(ID)=TRAIL(1)) THEN 8020
8016 KILL=INT(RND*10)+1::IF KILL>5 THEN CALL SOUND(10,-5,15)::KL=1
8020 RETURN
8030 REM CLEAR BUG MEMORY ROUTINE
8040 FOR H=1 TO 2:: FOR I=0 TO 4::FOR J=0 TO 4::FOR K=0 TO 2::MEM(H,I,J,K)=5::NEXT K::NEXT J::NEXT I::NEXT H
8050 RETURN
8060 REM DISPLAY BUG MOVEMENT ROUTINE
8070 CALL HCHAR(PY(ID),PX(ID),TRAIL(ID))::PX(ID)=NX(ID)::PY(ID)=NY(ID)::CALL HCHAR(PY(ID),PX(ID),BUG(ID))
8080 RETURN
9999 REM RANDOM OBJECT SCREEN PLACEMENT ROUTINE
10000 SUB PLACE(X,Y)
10010 X=INT(RND*30)+2 :: Y=INT(RND*21)+2
10020 CALL GCHAR(Y,X,C) :: IF C<>32 THEN 10010
10030 SUBEND
10035 REM RANDOM MOVEMENT GENERATION ROUTINE
10040 SUB MOVE(CX,CY)
10050 CX=INT(RND*3) :: DIR=INT(RND*10)+1 :: IF DIR>5 THEN CX=-CX
10060 CY=INT(RND*3) :: DIR=INT(RND*10)+1 :: IF DIR>5 THEN CY=-CY
10065 IF CX=0 AND CY=0 THEN 10050
10070 SUBEND
10075 REM OBSTACLE DETECTION ROUTINE
10080 SUB DETECT(ID,X,Y,CX,CY,R,RC,NX,NY)
10090 NX=X :: NY=Y :: SX=SGN(CX) :: SY=SGN(CY) :: AX=ABS(CX) :: AY=ABS(CY) :: R=0
10100 IF AX=0 THEN 10130
10110 AX=AX-1 :: IF SX=1 THEN NX=NX+1 ELSE NX=NX-1
10130 IF AY=0 THEN 10150
10140 AY=AY-1 :: IF SY=1 THEN NY=NY+1 ELSE NY=NY-1
10150 CALL GCHAR(NY,NX,RC)
10160 IF RC=32 OR (RC=91 AND ID=2) OR (RC=80 AND ID=1) THEN 10170
10163 R=1::GOTO 10180
10170 IF AX>0 OR AY>0 THEN 10100
10180 SUBEND

  • Like 1

If you like a little more structure in you XB programming, you can use the translator I wrote (http://codehackcreate.com/archives/237) to help keep the code more sane during development. I'm sure the forum will jack-up the formatting a little.

 

Input:

 

 

// BETA2
CALL CLEAR ::
RANDOMIZE

// INITIALIZE VARIABLES
DIM ..
 MEM(2,4,4,2),..
 PHASE(2),..
 BUG(2),..
 TRAIL(2),..
 PX(2),..
 PY(2),..
 CX(2),..
 CY(2),..
 NX(2),..
 NY(2),..
 RC(2)

CALL CHAR..
 (80,"0000001818000000"..
 ,91,"0000001818000000"..
 ,96,"FFFFFFFFFFFFFFFF"..
 ,104,"007E7E7E7E7E7E00"..
 ,112,"80433C3C3C7C8204"..
 ,120,"80433C3C3C7C8204")

CALL COLOR(7,10,1,8,6,1,10,15,1,11,10,1,12,6,1)::
CALL SCREEN(4)

GOSUB clear_bug_mem

ID=1::
PHASE(1)=1::
PHASE(2)=1::
BUG(1)=112::
BUG(2)=120::
TRAIL(1)=80::
TRAIL(2)=91

// SET UP FIELD
CALL HCHAR(1,1,96,32) ::
CALL VCHAR(2,1,96,23) ::
CALL VCHAR(2,32,96,23) ::
CALL HCHAR(24,2,96,30)

FOR I=1 TO 40 ::
 CALL PLACE(X,Y) ::
 CALL HCHAR(Y,X,104)::
NEXT I

FOR I=1 TO 2::
 CALL PLACE(PX(I),PY(I))::
 CALL HCHAR(PY(I),PX(I),BUG(I))::
NEXT I

FOR I=1 TO 2::
 CALL MOVE(CX(I),CY(I))::
NEXT I

// BETA BEHAVIOR
behavior_loop:
ON PHASE(ID) GOTO phase1, phase2, phase3

// PHASE 1 - PATH CLEAR
phase1:
 CALL DETECT(ID,PX(ID),PY(ID),CX(ID),CY(ID),R,RC(ID),NX(ID),NY(ID))
 IF R=0 THEN ..
   GOSUB display_bug_movement::
   GOSUB cmd_trapping::
   GOSUB id_rotation::
   GOTO behavior_loop ..
 ELSE ..
   PHASE(ID)=2::
   GOSUB id_rotation::
   GOTO behavior_loop ! PATH CLEAR. KEEP MOVING
 ENDIF


// PHASE 2 - PATH BLOCKED. RESPONSE FOUND
phase2:
 MRX=CX(ID)+2::
 MRY=CY(ID)+2::
 MK=MEM(ID,MRX,MRY,0)::
 MX=MEM(ID,MRX,MRY,1)::
 MY=MEM(ID,MRX,MRY,2) ! PATH BLOCKED. CHECK MEMORY FOR RESPONSE

 IF MX=5 OR MY=5 THEN ..
   GOSUB kill_decision::

   IF KL=1 THEN ..
     MEM(ID,MRX,MRY,0)=1::
     GOTO kill_response_found ..
   ELSE ..
     PHASE(ID)=3::
     GOSUB cmd_trapping::
     GOSUB id_rotation::
     GOTO behavior_loop ! NO CODE IN MEMORY. ATTEMPT KILL
   ENDIF
 ENDIF

 IF MK<>1 OR (MK=1 AND (RC(ID)=96 OR RC(ID)=112 OR RC(ID)=120)) THEN ..
   valid_motion ..
 ELSE ..
   CALL SOUND(10,-5,15)::
   GOSUB display_bug_movement::
   GOSUB cmd_trapping::
   PHASE(ID)=1::
   GOSUB id_rotation::
   GOTO behavior_loop
 ENDIF

 kill_response_found:
   MEM(ID,MRX,MRY,1)=CX(ID)::
   MEM(ID,MRX,MRY,2)=CY(ID)::
   GOSUB display_bug_movement::
   GOSUB cmd_trapping::
   PHASE(ID)=1::
   GOSUB id_rotation::
   GOTO behavior_loop ! KILL RESPONSE FOUND

 valid_motion:
   CALL DETECT(ID,PX(ID),PY(ID),MX,MY,R,RC(ID),NX(ID),NY(ID)) ! VALID MOTION CODE IN MEMORY. TEST CODE

   IF R=0 THEN ..
     CX(ID)=MX::
     CY(ID)=MY::
     GOSUB display_bug_movement::
     GOSUB cmd_trapping::
     PHASE(ID)=1::
     GOSUB id_rotation::
     GOTO behavior_loop ! PATH CLEAR. EXECUTE STORED MOVE
   ENDIF

 GOSUB kill_decision ! PATH BLOCKED. TRY TO KILL OBSTACLE

 IF KL=1 THEN ..
   MEM(ID,MRX,MRY,0)=1::
   CX(ID)=MX::
   CY(ID)=MY::
   GOSUB display_bug_movement::
   GOSUB cmd_trapping::
   PHASE(ID)=1::
   GOSUB id_rotation::
   GOTO behavior_loop ..
 ELSE ..
   GOSUB cmd_trapping::
   PHASE(ID)=3::
   GOSUB id_rotation::
   GOTO behavior_loop
 ENDIF


// PHASE 3 - PATH BLOCKED. NO RESPONSE FOUND
phase3:
 CALL MOVE(CX(ID),CY(ID))
 CALL DETECT(ID,PX(ID),PY(ID),CX(ID),CY(ID),R,RC(ID),NX(ID),NY(ID))

 IF R=0 THEN ..
   MEM(ID,MRX,MRY,0)=0::
   MEM(ID,MRX,MRY,1)=CX(ID)::
   MEM(ID,MRX,MRY,2)=CY(ID)::
   GOSUB display_bug_movement::
   GOSUB cmd_trapping::
   PHASE(ID)=1::
   GOSUB id_rotation::
   GOTO behavior_loop
 ENDIF

 GOSUB kill_decision::
 IF KL=0 THEN phase3

 MEM(ID,MRX,MRY,0)=1::
 MEM(ID,MRX,MRY,1)=CX(ID)::
 MEM(ID,MRX,MRY,2)=CY(ID)::
 GOSUB display_bug_movement::
 GOSUB cmd_trapping::
 PHASE(ID)=1::
 GOSUB id_rotation::
 GOTO behavior_loop

// END Behavior Loop


// ID ROTATION ROUTINE
id_rotation:
 IF ID=1 THEN ID=2 ELSE ID=1
RETURN


// COMMAND TRAPPING ROUTINE
cmd_trapping:
 CALL KEY(0,KY,S)
 IF KY<>67 AND KY<>99 THEN cmd_key_f ! C PRESSED: CLEAR BUG MEMORY

 GOSUB clear_bug_mem::
 RETURN

 cmd_key_f:
   IF KY<>70 AND KY<>102 THEN cmd_key_d ! F PRESSED: FORCE NEW MOTION CODE

 cmd_new_motion:
   CALL MOVE(NCX,NCY)::
   IF NCX=CX(ID) AND NCY=CY(ID) THEN ..
     cmd_new_motion ..
   ELSE ..
     CX(ID)=NCX::CY(ID)=NCY::
     RETURN
   ENDIF

 cmd_key_d:
   IF KY<>68 AND KY<>100 THEN cmd_key_g ! D PRESSED: DISPLACE BUG TO NEW LOCATION

   FOR I=1 TO 2::
     CALL HCHAR(PY(I),PX(I),32)::
     CALL PLACE(PX(I),PY(I))::
     CALL HCHAR(PY(I),PX(I),BUG(I))::
   NEXT I::

   RETURN

 cmd_key_g:
   IF KY<>71 AND KY<>103 THEN cmd_key_t ! G PRESSED: GENERATE NEW FIELD

   CALL CLEAR::
   CALL HCHAR(1,1,96,32) ::
   CALL VCHAR(2,1,96,23) ::
   CALL VCHAR(2,32,96,23) ::
   CALL HCHAR(24,2,96,30)

   FOR I=1 TO 40
     cmd_place_loop:
       CALL PLACE(X,Y)::
       IF (X=PX(1) AND Y=PY(1)) OR (X=PX(2) AND Y=PY(2)) THEN cmd_place_loop
       CALL HCHAR(Y,X,104)::
   NEXT I

   FOR I=1 TO 2::
     CALL HCHAR(PY(I),PX(I),BUG(I))::
   NEXT I::

   RETURN

 cmd_key_t:
   IF KY<>84 AND KY<>116 THEN RETURN ! T PRESSED: CLEAR BUG TRAIL

   FOR X=2 TO 31::
     FOR Y=2 TO 23::
       CALL GCHAR(Y,X,C)::
       IF C=80 OR C=91 THEN CALL HCHAR(Y,X,32)
     NEXT Y::
   NEXT X

RETURN


// KILL DECISION ROUTINE
kill_decision:
 KL=0::
 IF RC(ID)=96 OR RC(ID)=BUG(1) OR RC(ID)=BUG(2) THEN kill_done
 IF(ID=1 AND RC(ID)=TRAIL(2)) OR (ID=2 AND RC(ID)=TRAIL(1)) THEN kill_done

 KILL=INT(RND*10)+1::
 IF KILL>5 THEN ..
   CALL SOUND(10,-5,15)::
   KL=1
 ENDIF

kill_done:
RETURN


// CLEAR BUG MEMORY ROUTINE
clear_bug_mem:
 FOR H=1 TO 2::
   FOR I=0 TO 4::
     FOR J=0 TO 4::
       FOR K=0 TO 2::
         MEM(H,I,J,K)=5::
       NEXT K::
     NEXT J::
   NEXT I::
 NEXT H
RETURN


// DISPLAY BUG MOVEMENT ROUTINE
display_bug_movement:
 CALL HCHAR(PY(ID),PX(ID),TRAIL(ID))::
 PX(ID)=NX(ID)::
 PY(ID)=NY(ID)::
 CALL HCHAR(PY(ID),PX(ID),BUG(ID))
RETURN

// RANDOM OBJECT SCREEN PLACEMENT ROUTINE
SUB PLACE(X,Y)
 sub_place_loop:
   X=INT(RND*30)+2 ::
   Y=INT(RND*21)+2
   CALL GCHAR(Y,X,C) ::
   IF C<>32 THEN sub_place_loop
SUBEND


// RANDOM MOVEMENT GENERATION ROUTINE
SUB MOVE(CX,CY)
 sub_move_loop:

   CX=INT(RND*3) ::
   DIR=INT(RND*10)+1 ::
   IF DIR>5 THEN CX=-CX

   CY=INT(RND*3) ::
   DIR=INT(RND*10)+1 ::
   IF DIR>5 THEN CY=-CY

   IF CX=0 AND CY=0 THEN sub_move_loop
SUBEND

// OBSTACLE DETECTION ROUTINE
SUB DETECT(ID,X,Y,CX,CY,R,RC,NX,NY)

 NX=X ::
 NY=Y ::
 SX=SGN(CX) ::
 SY=SGN(CY) ::
 AX=ABS(CX) ::
 AY=ABS(CY) ::
 R=0

 sub_detect_loop:
   IF AX=0 THEN sub_detect_j1

   AX=AX-1 ::
   IF SX=1 THEN NX=NX+1 ELSE NX=NX-1

 sub_detect_j1:
   IF AY=0 THEN sub_detect_j2

   AY=AY-1 ::
   IF SY=1 THEN NY=NY+1 ELSE NY=NY-1

 sub_detect_j2:
   CALL GCHAR(NY,NX,RC)

   IF RC=32 OR (RC=91 AND ID=2) OR (RC=80 AND ID=1) THEN sub_detect_j3

   R=1::
   GOTO sub_detect_end

 sub_detect_j3:
   IF AX>0 OR AY>0 THEN sub_detect_loop

 sub_detect_end:
SUBEND

 

 

 

Output:

 

 

100 CALL CLEAR :: RANDOMIZE
110 DIM MEM(2,4,4,2),PHASE(2),BUG(2),TRAIL(2),PX(2),PY(2),CX(2),CY(2),NX(2),NY(2),RC(2)
120 CALL CHAR(80,"0000001818000000",91,"0000001818000000",96,"FFFFFFFFFFFFFFFF",104,"007E7E7E7E7E7E00",112,"80433C3C3C7C8204",120,"80433C3C3C7C8204")
130 CALL COLOR(7,10,1,8,6,1,10,15,1,11,10,1,12,6,1):: CALL SCREEN(4)
140 GOSUB 590
150 ID=1:: PHASE(1)=1:: PHASE(2)=1:: BUG(1)=112:: BUG(2)=120:: TRAIL(1)=80:: TRAIL(2)=91
160 CALL HCHAR(1,1,96,32) :: CALL VCHAR(2,1,96,23) :: CALL VCHAR(2,32,96,23) :: CALL HCHAR(24,2,96,30)
170 FOR I=1 TO 40 :: CALL PLACE(X,Y) :: CALL HCHAR(Y,X,104):: NEXT I
180 FOR I=1 TO 2:: CALL PLACE(PX(I),PY(I)):: CALL HCHAR(PY(I),PX(I),BUG(I)):: NEXT I
190 FOR I=1 TO 2:: CALL MOVE(CX(I),CY(I)):: NEXT I
200 ON PHASE(ID) GOTO 210,230,310
210 CALL DETECT(ID,PX(ID),PY(ID),CX(ID),CY(ID),R,RC(ID),NX(ID),NY(ID))
220 IF R=0 THEN GOSUB 610:: GOSUB 380:: GOSUB 360:: GOTO 200 ELSE PHASE(ID)=2:: GOSUB 360:: GOTO 200 ! PATH CLEAR. KEEP MOVING
230 MRX=CX(ID)+2:: MRY=CY(ID)+2:: MK=MEM(ID,MRX,MRY,0):: MX=MEM(ID,MRX,MRY,1):: MY=MEM(ID,MRX,MRY,2) ! PATH BLOCKED. CHECK MEMORY FOR RESPONSE
240 IF MX=5 OR MY=5 THEN GOSUB 550:: IF KL=1 THEN MEM(ID,MRX,MRY,0)=1:: GOTO 260 ELSE PHASE(ID)=3:: GOSUB 380:: GOSUB 360:: GOTO 200 ! NO CODE IN MEMORY. ATTEMPT KILL
250 IF MK<>1 OR (MK=1 AND (RC(ID)=96 OR RC(ID)=112 OR RC(ID)=120)) THEN 270 ELSE CALL SOUND(10,-5,15):: GOSUB 610:: GOSUB 380:: PHASE(ID)=1:: GOSUB 360:: GOTO 200
260 MEM(ID,MRX,MRY,1)=CX(ID):: MEM(ID,MRX,MRY,2)=CY(ID):: GOSUB 610:: GOSUB 380:: PHASE(ID)=1:: GOSUB 360:: GOTO 200 ! KILL RESPONSE FOUND
270 CALL DETECT(ID,PX(ID),PY(ID),MX,MY,R,RC(ID),NX(ID),NY(ID)) ! VALID MOTION CODE IN MEMORY. TEST CODE
280 IF R=0 THEN CX(ID)=MX:: CY(ID)=MY:: GOSUB 610:: GOSUB 380:: PHASE(ID)=1:: GOSUB 360:: GOTO 200 ! PATH CLEAR. EXECUTE STORED MOVE
290 GOSUB 550 ! PATH BLOCKED. TRY TO KILL OBSTACLE
300 IF KL=1 THEN MEM(ID,MRX,MRY,0)=1:: CX(ID)=MX:: CY(ID)=MY:: GOSUB 610:: GOSUB 380:: PHASE(ID)=1:: GOSUB 360:: GOTO 200 ELSE GOSUB 380:: PHASE(ID)=3:: GOSUB 360:: GOTO 200
310 CALL MOVE(CX(ID),CY(ID))
320 CALL DETECT(ID,PX(ID),PY(ID),CX(ID),CY(ID),R,RC(ID),NX(ID),NY(ID))
330 IF R=0 THEN MEM(ID,MRX,MRY,0)=0:: MEM(ID,MRX,MRY,1)=CX(ID):: MEM(ID,MRX,MRY,2)=CY(ID):: GOSUB 610:: GOSUB 380:: PHASE(ID)=1:: GOSUB 360:: GOTO 200
340 GOSUB 550:: IF KL=0 THEN 310
350 MEM(ID,MRX,MRY,0)=1:: MEM(ID,MRX,MRY,1)=CX(ID):: MEM(ID,MRX,MRY,2)=CY(ID):: GOSUB 610:: GOSUB 380:: PHASE(ID)=1:: GOSUB 360:: GOTO 200
360 IF ID=1 THEN ID=2 ELSE ID=1
370 RETURN
380 CALL KEY(0,KY,S)
390 IF KY<>67 AND KY<>99 THEN 410 ! C PRESSED: CLEAR BUG MEMORY
400 GOSUB 590:: RETURN
410 IF KY<>70 AND KY<>102 THEN 430 ! F PRESSED: FORCE NEW MOTION CODE
420 CALL MOVE(NCX,NCY):: IF NCX=CX(ID) AND NCY=CY(ID) THEN 420 ELSE CX(ID)=NCX::CY(ID)=NCY:: RETURN
430 IF KY<>68 AND KY<>100 THEN 450 ! D PRESSED: DISPLACE BUG TO NEW LOCATION
440 FOR I=1 TO 2:: CALL HCHAR(PY(I),PX(I),32):: CALL PLACE(PX(I),PY(I)):: CALL HCHAR(PY(I),PX(I),BUG(I)):: NEXT I:: RETURN
450 IF KY<>71 AND KY<>103 THEN 510 ! G PRESSED: GENERATE NEW FIELD
460 CALL CLEAR:: CALL HCHAR(1,1,96,32) :: CALL VCHAR(2,1,96,23) :: CALL VCHAR(2,32,96,23) :: CALL HCHAR(24,2,96,30)
470 FOR I=1 TO 40
480 CALL PLACE(X,Y):: IF (X=PX(1) AND Y=PY(1)) OR (X=PX(2) AND Y=PY(2)) THEN 480
490 CALL HCHAR(Y,X,104):: NEXT I
500 FOR I=1 TO 2:: CALL HCHAR(PY(I),PX(I),BUG(I)):: NEXT I:: RETURN
510 IF KY<>84 AND KY<>116 THEN RETURN ! T PRESSED: CLEAR BUG TRAIL
520 FOR X=2 TO 31:: FOR Y=2 TO 23:: CALL GCHAR(Y,X,C):: IF C=80 OR C=91 THEN CALL HCHAR(Y,X,32)
530 NEXT Y:: NEXT X
540 RETURN
550 KL=0:: IF RC(ID)=96 OR RC(ID)=BUG(1) OR RC(ID)=BUG(2) THEN 580
560 IF(ID=1 AND RC(ID)=TRAIL(2)) OR (ID=2 AND RC(ID)=TRAIL(1)) THEN 580
570 KILL=INT(RND*10)+1:: IF KILL>5 THEN CALL SOUND(10,-5,15):: KL=1
580 RETURN
590 FOR H=1 TO 2:: FOR I=0 TO 4:: FOR J=0 TO 4:: FOR K=0 TO 2:: MEM(H,I,J,K)=5:: NEXT K:: NEXT J:: NEXT I:: NEXT H
600 RETURN
610 CALL HCHAR(PY(ID),PX(ID),TRAIL(ID)):: PX(ID)=NX(ID):: PY(ID)=NY(ID):: CALL HCHAR(PY(ID),PX(ID),BUG(ID))
620 RETURN
630 SUB PLACE(X,Y)
640 X=INT(RND*30)+2 :: Y=INT(RND*21)+2
650 CALL GCHAR(Y,X,C) :: IF C<>32 THEN 640
660 SUBEND
670 SUB MOVE(CX,CY)
680 CX=INT(RND*3) :: DIR=INT(RND*10)+1 :: IF DIR>5 THEN CX=-CX
690 CY=INT(RND*3) :: DIR=INT(RND*10)+1 :: IF DIR>5 THEN CY=-CY
700 IF CX=0 AND CY=0 THEN 680
710 SUBEND
720 SUB DETECT(ID,X,Y,CX,CY,R,RC,NX,NY)
730 NX=X :: NY=Y :: SX=SGN(CX) :: SY=SGN(CY) :: AX=ABS(CX) :: AY=ABS(CY) :: R=0
740 IF AX=0 THEN 760
750 AX=AX-1 :: IF SX=1 THEN NX=NX+1 ELSE NX=NX-1
760 IF AY=0 THEN 780
770 AY=AY-1 :: IF SY=1 THEN NY=NY+1 ELSE NY=NY-1
780 CALL GCHAR(NY,NX,RC)
790 IF RC=32 OR (RC=91 AND ID=2) OR (RC=80 AND ID=1) THEN 810
800 R=1:: GOTO 820
810 IF AX>0 OR AY>0 THEN 740
820 SUBEND

 

 

  • Like 1

At what point is a structure considered alive? Are my bugs alive? Granted, they are pretty dumb still, and this will be changing in the near future, but is their behavior that much different from say an earthworm? An earthworm is definitely alive by anybody's reckoning. If I added a simple hermaphroditic reproductive system based on energy supply to the bugs along with basic food seeking behavior, will they reach the life threshold?

I know this is rather "deep" and likely outside the scope of this forum, but then, any programmer will eventually have to face these questions as programs acquire increasing levels of complexity...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...