Hi all,
Back when I was younger, I used to enjoy the “Fighting Fantasy” books, which were similar to Dungeons & Dragons but much simpler, and you didn’t need a bunch of people to play them. The book itself acted as the “game master”, giving you certain options and choices and dictating the results. A set of dice and you were all set to play!
I’ve played around with making these games into a program, and I experimented in the day with various versions of BASIC, and now I’m contemplating trying again, but this time in Applescript.
There are some problems, of course, and first and foremost is that quite often the game requires a set of more than two or three options (e.g. go east, west, north, check your map, open your inventory, etc.)
So I was thinking of a separate routine for menu options that would present two options and then a button for “more”:
set current_room_description to "You have entered a large room clutterd with broken furniture, chests and other junk. There are doors in the east and west walls as well as an alcove of some sort in the northern wall that your torchlight cannot reach."
set current_room_menu to {"Carefully search the room", "Investigate the alcove", "Open east door", "Open west door", "Inventory"}
Multimenu(current_room_description, current_room_menu)
on Multimenu(menuquery, menuopts)
set totalopts to count of items in menuopts
set good_selection to 0
set current_counter to 1
repeat until good_selection is 1
set out_buttons to {}
repeat 2 times
if current_counter is less than or equal to totalopts then
set out_buttons to out_buttons & item current_counter of menuopts
set current_counter to 1 + current_counter
else
set current_counter to 2
set out_buttons to out_buttons & item 1 of menuopts
end if
end repeat
set out_buttons to out_buttons & "More"
set askbutton to button returned of (display dialog menuquery buttons out_buttons)
if askbutton is not "More" then
set good_selection to 1
end if
end repeat
return askbutton
end Multimenu
Anyone have any suggestions or ideas on how to handle that better? I suppose an alternative would be to number all the room’s options and then use a "default answer " display dialog handler (e.g. 1-East, 2-West, 3-North, 4-Check Map, etc) but I think I like the idea of clicking buttons instead.
I was also testing out some of the in-game subroutines I’d need, and I put together a little test involving character creation, inventory management and even a very, very simple combat routine:
--generate a silly character name
set lb to ASCII character 13
set fname_1 to {"Ar", "Beor", "Car", "Dyn", "El", "Fri", "Grey", "Har", "Imo", "Jar", "Kero", "Leo", "Mith", "Ner", "Oli", "Pere", "Qui", "Ran", "Sta", "Tyn", "Ung", "Vell", "Will", "Xeren", "Yogr", "Zar"}
set fname_2 to {"tan", "ni", "vel", "ex", "han", "tz", "gryn", "hiel", "iel", "jan", "kael", "le", "min", "mer", "ox", "per", "qaen", "rill", "sten", "tire", "uller", "ven", "wiel", "xer", "yen", "zen"}
set fname_3 to {"is", "gar", "lis", "ta", "a", "lieb", "ght", "ho", "is", "je", "kle", "le", "mas", "ne", "ont", "pt", "quer", "rse", "st", "th", "un", "ve", "way", "xit", "yar", "zerg"}
set lname_1 to {"Aggor", "Blue", "Cray", "Deer", "Elk", "Fox", "Grey", "High", "Ire", "Jay", "Kill", "Lark", "May", "Nix", "Old", "Pipe", "Quiet", "Red", "Sand", "Tiger", "Under", "Vile", "White", "Xeen", "Yellow", "Zip"}
set lname_2 to {"arm", "black", "creek", "death", "end", "fang", "grim", "hand", "iron", "jack", "king", "land", "man", "nose", "ogre", "piper", "qualm", "rain", "snow", "throat", "uller", "vein", "wrath", "xing", "young", "zone"}
set random1 to (random number from 1 to 26)
set random2 to (random number from 1 to 26)
set random3 to (random number from 1 to 26)
set random4 to (random number from 1 to 26)
set random5 to (random number from 1 to 26)
set random6 to (random number from 1 to 2)
set firstname to text item random1 of fname_1
if random6 is 1 then
set firstname to firstname & text item random2 of fname_2
end if
set firstname to firstname & text item random3 of fname_3
set lastname to text item random4 of lname_1
set lastname to lastname & text item random5 of lname_2
set default_name to firstname & " " & lastname
set query_name to display dialog "What name shall ye be known as?" default answer default_name
set character_name to text returned of query_name
--generate the character's statistics
set stam_roll to random number from 2 to 12
set stamina to 12 + stam_roll
set luck_roll to random number from 1 to 6
set luck to 6 + luck_roll
set skill_roll to random number from 1 to 6
set skill to 6 + skill_roll
set Charinfo to character_name & lb & lb & "Stamina: " & stamina & lb & " Skill: " & skill & lb & " Luck: " & luck
display dialog Charinfo
global skill, luck, lb
global stamina
set inventory to {"Rations", 10, "Sword", 1, "Black Pearl", 5, "Potion of Strength", 1}
global inventory
--Check routine to add item
AddtoInventory("Rations", 5)
--Check routine to remove item
RemoveFromInventory("Black Pearl", 2)
--now let's display the inventory
DisplayInventory()
--how about some combat.
singleCombat("a Rat", 7, 7)
singleCombat("an Orc", 10, 6)
on DisplayInventory()
set itc to -1
set Inventory_output to "Inventory:" & lb & lb
repeat ((count of text items in inventory) / 2) times
set itc to 2 + itc
set Inventory_output to Inventory_output & text item itc of inventory
if ((text item (itc + 1) of inventory) as number) is greater than 1 then
set Inventory_output to Inventory_output & " (" & text item (itc + 1) of inventory & ")"
end if
set Inventory_output to Inventory_output & (ASCII character 13)
end repeat
display dialog Inventory_output
end DisplayInventory
on AddtoInventory(AddItem, AddQuantity)
set itc to -1
set already_flag to 0
repeat ((count of text items in inventory) / 2) times
set itc to 2 + itc
if text item itc of inventory is AddItem then
set new_counter to (text item (itc + 1) of inventory) as number
set new_counter to AddQuantity + new_counter
set text item (1 + itc) of inventory to new_counter
set already_flag to 1
end if
end repeat
if already_flag is 0 then
set inventory to inventory & AddItem
set inventory to inventory & AddQuantity
end if
end AddtoInventory
on RemoveFromInventory(RemoveItem, RemoveQuantity)
set new_inventory to {""}
set itc to -1
repeat ((count of text items in inventory) / 2) times
set keep_in_inventory to 1
set itc to 2 + itc
if text item itc of inventory is RemoveItem then
set new_counter to (text item (itc + 1) of inventory) as number
set final_counter to new_counter - RemoveQuantity
set text item (1 + itc) of inventory to final_counter
if final_counter is less than or equal to 0 then
set keep_in_inventory to 0
end if
end if
if keep_in_inventory is 1 then
set new_inventory to new_inventory & text item itc of inventory
set new_inventory to new_inventory & text item (itc + 1) of inventory
end if
end repeat
set inventory to ""
set inventory to items 2 thru (count of items in new_inventory) of new_inventory
end RemoveFromInventory
on singleCombat(Monster, monster_skill, monster_health)
set attack_message to Monster & " draws near." & (ASCII character 13) & "(Skill:" & monster_skill & ", Stamina:" & monster_health & ")"
display dialog attack_message
set combat_flag to 0
repeat until combat_flag is 1
set pc_roll to random number from 2 to 12
set monster_roll to random number from 2 to 12
set pc_attack to pc_roll + skill
set monster_attack to monster_roll + monster_skill
if pc_attack is greater than monster_attack then
set monster_health to monster_health - 2
if monster_health is less than or equal to 0 then
set combat_flag to 1
display dialog "You killed " & Monster & "!"
else
display dialog Monster & " was hit (" & monster_health & " health remaining)"
end if
end if
if monster_attack is greater than pc_attack then
set stamina to stamina - 2
if stamina is less than or equal to 0 then
set combat_flag to 1
display dialog "You were killed by " & Monster & "."
else
display dialog "You were hit. (" & stamina & " health remaining)"
end if
end if
end repeat
end singleCombat
There are some things that need work, though, of course, and the whole thing needs to be put together, so that’s something I’ll be working on. Also I need to go through the books and figure out which other routines would need to be added – specific checks if there is an item in inventory, for instance, or adding specific character flags for certain events, and so on.
I’d love to hear some feedback or ideas from other people!
Oh, and I know that this could be done differently and more efficiently in Studio or Xcode but I’m kind of interested in keeping it entirely in Applescript – just to see if it can be done!