PNK

No preview image

1 collaborator

Uri_dolphin3 Uri Wilensky (Author)

Tags

(This model has yet to be categorized with any tags)
Model group CCL | Visible to everyone | Changeable by group members (CCL)
Model was written in NetLogo 4.1pre1 • Viewed 279 times • Downloaded 22 times • Run 0 times
Download the 'PNK' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


VERSION

$Id: PNK.nlogo 39722 2008-05-01 18:38:33Z everreau $

WHAT IS IT?

This model is a simple implementation of a "real-time strategy" type game. It is designed to teach NetLogo and be fun (in that order.) It is a strictly HubNet model. The idea is that students represent competing armies in the playing field. The goal is to capture all of the bases (by attacking them and thus winning them to your side.) The player can command three different types of units: pirates, knights, and ninjas. They have special attributes as follows:

Pirates are slow. However, when they attack, they damage all enemy units in range, not just the specific unit they are attacking.

Knights are medium speed. They are considered to be helpful knights, and thus automatically heal nearby friendly units.

Ninjas are very quick, but can't attack bases. They have ninja magic, however, that allows them to disappear and reappear at will. Other units can still attack invisible ninjas, but the user obviously doesn't know where they are.

More tradition RTS games are controlled by selecting a unit with the mouse and giving it commands. PKN is instead controlled by issuing NetLogo commands to each type of unit. Individual units are not selectable; strategies automatically apply to the entire unit type. (There are ways to programmatically command half of the pirates attack bases, for example, while the other half defends your own bases.) While a basic strategy requires no more NetLogo knowledge than using the provided attack-any and defend-any commands, more advanced strategies naturally require more advanced NetLogo mastery.

HOW IT WORKS

At each timestep, all of the units perform the actions stored in their "plan". While the simulation is running (or paused), the user can click one of the buttons to get a copy of that unit's current plan. The user can then modify the plan, and hit the done button to submit it back to the server. From then on, the user's units will perform the new plan. This allows the user to adopt a general strategy (attack the opponents' bases), but also react to current developments (defend your especially endangered base.) Once all of the units of a player are destroyed, that player is done. When only one player remains, the game is over.

HOW TO USE IT

To use this model, click the Start Server button and initialize the server. Now, click the Setup Phase button, and tell the users to join. During this time, no code is actually executed, but the users can modify the plans for their units. Once players are satisfied with their initial plans for attack, unclick the Setup Phase button, and click the Start Game button. The model will then be running, with each players' units acting appropriately. If there is an error in the code for a player, that breed of the player's doesn't move, and the error message is passed to the player. The player can then correct the code and resubmit to the server. If a player wishes to pause the game (to allow more measured strategizing and programming), the user can set their "ready-to-pause" switch to true. If all players have this set to true, the game will pause. It will remain paused until ALL players set their switch to off.

To capture a base (either a white neutral base or a colored enemy base), simply attack it like you would any other unit. When a base is conquered, it becomes owner by a random one of the attack units.

Note: Ninjas can't attack bases.

The attack-any and defend-any commands make sure you don't accidentally attack your own team or heal an enemy team. The attack and defend commands don't take care of this for you.

Similarly, the attack-any and defend-any attempt to target intentionally. (They will target the nearest available appropriate enemy and will switch targets when necessary) The attack and defend commands make no such promises.

THINGS TO TRY

Try to develop more complicated strategies. You can be especially devious with the ninjas.

EXTENDING THE MODEL

You can extend this model in a myriad number of ways.

For example, you could:

Add new units.

Add new base types.

Rewrite the production model.

Modify the attack-any, defend-any, etc. commands.

Add new attack styles.

Implement anti-cheating checks.

Remove the checks from attack-any and defend-any that take care of inappropriate targeting (attacking your own team, healing the other team.)

Show damage on units.

NETLOGO FEATURES

Because of a lack of structures in NetLogo, a "players" breed was used to act as a struct. This breed is never shown or really interacted with; it's just used to store information relevant to each player. This is definitely a hack.

A lot of the __make-* code is duplicated; some kind of OOP inheritance here would've been neat.

Sometimes the hubnet-exit-message was getting fired more than once for the same client, so I had to write a little extra code to deal with that.

The carefully command is used to execute each units' code; therefore, if there is an error, we can convey it to the user instead of crashing.

RELATED MODELS

This is related to an unpublished model that implemented a HubNet version of the Prisoner's Dilemma. I believe it was written by Andrei Scheinkman.

CREDITS AND REFERENCES

This model was designed by Nate Nichols for MAM, Fall '05.

Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

breed [ players player ]
breed [ knights knight ]
breed [ pirates pirate ]
breed [ bases base]
breed [ ninjas ninja ]
players-own [name plans last-used last-error ready-to-pause]
knights-own [owner plan health speed target targeted-by last-defended]
pirates-own [owner plan health speed target targeted-by last-defended]
ninjas-own [owner plan health speed target targeted-by last-defended]
bases-own [owner plan health targeted-by]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Functions beginning with __ are so named because otherwise they would sound like functions that would be called by players.
;;For purposes of game design and balance, these functions should not be called by players.

to __make-knight  ;;Base procedure
  hatch-knights 1
  [
    set owner [owner] of myself
    set color [color] of owner
    set speed knight-speed
    set health knight-attack-strength
    set target nobody
    set last-defended nobody
    set targeted-by []
    set size 2
  ]
end 

to __make-pirate ;;Base procedure
  hatch-pirates 1
  [
    set owner [owner] of myself
    set color [color] of owner
    set speed pirate-speed
    set health pirate-health
    set target nobody
    set last-defended nobody
    set targeted-by []
    set size 5
  ]
end 

to __make-ninja ;;Base procedure
  hatch-ninjas 1
  [
    set owner [owner] of myself
    set color [color] of owner
    set speed ninja-speed
    set health ninja-health
    set target nobody
    set last-defended nobody
    set targeted-by []
    set size 2
  ]
end 

to __target [targ] ;;Unit procedure
  if target != nobody [ask target [set targeted-by remove myself targeted-by]]
  set target targ
  ask target [set targeted-by lput myself targeted-by]
end 

to __attack ;;Unit procedure
  __move-towards-target
  if target != nobody
  [
    ifelse breed = knights
    [
      if distance target < knight-attack-range
      [
        ask target
        [
          set health health - knight-attack-strength
          ask turtles with [breed != players and color = [color] of myself]
          [
            set health health + knight-heal-amount
          ]
        ]
      ]
    ]
    [
      ifelse breed = pirates
      [
        if distance target < pirate-attack-range [ask turtles with [breed != players and color != [color] of myself] [set health health - pirate-attack-strength]]
      ]
      [
        if breed = ninjas
        [
          if not member? target bases with [color != [color] of myself] [if distance target < ninja-attack-range [ask target [set health health - ninja-attack-strength]]]
        ]
      ]
    ]
  ]
end 

to __move-towards-target ;;Unit procedure
  if target != nobody
  [
    ifelse distance target > [size] of target
    [
      set heading towards target + random (21) - 10
      fd min list speed distance target
    ]
    [
      setxy (xcor + (random-float .5) - .25) (ycor + (random-float .5) - .25)
      set heading towards target
    ]
  ]
end 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

to startup
  hubnet-set-client-interface "COMPUTER" []
end 

to setup
  ca
  set-default-shape bases "house"
  set-default-shape knights "sword"
  set-default-shape pirates "crossbones"
  set-default-shape ninjas "ninja-star"
  create-bases base-count
  [ ;These are initially neutral bases
    set owner self
    setxy random 150 random 150
    set color white
    set size 2
    set health 10
    set targeted-by []
  ]
end 

to-report load-file [filename]
  let ret ""
  file-open filename
  while [not file-at-end?]
  [
    set ret word ret file-read-line
    set ret word ret " \\n "
  ]
  file-close
  report ret
end 

to listen-clients
  while [ hubnet-message-waiting? ]
  [
    hubnet-fetch-message
    ifelse hubnet-enter-message?
    [ create-new-student ]
    [
      ifelse hubnet-exit-message?
      [ remove-student ]
      [ execute-command hubnet-message-tag ]
    ]
  ]
end 

to create-new-student
  create-players 1
  [
    set name hubnet-message-source
    set plans (list "move-random" )
    set plans lput "produce-knights" plans
    set plans lput "move-random" plans
    set plans lput "move-random" plans
    set color (count players - 1) * 10 + 5
    set ready-to-pause false
    hubnet-send name "your-color" color
    set last-error ""
    hatch-bases 1
    [
      set owner myself
      setxy random 150 random 150
      set color [color] of owner
      set size 2
      set health 10
      set targeted-by []
    ]
    ht
  ]
end 

to remove-student
  let leaving-player lookup-player hubnet-message-source
  if leaving-player != nobody
  [
    ask leaving-player
    [
      ask turtles with [breed != players and owner = myself] [die]
      die
    ]
  ]
end 

to-report lookup-player [player-name]
  let player nobody
  ask players
  [
    if name = player-name [set player self]
  ]
  report player
end 

to-report atoi [brd]
  if brd = "knights" or brd = knights [report 0]
  if brd = "bases" or brd = bases [report 1]
  if brd = "pirates" or brd = pirates [report 2]
  if brd = "ninjas" or brd = ninjas [report 3]
end 

to go
  listen-clients
  do-plans
  fix-turtles
  update-counts
  if not any? players with [not ready-to-pause]
  [
    while [any? players with [ready-to-pause]]
    [
      listen-clients
      wait 1
    ]
  ]
end 

to fix-turtles
  ask turtles with [breed != players and breed != bases and health < 0]
  [
    if target != nobody 
    [
      ask target
      [  set targeted-by remove myself targeted-by ]
    ]
    foreach targeted-by [ask ? [set target nobody]]
    die
  ]
  ask bases with [health < 0]
  [
    let killer one-of targeted-by
    hatch-bases 1
    [
      set owner [owner] of killer
      set color [color] of owner
      set size 2
      set health base-health
      set targeted-by []
    ]
    foreach targeted-by [ask ? [set target nobody]]
    die
  ]
end 

to execute-command [comm]
    ifelse hubnet-message-tag = "comm"
    [
      ask lookup-player hubnet-message-source [set plans replace-item atoi last-used plans hubnet-message]
    ]
    [
      ifelse hubnet-message-tag = "ready-to-pause"
      [
        ifelse hubnet-message
        [
          ask lookup-player hubnet-message-source [set ready-to-pause true]
        ]
        [
          ask lookup-player hubnet-message-source [set ready-to-pause false]
        ]
      ]
      [
        let msg ""
        ask lookup-player hubnet-message-source [set msg item atoi hubnet-message-tag plans set last-used hubnet-message-tag]
        hubnet-send hubnet-message-source "comm" msg
      ]
    ]
end 

to do-plans
  ask players
  [
    carefully
    [
      ask turtles with [breed != players and owner = myself]
      [
        run item atoi breed [plans] of owner
      ]
    ]
    [
      hubnet-send name "error-message" error-message
    ]
  ]
end 

to update-counts
  ask players
  [
    hubnet-send name "base-count" count bases with [owner = myself]
    hubnet-send name "knight-count" count knights with [owner = myself]
    hubnet-send name "pirate-count" count pirates with [owner = myself]
    hubnet-send name "ninja-count" count ninjas with [owner = myself]
  ]
end 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;These functions are provided for players.

to move-random
  rt random (30) - 15
  fd speed
end 

to produce-knights
  if random knight-produce-chance = 0 [__make-knight ]
end 

to produce-pirates
  if random pirate-produce-chance = 0 [ __make-pirate]
end 

to produce-ninjas
  if random ninja-produce-chance = 0 [__make-ninja]
end 

to attack [new-target]
  __target new-target
  __attack
end 

to attack-any [target-type]
  if target = nobody or not member? target target-type ;If old target isn't a member of new target, change target
  [
    ifelse any? target-type with [ color != [color] of myself]
    [ __target min-one-of target-type with [ color != [color] of myself] [distance myself] ]
    [set target nobody]
  ]
  __attack
end 

to defend [the-vic]
  ifelse length [targeted-by] of the-vic > 0
  [attack one-of [targeted-by] of the-vic]
  [set target nobody]
end 

to defend-any [vic-type]
  let defense-targets vic-type with [color = [color] of myself]
  if any? defense-targets
  [
    attack-any turtles with [breed != players and breed != bases and color != [color] of myself and target != nobody and member? target defense-targets]
  ]
end 

to ninja-hide
  if breed = ninjas [ht]
end 

to ninja-show
  if breed = ninjas [st]
end 

There are 2 versions of this model.

Uploaded by When Description Download
Uri Wilensky over 14 years ago PNK Download this version
Uri Wilensky over 14 years ago PNK Download this version

Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.