Difference between revisions of "Tutorial Project. Release 4"
From wiki.visual-prolog.com
m |
m |
||
Line 18: | Line 18: | ||
*Create the new project with the User Interface strategy Console | *Create the new project with the User Interface strategy Console | ||
*In the created project replace the entire content of the file "main.pro" by the code shown below | *In the created project replace the entire content of the file "main.pro" by the code shown below | ||
*While building the project answer "Add All", when any dialog with proposals to include any packages to the project appears | *While building the project answer "Add All", when any dialog with proposals to include any packages to the project appears | ||
Revision as of 22:29, 4 June 2010
Written by Victor Yukhtenko. Email: victor@pdc.spb.su
This program is part of the Tutorial Project Evolutions article.
Game description
- The game is played on an M x N board.
Game rules
- Each player on his turn adds a new point. The point must prolong the existing Polyline (or start the Polyline, if it doesn't exist).
- The resulting Polyline must be non-interrupted and each move can be taken in any of end of the line.
- The player, which locks the line (the point is set on the polyline), wins.
The size of the board in the code is set 6x6 It is not recommended to set the size of the board more than 36 points (say 6 x 6) due to the inefficient algorithm used |
The strategy of the computer behaviour adopted from the Tutorial Project. Release 1 (written by Elena Efimova).
Differences (relative to version 3):
- If no successful move found, then the next move is random
- The structure of the class computer modified dramatically
To run the game please make the steps as follows:
- Create the new project with the User Interface strategy Console
- In the created project replace the entire content of the file "main.pro" by the code shown below
- While building the project answer "Add All", when any dialog with proposals to include any packages to the project appears
/************************************************************ Copyright (c) 2007-2010 Victor Yukhtenko Tested with Vip7.3 SpbSolutions/Examples/Polyline Predicates, which represent the strategy neighbour_nd, neighbourOutOfPolyLine_nd, resolveStep, successfulStep, stepCandidate based on solutions proposed by Elena Efimova Written by: Victor Yukhtenko ************************************************************/ 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 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 end class computer implement computer inherits genericComputer end implement computer /****************************************** Class genericComputer ******************************************/ interface genericComputer supports player supports polyLineBrain end interface genericComputer class genericComputer:genericComputer open core, exception end class genericComputer implement genericComputer inherits polyLineBrain1 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:- Cell=randomStep(), !. resolveStep()=juniourJudge::c(X+1,Y+1):- X=math::random(juniourJudge::maxColumn_P-1), Y=math::random(juniourJudge::maxRow_P-1). 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 genericComputer /****************************************** Interface polylineBrain ******************************************/ interface polylineBrain open core constants notDefinedPredicate_C="The predicate is not defined. Must be defined in the daughter class. ". predicates stepCandidate: (juniourJudge::cell*,juniourJudge::cell* [out],juniourJudge::cell [out]) nondeterm. successfulStep: (juniourJudge::cell*)->juniourJudge::cell nondeterm. randomStep:()->juniourJudge::cell determ. end interface polyLineBrain /****************************************** Class polylineBrain1 ******************************************/ class polyLineBrain1:polyLineBrain open core predicates classInfo : core::classInfo. end class polyLineBrain1 implement polyLineBrain1 open core, exception constants className = "polyLineBrain1". classVersion = "1.0". clauses classInfo(className, classVersion). clauses successfulStep(PolyLine)=BestMove:- This:stepCandidate(PolyLine, _PolyLine1,BestMove), list::isMember(BestMove, PolyLine), !. successfulStep(PolyLine)=Cell:- This:stepCandidate(PolyLine, PolyLine1,Cell), not(_=successfulStep(PolyLine1)). clauses randomStep()=Cell:- findAll(NewCell,This:stepCandidate(juniourJudge::polyline_P,_Polyline1, NewCell),CellCandidateListWithDuplicates), CellCandidateList=list::removeDuplicates(CellCandidateListWithDuplicates), not(CellCandidateList=[]), NoOfVariants=list::length(CellCandidateList), ChoiceNo=math::random(NoOfVariants-1), Cell=list::nth(ChoiceNo+1,CellCandidateList). clauses stepCandidate(_Cell,_PolyLine,_Move):- common_exception::raise_error(classinfo,predicate_name(),notDefinedPredicate_C). end implement polylineBrain1 /****************************************** 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; searchDepth_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)?:". searchDepth_C="\nDefine the depth of the search (% - by default)?? ". 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). inputInvitation(searchDepth_S,StringParameter):- console::writef(searchDepth_C,StringParameter). 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