Difference between revisions of "Tutorial Project. Release 3"
From wiki.visual-prolog.com
m |
m |
||
Line 28: | Line 28: | ||
<vip> | <vip> | ||
/***************************************************************************** | /***************************************************************************** | ||
Written by Victor Yukhtenko | |||
SpbSolutions/Examples/Polyline | SpbSolutions/Examples/Polyline |
Revision as of 14:36, 1 April 2011
Written by Victor Yukhtenko. Email: victor@pdc.spb.su
The programs listed below are part of the Evolutions Tutorial Project article.
Goal
To demonstrate the features of the Visual Prolog programming language and system features:
- data exchange principles in classes and objects;
- advanced exception handling.
Functionality
- the size of the field is 6x6 cells;
- it may be more then two players;
- the type of each player (human of computer) may be chosen;
- the move may be very unfortunate if the computer can not find the successful move.
Code
- Tested with Visual Prolog 7.3 build 7302.
- Each Class plays the special role, like:
- game – is the main application monitor;
- human – the model of the player-human;
- computer - the model of the player-computer;
- seniourJudge – the Senior Judge, give the permission to the next player to make the move, waits the information regarding the end of the game and announces the winner;
- juniourJudge – the Junior Judge, receives the move from the player, checks the validation of the moves, fixes the move of the player, which wins;
- humanInterface – represents the information regarding the game flow to the observer and interprets the observer’s activities;
- Due to an inefficient algorithm for the computer game field size more than 36 cells (6x6, for example) to install not recommended.
Install
To get the full set of projects of the series of the Polyline projects, please download archives using links at PDC forum:
- VipSpbSDK_PE_73_Examples_Polyline_1_14.zip
- VipSpbSDK_PE_73_Tools_Polyline_1_14.zip]
to any convenient directory. The directory named VipSpbSDK will be created automatically.
If you have the VipSpbSDK installed, then please open project Examples\Polyline\Polyline3\Polyline3.prj.
If you do not have the full set of examples from the VipSpbSDK, then please do as follows:
- Create the new project using the interface strategy console
- Build the project
- Replace the content of the file "main.pro" by the code proposed below.
- Build the project again. While building the project please respond “Add All”, when there will be the proposal to include additional packages to the project.
Run
Run the application using the “E” of the IDE or run the executable at the directory EXE.
/***************************************************************************** Written by Victor Yukhtenko SpbSolutions/Examples/Polyline Predicates, which represent the strategy neighbour_nd, neighbourOutOfPolyLine_nd, resolveStep, successfulStep, stepCandidate based on solutions proposed by Elena Efimova ********************************************/ goal mainExe::run(main::run). /************ Class Main ************/ implement main open core constants className = "main". classVersion = "1.0". clauses classInfo(className, classVersion). clauses run():- console::init(), game::run(). end implement main class game open core predicates classInfo : core::classInfo. predicates run:(). end class game implement game open core constants className = "game". classVersion = "1.0". clauses classInfo(className, classVersion). class facts playerNo_V:positive:=1. clauses run():- humanInterface::announceStartUp(), PlayerType=humanInterface::getInput(humanInterface::playerType_S,toString(playerNo_V)), not(PlayerType=""), try Player=createPlayerObject(toTerm(PlayerType)), seniourJudge::addPlayer(Player), playerNo_V:=playerNo_V+1 catch _TraceID do humanInterface::announceManagerError(humanInterface::errorPlayerType_S) end try, !, run(). run():- startingPlayer(). class predicates playListMember:()->string nondeterm. clauses playListMember()=PlayersListMember:- I = std::fromTo(1, list::length(seniourJudge::players_V)), Player=list::nth(I-1,seniourJudge::players_V), PlayersListMember=string::format("\n% - %",I,Player:name). class predicates startingPlayer:(). clauses startingPlayer():- not(seniourJudge::players_V=[]) and not(seniourJudge::players_V=[_SiglePlayer]), findAll(PlayListMember,PlayListMember=playListMember(),PlayList), PlayListStr=string::concatList(PlayList), StartingPlayerStr=humanInterface::getInput(humanInterface::startingPlayer_S,PlayListStr), not(StartingPlayerStr=""), try StartingPlayer=toTerm(StartingPlayerStr), !, startGame(StartingPlayer) catch _TraceID1 do humanInterface::announceManagerError(humanInterface::errorMustBeNumber_S), !, startingPlayer() end try. startingPlayer(). class predicates startGame:(positive). clauses startGame(StartingPlayer):- try Player=list::nth(StartingPlayer-1,seniourJudge::players_V), % list::nth(...) needs unsigned !, seniourJudge::play(Player) catch _Trace_D do humanInterface::announceManagerError(humanInterface::errorStartingPlayer_S), ! end try, !, startingPlayer(). class predicates createPlayerObject:(positive)->player. clauses createPlayerObject(1)=Player:- !, Player=human::new(). createPlayerObject(2)=Player:- !, Player=computer::new(). createPlayerObject(_)=_Player:- exception::raise(classInfo,wrongInputException,[]). class predicates wrongInputException:exception. clauses wrongInputException ( classInfo, predicate_Name(), "" ). end implement game /************************ Class seniorJudge ************************/ class seniourJudge open core properties players_V:player*. inProgress_V:boolean. predicates play:(player CurrentPlayer). addPlayer:(player NextPlayer). end class seniourJudge implement seniourJudge open core, humanInterface class facts players_V:player*:=[]. inProgress_V:boolean:=false. clauses play(Player):- inProgress_V=false, humanInterface::showStage(), inProgress_V:=true, Player:move(), humanInterface::announceStarter(Player:name), play(Player), !. play(Player):- juniourJudge::isGameOver(), !, Player:announceWin(), foreach (Participant=list::getMember_nd(players_V) and not(Participant=Player)) do Participant:announceLoss() end foreach, inProgress_V:=false, juniourJudge::reset(). play(Player):- NextPlayer=nextPlayer(Player), NextPlayer:move(), !, play(NextPlayer). clauses addPlayer(NextPlayer):- players_V:=list::append(players_V,[NextPlayer]). class predicates nextPlayer:(player CurrentPlayer)->player NextPlayer. clauses nextPlayer(Player)=NextPlayer:- Index=list::tryGetIndex(Player,players_V), NextPlayer=list::tryGetNth(Index+1,players_V), !. nextPlayer(_Player)=list::nth(0,players_V). end implement seniourJudge /************************ Class juniourJudge ************************/ class juniourJudge open core predicates classInfo : core::classInfo. domains cell = c(positive,positive). stepType_D= ordinary_S; winner_S. properties maxRow_P:positive. maxColumn_P:positive. polyline_P:cell*. predicates neighbour_nd: (cell,cell) nondeterm (i,o) (i,i). neighbourOutOfPolyLine_nd:(cell,cell)->cell nondeterm. set: (string ). isGameOver:() determ. reset:(). end class juniourJudge implement juniourJudge open core, humanInterface constants className = "JuniourJudge". classVersion = "1.0". clauses classInfo(className, classVersion). class facts maxRow_P:positive:=6. maxColumn_P:positive:=6. polyline_P:cell*:=[]. endOfGame_V:boolean:=false. clauses isGameOver():- endOfGame_V=true. clauses set(InputString):- Cell=toTerm(InputString), handleInput (Cell). clauses reset():- juniourJudge:: polyline_P:=[], juniourJudge::endOfGame_V:=false. class predicates handleInput:(juniourJudge::cell). clauses handleInput(Cell):- list::isMember(Cell,polyline_P), try _=makePolyLine(Cell,polyline_P) % it will be an exception if wrong Cell, but we ignore it by failing catch _TraceID do fail end try, !, endOfGame_V:=true, humanInterface::showStep(Cell,winner_S). handleInput (Cell):- polyline_P:=makePolyLine(Cell,polyline_P), !, humanInterface::showStep(Cell,ordinary_S). class predicates makePolyLine: (cell,cell*)-> cell* multi. clauses makePolyLine(c(X,Y),[])=[c(X,Y)]:- X>0,X<=maxColumn_P, Y>0,Y<=maxRow_P, !. makePolyLine(NewCell,[SingleCell])=[NewCell,SingleCell]:- neighbour_nd(SingleCell, NewCell), !. makePolyLine(NewCell,[Left, RestrictingCell | PolyLineTail])=[NewCell, Left, RestrictingCell | PolyLineTail]:- NewCell=neighbourOutOfPolyLine_nd(Left,RestrictingCell). makePolyLine(NewCell,PolyLine)=list::reverse([NewCell,Left, RestrictingCell | PolyLineTail]):- [Left, RestrictingCell | PolyLineTail]= list::reverse(PolyLine), NewCell=neighbourOutOfPolyLine_nd(Left,RestrictingCell). makePolyLine(NewCell,_PolyLine)= _PolyLine1:- exception::raise(classInfo,wrongStepException,[namedValue("data",string(toString(NewCell)))]). class predicates wrongStepException:exception. clauses wrongStepException ( classInfo, predicate_Name(), "the point % can not prolong the polyline!" ). clauses neighbourOutOfPolyLine_nd(Cell,RestrictingCell)=NewCell:- neighbour_nd(Cell,NewCell), not(NewCell = RestrictingCell). clauses neighbour_nd(c(X, Y), c(X + 1, Y)):- X < maxColumn_P. neighbour_nd(c(X, Y), c(X, Y + 1)):- Y < maxrow_P. neighbour_nd(c(X, Y), c(X - 1, Y)):- X > 1. neighbour_nd(c(X, Y), c(X, Y - 1)):- Y > 1. end implement juniourJudge /****************************************** Interface Player ******************************************/ interface player predicates move:(). announceWin:(). announceLoss:(). properties name:string. end interface player /****************************************** Class human ******************************************/ class human:player open core end class human implement human open core facts name:string:=string::format("Hum_%",toString(This)). clauses new():- Name=humanInterface::getInput(humanInterface::playerName_S,name), if not(Name="") then name:=Name end if. clauses move():- InputString=humanInterface::getInput(humanInterface::playerStep_S), try juniourJudge::set(InputString) catch TraceID do handleException(TraceID), fail end try, !. move():- move(). clauses announceWin():- humanInterface::announceWin(name). announceLoss():- humanInterface::announceLoss(name). class predicates handleException:(exception::traceId TraceID). clauses handleException(TraceID):- foreach Descriptor=exception::getDescriptor_nd(TraceID) do Descriptor = exception::descriptor( _ClassInfo1, exception::exceptionDescriptor(_ClassInfo2,_PredicateName,Description), _Kind, ExtraInfo, _GMTTime, _ExceptionDescription, _ThreadId), if ExtraInfo=[namedValue("data",string(CellPointer))] then ErrorMsg=string::format(Description,CellPointer), humanInterface::announceError(ErrorMsg) else humanInterface::announceError("") end if end foreach. end implement human /****************************************** Class computer ******************************************/ class computer:player open core end class computer implement computer open core facts name:string:=string::format("Cmp_%",toString(This)). clauses new():- Name=humanInterface::getInput(humanInterface::playerName_S,name), if not(Name="") then name:=Name end if. clauses move():- humanInterface::announceThinker(name), Cell=resolveStep(), juniourJudge::set(toString(Cell)). predicates resolveStep:()->juniourJudge::cell. clauses resolveStep()=Cell:- Cell=successfulStep(juniourJudge::polyline_P), !. resolveStep()=Cell:- stepCandidate(juniourJudge::polyline_P,_PolyLine,Cell), !. resolveStep()=juniourJudge::c(X+1,Y+1):- X=math::random(juniourJudge::maxColumn_P-1), Y=math::random(juniourJudge::maxRow_P-1). class predicates successfulStep: (juniourJudge::cell*)->juniourJudge::cell nondeterm. clauses successfulStep(PolyLine)=Cell:- stepCandidate(PolyLine,_PolyLine1,Cell), list::isMember(Cell, PolyLine), !. successfulStep(PolyLine)=Cell:- stepCandidate(PolyLine, PolyLine1, Cell), not(_=successfulStep(PolyLine1)). class predicates stepCandidate: (juniourJudge::cell*,juniourJudge::cell* [out],juniourJudge::cell [out]) nondeterm. clauses stepCandidate([Cell],[Cell,NewCell], NewCell):- juniourJudge::neighbour_nd(Cell, NewCell). stepCandidate([Left, RestrictingCell | PolyLine],[NewCell,Left, RestrictingCell| PolyLine], NewCell):- NewCell=juniourJudge::neighbourOutOfPolyLine_nd(Left,RestrictingCell). stepCandidate(PolyLine,list::reverse([NewCell,Left, RestrictingCell |PolyLineTail]),NewCell):- [Left, RestrictingCell |PolyLineTail] = list::reverse(PolyLine), NewCell=juniourJudge::neighbourOutOfPolyLine_nd(Left,RestrictingCell). clauses announceWin():- humanInterface::announceWin(name). clauses announceLoss():- humanInterface::announceLoss(name). end implement computer /****************************************** Class HumanInterface ******************************************/ class humanInterface open core predicates announceStartUp:(). predicates showStage:(). showStep:(juniourJudge::cell,juniourJudge::stepType_D). getInput:(inputType_D,string StringParameter)->string InputString. getInput:(inputType_D)->string InputString. predicates announceManagerError:(choiceError_D). predicates announceStarter:(string Name). announceThinker:(string Name). announceWin:(string Name). announceLoss:(string Name). announceError:(string Description). announceError:(). domains choiceError_D= errorPlayerType_S; errorMustBeNumber_S; errorstartingPlayer_S. domains inputType_D= playerStep_S; playerType_S; playerName_S; startingPlayer_S. end class humanInterface implement humanInterface open core constants cellMarkedOrdinary_C="*". cellMarkedWinner_C="O". constants % messages thinker_C="% is thinking ...". beginner_C="First move done by: %". error_C="Error, % ". congratulation_C="Player % won!". sorryLoss_C="%, Sorry, you loss :-(". playerStep_C="Please enter your move as c(X,Y): ". playerType_C="\nPlayer #%s. Please enter the player type (1-human, 2-computer, Enter - end of choice):". playerName_C="\nPlease assign the name to the player (% proposed):". startingPlayer_C="\nWho moves the first (PlayerNo or Enter - end of the game)?:". errorPlayerType_C="\nNo such player type exists! Enter - repeat input:". errorMustBeNumber_C="\nMust be number! Please repeat input:". errorstartingPlayer_C="\nNo such Player exiasts! Please repeat input:". constants verticalSpace_C=2. horizontalSpace_C=3. emptyLineLenght_C=80. constants % Position of Line starterLine_C=1. announceLine_C=starterLine_C+1. actionLine_C=announceLine_C+1. polylineLine_C=actionLine_C+1. clauses getInput(InputType)=Input:- Input=getInput(InputType,""). getInput(InputType,StringParameter)=Input:- inputInvitation(InputType,StringParameter), Input = console::readLine(), console::clearInput(). class predicates inputInvitation:(inputType_D,string StringParameter). clauses inputInvitation(playerStep_S,_StringParameter):- clearMessageArea(actionLine_C), writeMessage(actionLine_C,"%",playerStep_C). inputInvitation(playerName_S,StringParameter):- console::writef(playerName_C,StringParameter). inputInvitation(playerType_S,StringParameter):- console::writef(playerType_C,StringParameter). inputInvitation(startingPlayer_S,StringParameter):- console::write(StringParameter,startingPlayer_C). clauses showStage():- console::clearOutput(), foreach I = std::fromTo(1, juniourJudge::maxColumn_P) do console::setLocation(console_native::coord(horizontalSpace_C*I, 0)), console::write(I) end foreach, foreach J = std::fromTo(1, juniourJudge::maxRow_P) do console::setLocation(console_native::coord(0, verticalSpace_C*J)), console::write(J) end foreach. clauses showStep(juniourJudge::c(X,Y),_Type):- console::setLocation(console_native::coord(horizontalSpace_C*X, verticalSpace_C*Y)), fail. showStep(_Cell,juniourJudge::ordinary_S):- console::write(cellMarkedOrdinary_C). showStep(_Cell,juniourJudge::winner_S):- console::write(cellMarkedWinner_C). clauses announceStartUp():- console::clearOutput(). clauses announceStarter(Name):- clearMessageArea(starterLine_C), writeMessage(starterLine_C,beginner_C,Name). clauses announceManagerError(errorPlayerType_S):- console::write(errorPlayerType_C), _=console::readLine(). announceManagerError(errorMustBeNumber_S):- console::write(errorMustBeNumber_C). announceManagerError(errorstartingPlayer_S):- console::write(errorstartingPlayer_C). clauses announceError():- announceError(""). announceError(ErrorText):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,error_C,ErrorText). clauses announceWin(Name):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,congratulation_C,Name), showPolyLine(), _ = console::readLine(). announceLoss(Name):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,sorryLoss_C,Name), showPolyLine(), _ = console::readLine(). clauses announceThinker(Name):- clearMessageArea(announceLine_C), clearMessageArea(actionLine_C), writeMessage(actionLine_C,thinker_C,Name). class predicates showPolyLine:(). clauses showPolyLine():- clearMessageArea(actionLine_C), writeMessage(polylineLine_C,"%",toString(juniourJudge::polyline_P)). class predicates clearMessageArea:(positive AreaID). clauses clearMessageArea(AreaID):- console::setLocation(console_native::coord(0,juniourJudge::maxRow_P*verticalSpace_C+AreaID)), console::write(string::create(emptyLineLenght_C," ")). class predicates writeMessage:(positive AreaID,string FormatString,string ParameterString). clauses writeMessage(AreaID,FormatString,ParameterString):- console::setLocation(console_native::coord(0, juniourJudge::maxRow_P*verticalSpace_C+AreaID)), console::writef(FormatString,ParameterString). end implement humanInterface