size : 6940
uploaded_on : Sat Jun 20 00:00:00 1998
modified_on : Wed Dec 8 14:03:35 1999
title : AI: find a way
org_filename : ai_way.pas
author : Wonderboy
authoremail : Page_Wonderboy@hotmail.com
description : A basic form of AI
keywords :
tested : Borland Pascal 7.0
submitted_by : The CKB Crew
submitted_by_email : ckb@netalive.org
uploaded_by : nobody
modified_by : nobody
owner : nobody
lang : pas
file-type : text/plain
category : pascal-alg-maths
__END_OF_HEADER__
{$A+,B-,D-,E-,F-,G+,I+,L-,N+,O-,P-,Q-,R-,S+,T-,V+,X+,Y-}
{This programs shows you how the computer can find the shortest way from one point to
another.
Explantion: create a matrix and choose a starting point:
|--|--|--|
| S| | |
|--|--|--|
| | | |
|--|--|--|
| | | F|
|--|--|--|
Fill every free coordinate with the value -1 and every unpassable coordinate
with the value -2. Give the finish a value 0. The value 0 means:
the distance from that coordinate to the finish is 0.
|--|--|--|
| S|-1|-1|
|--|--|--|
|-1|-2|-1|
|--|--|--|
|-2|-1| 0|
|--|--|--|
Now start from the Finish coordinates and fill in the distances from each coordinate
to the finish:
|--|--|--| |--|--|--| |--|--|--| |--|--|--|
| S|-1|-1| | S|-1| 2| | S| 3| 2| | 4| 3| 2|
|--|--|--| |--|--|--| |--|--|--| |--|--|--|
|-1|-2| 1| -> |-1|-2| 1| -> |-1|-2| 1| -> |-1|-2| 1|
|--|--|--| |--|--|--| |--|--|--| |--|--|--|
|-2| 1| 0| |-2| 1| 0| |-2| 1| 0| |-2| 1| 0|
|--|--|--| |--|--|--| |--|--|--| |--|--|--|
The start coordinate has a value 4, which means the shortest way the the finish
is 4. You can now trace the shortest way from start to finish:
|--|--|--|
| X| X| X|
|--|--|--|
|-1|-2| X|
|--|--|--|
|-2| 1| X|
|--|--|--|
The following example program only looks left, up, right and down for the
shortest way form start to finish}
Program AI_Find_A_Way;
Uses Graph, Crt, Dos;
Const MatrixMinX = 1; {Do not change}
MatrixMinY = 1; {Do not change}
MatrixMaxX = 128; {Matrix size}
MatrixMaxY = 128; {Matrix size}
MaxWay = 500; {Maximum length of the way to find}
Type PointType = Record {Record to store coordinates}
x,y:Byte;
End;
ToDoType = Record
T: Array[1..1000] Of PointType; {1000 is just a value, which should be enough}
End;
Var Graphix :Integer;
PlayField :Array[1..MatrixMaxX] Of Array[1..MatrixMaxY] Of Integer;
ToDoNow, ToDoNextTurn :^ToDoType; {The coordinates to check}
NumberToDoNow,
NumberToDoNextTurn :Integer; {Number of coordinates to check}
tx,ty :Integer;
Start,Finish :PointType;
CurValue :Integer; {The value or distance to fill the next coordinates with}
Procedure CreateMatrix;
Begin
Start.x:=1; {Start coordinate}
Start.y:=1; {Start coordinate}
Finish.x:=MatrixMaxX; {Finish coordinate}
Finish.y:=MatrixMaxY; {Finish coordinate}
Randomize;
For tx:=1 To MatrixMaxX Do {Value -2 is an unpassable coordinate, -1 is an empty coordinate}
For ty:=1 To MatrixMaxY Do
Case Random(8) Of
0: Begin PlayField[tx,ty]:=-2; PutPixel(tx, ty, Red); End;
Else PlayField[tx,ty]:=-1
End;
PlayField[Start.x,Start.y]:=-1; {Ensure the Start coordinates have value -1}
PlayField[Finish.x,Finish.y]:=0; {The distance from the finish coordinates
to the finish is 0}
End;
Procedure FindWay(n:Integer);
Var FoundMyWay:Boolean;
Procedure Check(cx,cy,cn:Integer);
Procedure FillUnder(fx,fy,fn:Integer);
Begin
PlayField[fx,fy]:=fn; {Give a coordinate a distance to to finish}
Inc(NumberToDoNextTurn, 1); {Check in the next Check 1 Coordinate more}
ToDoNextTurn^.T[NumberToDoNextTurn].x:=fx; {Store the coordinate for a next check}
ToDoNextTurn^.T[NumberToDoNextTurn].y:=fy; {Store the coordinate for a next check}
End; {EndFillUnder}
Begin
If (cx > 1) And (PlayField[cx-1,cy]=-1) Then FillUnder(cx-1,cy,cn); {Check left}
If (cy > 1) And (PlayField[cx,cy-1]=-1) Then FillUnder(cx,cy-1,cn); {Check up}
If (cx < MatrixMaxX) And (PlayField[cx+1,cy]=-1) Then FillUnder(cx+1,cy,cn); {Check right}
If (cy < MatrixMaxY) And (PlayField[cx,cy+1]=-1) Then FillUnder(cx,cy+1,cn); {Check down}
End; {End Check}
Begin
FoundMyWay:=False;
NumberToDoNow:=NumberToDoNextTurn;
NumberToDoNextTurn:=0;
Move(ToDoNextTurn^, ToDoNow^, SizeOf(ToDoType)); {Finished checking all the coordinates this
turn. Move all the coordinates to check next
turn to the pointer to check now.
To speed up the process a lot,
use a faster move procedure!}
For tx:=1 To NumberToDoNow Do
Check(ToDoNow^.T[tx].x,ToDoNow^.T[tx].y,n+1);
If n > MaxWay Then Begin Write(#7); Halt; End; {Can't get there in #MaxWay moves!}
If PlayField[Start.x,Start.y]<>-1 Then FoundMyWay:=True; {If the record Start contains
a value other than -1, than
the value it contains is the
shortest way to the finish}
If FoundMyWay=False Then FindWay(n+1);
End; {End FindWay}
Procedure DisplayWay(VanX, VanY, NaarX, NaarY: Integer);
Begin
If Not ((VanX=NaarX) And (VanY=NaarY)) Then
Begin
NumberToDoNextTurn:=1;
ToDoNextTurn^.T[NumberToDoNextTurn].x:=Finish.x;
ToDoNextTurn^.T[NumberToDoNextTurn].y:=Finish.y;
FindWay(0); {Start filling the field with the distances
for the shortests way to to the finish}
CurValue:=PlayField[Start.x,Start.y];
tx:=Start.x;
ty:=Start.y;
Repeat {Check left, up, right and down for the shortest distance to the finish and move to
that position until you have reached the finish}
If (tx > 1) And (PlayField[tx-1,ty]=CurWaarde-1) And (PlayField[tx-1,ty]>-1) Then
Begin tx:=tx-1; PutPixel(tx, ty, Yellow); Dec(CurWaarde) End
Else If (ty > 1) And (PlayField[tx,ty-1]=CurWaarde-1) And (PlayField[tx,ty-1]>-1) Then
Begin ty:=ty-1; PutPixel(tx, ty, Yellow); Dec(CurWaarde) End
Else If (tx < MatrixMaxX) And (PlayField[tx+1,ty]=CurWaarde-1) And (PlayField[tx+1,ty]>-1) Then
Begin tx:=tx+1; PutPixel(tx, ty, Yellow); Dec(CurWaarde) End
Else If (ty < MatrixMaxY) And (PlayField[tx,ty+1]=CurWaarde-1) And (PlayField[tx,ty+1]>-1) Then
Begin ty:=ty+1; PutPixel(tx, ty, Yellow); Dec(CurWaarde) End;
Until (tx=Finish.x) And (ty=Finish.y); {Reached the Finish!}
End;
End; {End