Early chess programs did not have a resignation facility; a program losing a game played until mate or until its operator resigned on its behalf. I believe that Belle by Ken Thompson was the first program to be able to resign on its own and it would throw in the towel after it saw it was a Rook (or equivalent) down.
Some programs like Crafty have a more sophisticated resignation mechanism that takes into account the opponent's rating/title, the amount of time remaining on the clock, and the current expectation. It would be possible to add other factors such as the stage of the game, whether or not tablebases were available, and perhaps how much time had already been spent playing to hopes of wearing down a human opponent.
Symbolic has had its resignation facility changed several times. One component that it has always had is to resign if the opponent would have a mate-in-one move after a search; so the program has never been checkmated. Unlike Crafty, Symbolic does not do any opponent modelling when determining when to resign; as the phrase goes, it plays the board and not the man. This may at times result in a premature resignation, but I have chosen this route because it makes it easier to compare games against different opponents. Likewise, Symbolic has no provision for an opponent specific contempt factor.
Symbolic has a C++ class CTDRTrack (Draw/Resign tracker), and a single instance of this class is used by the command processor in use (e.g., the xboard interface) to determine when to offer/accept draws or to resign. The instance keeps track of the last N search result scores (currently N=5); only those results that have real scores are retained. Searches that return book moves or only one move available are not tracked. If the tracker sees N scores in a row such that 1) the first score is below the resignation threshold (currrently six pawns) and that 2) each successor score is lower than its prior score, then the command processor will issue a resignation.
The above seems to work okay. It helps a lot in endgames when the tablebases indicate a long loss by determining if the opponent has sufficient endgame knowledge to win.
The idea of a score tracker can be useful in other ways. For example, it could also be used to politely suggest that an opponent should resign when the score is high and steadily increasing. If chess had a doubling cube like backgammon, a score tracker could determine when to double or when to give up after the opponent doubled. Another example would be to use the tracker to modify the nominal search time allocation, increasing allocation when the program was getting into a downward slide or decreasing it when the opponent was starting to get into trouble.
For programmers: how does your program determine when to resign?